diff --git a/CVCncLib/CVCncLib.dll b/CVCncLib/CVCncLib.dll
index fa1d7911..77ac5221 100644
Binary files a/CVCncLib/CVCncLib.dll and b/CVCncLib/CVCncLib.dll differ
diff --git a/IOB-UT-NEXT/Enums.cs b/IOB-UT-NEXT/Enums.cs
index 095afc33..99e1da4b 100644
--- a/IOB-UT-NEXT/Enums.cs
+++ b/IOB-UT-NEXT/Enums.cs
@@ -270,10 +270,15 @@ namespace IOB_UT_NEXT
ND,
///
- /// Adapter ModBus TCP
+ /// Adapter ModBus TCP generico
///
MODBUS_TCP,
+ ///
+ /// Adapter ModBus TCP versione HAM (Pizzaferri)
+ ///
+ MODBUS_TCP_HAM,
+
///
/// Adapter MTConnect
///
diff --git a/IOB-UT-NEXT/IOB-UT-NEXT.csproj b/IOB-UT-NEXT/IOB-UT-NEXT.csproj
index 663002a2..e727dce1 100644
--- a/IOB-UT-NEXT/IOB-UT-NEXT.csproj
+++ b/IOB-UT-NEXT/IOB-UT-NEXT.csproj
@@ -59,8 +59,8 @@
..\packages\SharpZipLib.1.3.1\lib\net45\ICSharpCode.SharpZipLib.dll
-
- ..\packages\MapoSDK.6.13.2105.1421\lib\net40\MapoSDK.dll
+
+ ..\packages\MapoSDK.6.13.2109.1112\lib\net40\MapoSDK.dll
..\packages\Microsoft.Bcl.AsyncInterfaces.5.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll
diff --git a/IOB-UT-NEXT/ToMapo.cs b/IOB-UT-NEXT/ToMapo.cs
index 7a318db4..6b391f1a 100644
--- a/IOB-UT-NEXT/ToMapo.cs
+++ b/IOB-UT-NEXT/ToMapo.cs
@@ -188,25 +188,18 @@ namespace IOB_UT_NEXT
#endregion Public Methods
}
+#if false
///
/// Struttura della conf memoria ModBus
///
public class BaseModbusConf
{
- #region Public Enums
-
public enum DataType
{
ND = 0,
- Bit,
- Int,
- Real
- }
-
- public enum MemDirection
- {
- R,
- W
+ BIT,
+ INT,
+ REAL
}
public enum MemType
@@ -218,53 +211,58 @@ namespace IOB_UT_NEXT
HoldingRegister = 4
}
- #endregion Public Enums
-
- #region Public Properties
+ ///
+ /// Elenco aree memoria ModBus in lettura
+ ///
+ public List mMapRead { get; set; } = new List();
///
- /// Elenco aree memoria mobdus
+ /// Elenco aree memoria ModBus in scrittura
///
- public List MemoryList { get; set; } = new List();
-
- #endregion Public Properties
-
- #region Public Classes
+ public List mMapWrite { get; set; } = new List();
///
/// struttura di base memoria ModBus
///
public class ModbusMemArea
{
- #region Public Properties
-
public ushort BaseAddr { get; set; } = 0;
public string RawAddr { get; set; } = "";
- public ushort Size { get; set; } = 2;
+ public ushort Size { get; set; } = 0;
+
+ [JsonConverter(typeof(StringEnumConverter))]
public MemType Type { get; set; } = MemType.ND;
public List VarList { get; set; } = new List();
-
- #endregion Public Properties
}
public class VarConf
{
- #region Public Properties
+ public string description { get; set; } = "";
+ public int factor { get; set; } = 1;
- public MemDirection Direction { get; set; } = MemDirection.R;
- public ushort MemAddr { get; set; } = 0;
- public string Name { get; set; } = "ND";
- public int RangeMax { get; set; } = 0;
- public int RangeMin { get; set; } = 0;
- public ushort Size { get; set; } = 2;
- public DataType Type { get; set; } = DataType.ND;
+ public bool hasRange
+ {
+ get
+ {
+ return !this.minVal.Equals(this.maxVal);
+ }
+ }
- #endregion Public Properties
+ public ushort index { get; set; } = 0;
+ public int maxVal { get; set; } = 0;
+ public string memAddr { get; set; } = "";
+ public int minVal { get; set; } = 0;
+ public string name { get; set; } = "none";
+ public ushort size { get; set; } = 0;
+
+ [JsonConverter(typeof(StringEnumConverter))]
+ public DataType tipoMem { get; set; } = DataType.ND;
+
+ public string value { get; set; } = "";
}
-
- #endregion Public Classes
}
+#endif
///
/// Classe gestione configurazione parametri di base x configuraizone estesa (es MTConnect, OPC-UA, ...)
diff --git a/IOB-UT-NEXT/packages.config b/IOB-UT-NEXT/packages.config
index 70c5455c..3ad1f452 100644
--- a/IOB-UT-NEXT/packages.config
+++ b/IOB-UT-NEXT/packages.config
@@ -1,6 +1,6 @@

-
+
diff --git a/IOB-WIN-NEXT/AdapterForm.cs b/IOB-WIN-NEXT/AdapterForm.cs
index 9445b21a..4af037c8 100644
--- a/IOB-WIN-NEXT/AdapterForm.cs
+++ b/IOB-WIN-NEXT/AdapterForm.cs
@@ -1191,6 +1191,11 @@ namespace IOB_WIN_NEXT
start.Enabled = true;
break;
+ case tipoAdapter.MODBUS_TCP_HAM:
+ iobObj = new IobModbusTCPHam(this, IOBConf);
+ start.Enabled = true;
+ break;
+
case tipoAdapter.MTConnect:
iobObj = new IobMTC(this, IOBConf);
start.Enabled = true;
diff --git a/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini b/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini
index 04480fbe..b2c6e223 100644
--- a/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini
+++ b/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini
@@ -1,7 +1,7 @@
;Configurazione IOB-WIN
[IOB]
-;Impianto COMECA per Pizzaferri
-CNCTYPE=MODBUS_TCP
+;Impianto HAM per Pizzaferri
+CNCTYPE=MODBUS_TCP_HAM
PING_MS_TIMEOUT=500
[MACHINE]
@@ -11,9 +11,6 @@ MODEL=HAM
[CNC]
IP=hampizzaferri.dyndns.org
PORT=502
-;CPUTYPE=S71500
-;RACK=0
-;SLOT=0
[SERVER]
;MPIP=https://localhost:44339
@@ -27,10 +24,11 @@ CMDADV1=?valore=
CMDREBO=/IOB/sendReboot?idxMacchina=
[MEMORY]
-ADDR_READ=DB85.DBB0
-ADDR_WRITE=DB85.DBB280
-SIZE_READ=280
-SIZE_WRITE=32
+ADDR_READ=40001
+ADDR_WRITE=40401
+SIZE_READ=34
+;SIZE_READ=5046
+SIZE_WRITE=358
[BLINK]
@@ -50,7 +48,7 @@ BLINK_FILT=0
[OPTPAR]
;PZCOUNT_MODE=STD.[PAR/MEM].info|BIT.indice
PZCOUNT_MODE=STD.DB85.DBRE16
-DISABLE_PZCOUNT=FALSE
+DISABLE_PZCOUNT=TRUE
ENABLE_SEND_PZC_BLOCK=TRUE
MIN_SEND_PZC_BLOCK=0
MAX_SEND_PZC_BLOCK=100
@@ -59,14 +57,14 @@ ENABLE_DYN_DATA=TRUE
FORCE_DYN_DATA=TRUE
; clock base (da 10ms)
-timerIntMs=20
+timerIntMs=100
; conf parametri memoria READ/WRITE
-PARAM_CONF=PIZ03.json
+PARAM_CONF=PIZ04.json
-NO_PING=TRUE
+NO_PING=FALSE
; conf aree allarme
-ALARM_CONF=PIZ03_alarm.json
+ALARM_CONF=PIZ04_alarm.json
[BRANCH]
NAME=master
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/DATA/CONF/PIZ04.json b/IOB-WIN-NEXT/DATA/CONF/PIZ04.json
index a28052db..4889aa31 100644
--- a/IOB-WIN-NEXT/DATA/CONF/PIZ04.json
+++ b/IOB-WIN-NEXT/DATA/CONF/PIZ04.json
@@ -1,247 +1,255 @@
{
- "mMapWrite": {
- "setProg": {
- "name": "setProg",
- "description": "Programma",
- "tipoMem": "String",
- "memAddr": "DB6.DBB50",
- "index": 50,
- "size": 50
- },
- "setComm": {
- "name": "setComm",
- "description": "Commessa",
- "tipoMem": "String",
- "memAddr": "DB6.DBB0",
- "index": 0,
- "size": 50
- },
- "setArt": {
- "name": "setArt",
- "description": "Articolo",
- "tipoMem": "String",
- "memAddr": "DB6.DBB100",
- "index": 100,
- "size": 50
- },
- "setPzComm": {
- "name": "setPzComm",
- "description": "Qty",
- "memAddr": "DB30.DBB212",
- "tipoMem": "DInt",
- "index": 212,
- "size": 4
- }
- },
+ //"mMapWrite": {
+ // "setProg": {
+ // "name": "setProg",
+ // "description": "Programma",
+ // "tipoMem": "String",
+ // "memAddr": "DB6.DBB50",
+ // "index": 50,
+ // "size": 50
+ // },
+ // "setComm": {
+ // "name": "setComm",
+ // "description": "Commessa",
+ // "tipoMem": "String",
+ // "memAddr": "DB6.DBB0",
+ // "index": 0,
+ // "size": 50
+ // },
+ // "setArt": {
+ // "name": "setArt",
+ // "description": "Articolo",
+ // "tipoMem": "String",
+ // "memAddr": "DB6.DBB100",
+ // "index": 100,
+ // "size": 50
+ // },
+ // "setPzComm": {
+ // "name": "setPzComm",
+ // "description": "Qty",
+ // "memAddr": "DB30.DBB212",
+ // "tipoMem": "DInt",
+ // "index": 212,
+ // "size": 4
+ // }
+ //},
"mMapRead": {
- "TE2A": {
- "name": "TE2A",
- "description": "Temperatura Controllo Tenute Pompa A",
- "memAddr": "DB85.DBB0",
- "tipoMem": "Real",
- "index": 0,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
- "TE1A": {
- "name": "TE1A",
- "description": "Temperatura Raffreddamento Pompa A",
- "memAddr": "DB85.DBB4",
- "tipoMem": "Real",
- "index": 4,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
- "TE3A": {
- "name": "TE3A",
- "description": "Temperatura Cavitazione Pompa A",
- "memAddr": "DB85.DBB8",
- "tipoMem": "Real",
- "index": 8,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
- "Temp01": {
- "name": "TE04",
- "description": "Temperatura Torcia Aria Fredda",
- "memAddr": "DB85.DBB12",
- "tipoMem": "Real",
- "index": 12,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
"Level": {
- "name": "LT15",
+ "name": "GiacSerb",
"description": "Livello Serbatoio",
- "memAddr": "DB85.DBB16",
+ "memAddr": "40001",
"tipoMem": "Real",
- "index": 16,
- "size": 4,
+ "index": 1,
+ "size": 2,
"func": "MAX",
"period": 60,
- "factor": 1
- },
- "PressBH": {
- "name": "PT01",
- "description": "Pressione Linea CNG",
- "memAddr": "DB85.DBB20",
- "tipoMem": "Real",
- "index": 20,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
- "PressBL": {
- "name": "PT100",
- "description": "Pressione Riduttrice",
- "memAddr": "DB85.DBB24",
- "tipoMem": "Real",
- "index": 24,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
+ "factor": 280,
+ "minVal": 0,
+ "maxVal": 100
},
"MainPress": {
- "name": "PT16",
+ "name": "PressSerb",
"description": "Pressione Serbatoio",
- "memAddr": "DB85.DBB28",
+ "memAddr": "40003",
"tipoMem": "Real",
- "index": 28,
- "size": 4,
+ "index": 3,
+ "size": 2,
"func": "MAX",
"period": 60,
- "factor": 1
+ "factor": 1,
+ "minVal": 0,
+ "maxVal": 25
},
- "Temp02": {
- "name": "TT17",
- "description": "Temperatura Spurgo Torcia Serbatoio",
- "memAddr": "DB85.DBB36",
+ "PressBH": {
+ "name": "PBH",
+ "description": "Pressione media all’interno dell’accumulo GNC (pacco bombole) di alta pressione",
+ "memAddr": "40019",
"tipoMem": "Real",
- "index": 36,
- "size": 4,
+ "index": 19,
+ "size": 2,
"func": "MAX",
"period": 60,
- "factor": 1
+ "factor": 1,
+ "minVal": 0,
+ "maxVal": 400
},
- "TE06": {
- "name": "TE06",
- "description": "Temperatura Uscita Vaporizzatore",
- "memAddr": "DB85.DBB40",
+ "PressBL": {
+ "name": "PBM",
+ "description": "Pressione media all’interno dell’accumulo GNC (pacco bombole) di media pressione",
+ "memAddr": "40021",
"tipoMem": "Real",
- "index": 40,
- "size": 4,
+ "index": 21,
+ "size": 2,
"func": "MAX",
"period": 60,
- "factor": 1
+ "factor": 1,
+ "minVal": 0,
+ "maxVal": 400
},
- "TE05": {
- "name": "TE05",
- "description": "Temperatura Carica Fredda",
- "memAddr": "DB85.DBB60",
- "tipoMem": "Real",
- "index": 60,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
- "TE2B ": {
- "name": "TE2B",
- "description": "Temperatura Controllo Tenute Pompa B",
- "memAddr": "DB85.DBB64",
- "tipoMem": "Real",
- "index": 64,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
- "TE1B ": {
- "name": "TE1B",
- "description": "Temperatura Raffreddamento Pompa B",
- "memAddr": "DB85.DBB68",
- "tipoMem": "Real",
- "index": 68,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
- "TE3B": {
- "name": "TE3B",
- "description": "Temperatura Cavitazione Pompa B",
- "memAddr": "DB85.DBB72",
- "tipoMem": "Real",
- "index": 72,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
- "PressH": {
- "name": "PT300A",
- "description": "Alta Pressione",
- "memAddr": "DB85.DBB120",
- "tipoMem": "Real",
- "index": 120,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
- "PressM": {
- "name": "PT300M",
- "description": "Media Pressione",
- "memAddr": "DB85.DBB124",
- "tipoMem": "Real",
- "index": 124,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
- "LivelloPerc": {
- "name": "LT15%",
- "description": "Livello Serbatorio %",
- "memAddr": "DB85.DBB148",
- "tipoMem": "Real",
- "index": 148,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
- "MinTemp01": {
- "name": "MinTempTE04",
- "description": "Minima Temperatura Linea Sfiato Gas TE04",
- "memAddr": "DB85.DBB152",
- "tipoMem": "Real",
- "index": 152,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- },
- "MinTemp02": {
- "name": "MinTempTT17",
- "description": "Minima Temperatura Linea Sfiato Gas Torcia Serbatoio TT17",
- "memAddr": "DB85.DBB156",
- "tipoMem": "Real",
- "index": 156,
- "size": 4,
- "func": "MAX",
- "period": 60,
- "factor": 1
- }
+ //"TE2A": {
+ // "name": "TE2A",
+ // "description": "Temperatura Controllo Tenute Pompa A",
+ // "memAddr": "DB85.DBB0",
+ // "tipoMem": "Real",
+ // "index": 0,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"TE1A": {
+ // "name": "TE1A",
+ // "description": "Temperatura Raffreddamento Pompa A",
+ // "memAddr": "DB85.DBB4",
+ // "tipoMem": "Real",
+ // "index": 4,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"TE3A": {
+ // "name": "TE3A",
+ // "description": "Temperatura Cavitazione Pompa A",
+ // "memAddr": "DB85.DBB8",
+ // "tipoMem": "Real",
+ // "index": 8,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"Temp01": {
+ // "name": "TE04",
+ // "description": "Temperatura Torcia Aria Fredda",
+ // "memAddr": "DB85.DBB12",
+ // "tipoMem": "Real",
+ // "index": 12,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"Temp02": {
+ // "name": "TT17",
+ // "description": "Temperatura Spurgo Torcia Serbatoio",
+ // "memAddr": "DB85.DBB36",
+ // "tipoMem": "Real",
+ // "index": 36,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"TE06": {
+ // "name": "TE06",
+ // "description": "Temperatura Uscita Vaporizzatore",
+ // "memAddr": "DB85.DBB40",
+ // "tipoMem": "Real",
+ // "index": 40,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"TE05": {
+ // "name": "TE05",
+ // "description": "Temperatura Carica Fredda",
+ // "memAddr": "DB85.DBB60",
+ // "tipoMem": "Real",
+ // "index": 60,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"TE2B ": {
+ // "name": "TE2B",
+ // "description": "Temperatura Controllo Tenute Pompa B",
+ // "memAddr": "DB85.DBB64",
+ // "tipoMem": "Real",
+ // "index": 64,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"TE1B ": {
+ // "name": "TE1B",
+ // "description": "Temperatura Raffreddamento Pompa B",
+ // "memAddr": "DB85.DBB68",
+ // "tipoMem": "Real",
+ // "index": 68,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"TE3B": {
+ // "name": "TE3B",
+ // "description": "Temperatura Cavitazione Pompa B",
+ // "memAddr": "DB85.DBB72",
+ // "tipoMem": "Real",
+ // "index": 72,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"PressH": {
+ // "name": "PT300A",
+ // "description": "Alta Pressione",
+ // "memAddr": "DB85.DBB120",
+ // "tipoMem": "Real",
+ // "index": 120,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"PressM": {
+ // "name": "PT300M",
+ // "description": "Media Pressione",
+ // "memAddr": "DB85.DBB124",
+ // "tipoMem": "Real",
+ // "index": 124,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"LivelloPerc": {
+ // "name": "LT15%",
+ // "description": "Livello Serbatorio %",
+ // "memAddr": "DB85.DBB148",
+ // "tipoMem": "Real",
+ // "index": 148,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"MinTemp01": {
+ // "name": "MinTempTE04",
+ // "description": "Minima Temperatura Linea Sfiato Gas TE04",
+ // "memAddr": "DB85.DBB152",
+ // "tipoMem": "Real",
+ // "index": 152,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //},
+ //"MinTemp02": {
+ // "name": "MinTempTT17",
+ // "description": "Minima Temperatura Linea Sfiato Gas Torcia Serbatoio TT17",
+ // "memAddr": "DB85.DBB156",
+ // "tipoMem": "Real",
+ // "index": 156,
+ // "size": 4,
+ // "func": "MAX",
+ // "period": 60,
+ // "factor": 1
+ //}
}
}
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/DATA/CONF/PIZ04_alarm.json b/IOB-WIN-NEXT/DATA/CONF/PIZ04_alarm.json
index 2f20c6bc..2b51df57 100644
--- a/IOB-WIN-NEXT/DATA/CONF/PIZ04_alarm.json
+++ b/IOB-WIN-NEXT/DATA/CONF/PIZ04_alarm.json
@@ -1,125 +1,125 @@
[
- {
- "description": "Allarmi Impianto",
- "tipoMem": "Boolean",
- "memAddr": "DB85.DBB232",
- "index": 232,
- "size": 6,
- "messages": [
- "Emergenza Non Ripristinata",
- "Emergenza QE Intervenuta",
- "Emergenza Puls. Dispencer B Invervenuta",
- "Emergenza Puls. Dispencer A Invervenuta",
- "Stato Interruttore Erogatore Liquido B",
- "Allarme Controllo Tensione di Rete",
- "Allarme Controllo Tensione Antincendio",
- "Stato Interruttore Erogatore Liquido A",
- "Stato Sezionatore Generale",
- "Stato Interruttore Protezione SPD",
- "Stato Interruttore Sirena e Rotoalarm",
- "Stato Interruttore Luci Emergenza",
- "Stato Interruttore Pompa PC1A",
- "Stato Interruttore Pompa PC1B",
- "Stato Interruttore Pompa Sommersa C",
- "Stato Termica Boil-Off",
- "##234.0",
- "Preallarme Centralina Metano",
- "Allarme Centralina Metano",
- "Emergenza Puls. Dispencer C Invervenuta",
- "Mancaza Pressione Aria",
- "Minima Temperatura Linea Sfiato Gas TE04",
- "Minima Temperatura Linea Sfiato Gas Torcia Serbatoio TT17",
- "Massima Temperatura Linea Sfiato Gas Torcia Serbatoio TT17",
- "Almeno Un Emergenza Intervenuta",
- "Arresto Operativo da PT1(predisposizione)",
- "Stato Interruttore Alimentazione Punto Zero",
- "##234.11",
- "##234.12",
- "##234.13",
- "##234.14",
- "Configurazione Incongruente",
- "Pulsante Emergenza 2 SB17.3A Premuto",
- "Pulsante Emergenza 1 SB17.3B Premuto",
- "Pulsante Emergenza SB17.3C Premuto",
- "Pulsante Emergenza 3 SB17.5 Premuto",
- "Pulsante Emergenza 4 SB17.7 Premuto",
- "##236.5",
- "##236.6",
- "##236.7",
- "GT_TE2A",
- "GT_TE1A",
- "GT_TE3A",
- "GT_TE04",
- "GT_LT15",
- "GT_PT01",
- "GT_PT300R",
- "GT_PT16"
- ]
- },
- {
- "description": "Allarmi Serbatoio",
- "tipoMem": "Boolean",
- "memAddr": "DB85.DBB248",
- "index": 248,
- "size": 2,
- "messages": [
- "Serbatoio Troppo Pieno",
- "Serbatoio Pieno_HH",
- "Serbatoio Pieno_H",
- "Serbatoio Vuoto_LL",
- "H Pressione Serbatoio",
- "HH Pressione Serbatoio",
- "LL Temperatura Ingresso BoilOff TE08",
- "Minima Pressione Serbatoio per Partenza Pompe",
- "Timeout Apertura Valvola PV1",
- "Timeout Chiusura Valvola PV1",
- "Timeout Apertura Valvola PV70",
- "Timeout Chiusura Valvola PV70",
- "##248.12",
- "##248.13",
- "##248.14",
- "##248.15"
- ]
- },
- {
- "description": "Allarmi Pompa Alta Pressione A",
- "tipoMem": "Boolean",
- "memAddr": "DB85.DBB252",
- "index": 252,
- "size": 4,
- "messages": [
- "Ritardo Avvio Pompa PC1B",
- "##252.1",
- "Temperatura Freddo TE1B NON Raggiunta",
- "HH Temperatura Cavitazione TE3B",
- "Allarme Temperatura Tenute Pompa TE2B",
- "LL Temperatura Ingresso Stoccaggio TE06",
- "Allarme Temperatura Ingresso Stoccaggio TE07",
- "Aumento Pressione PT01",
- "##Max Pressione PT01",
- "##256.9",
- "##256.10",
- "##256.11",
- "##256.12",
- "##256.13",
- "##256.14",
- "##256.15",
- "Timeout Apertura PV3B",
- "Timeout Apertura PV5B",
- "Timeout Apertura PV6B",
- "Timeout Apertura PV7",
- "##258.4",
- "##258.5",
- "##258.6",
- "##258.7",
- "##258.8",
- "##258.9",
- "##258.10",
- "##258.11",
- "##258.12",
- "##258.13",
- "##258.14",
- "##258.15"
- ]
- }
+ //{
+ // "description": "Allarmi Impianto",
+ // "tipoMem": "Boolean",
+ // "memAddr": "DB85.DBB232",
+ // "index": 232,
+ // "size": 6,
+ // "messages": [
+ // "Emergenza Non Ripristinata",
+ // "Emergenza QE Intervenuta",
+ // "Emergenza Puls. Dispencer B Invervenuta",
+ // "Emergenza Puls. Dispencer A Invervenuta",
+ // "Stato Interruttore Erogatore Liquido B",
+ // "Allarme Controllo Tensione di Rete",
+ // "Allarme Controllo Tensione Antincendio",
+ // "Stato Interruttore Erogatore Liquido A",
+ // "Stato Sezionatore Generale",
+ // "Stato Interruttore Protezione SPD",
+ // "Stato Interruttore Sirena e Rotoalarm",
+ // "Stato Interruttore Luci Emergenza",
+ // "Stato Interruttore Pompa PC1A",
+ // "Stato Interruttore Pompa PC1B",
+ // "Stato Interruttore Pompa Sommersa C",
+ // "Stato Termica Boil-Off",
+ // "##234.0",
+ // "Preallarme Centralina Metano",
+ // "Allarme Centralina Metano",
+ // "Emergenza Puls. Dispencer C Invervenuta",
+ // "Mancaza Pressione Aria",
+ // "Minima Temperatura Linea Sfiato Gas TE04",
+ // "Minima Temperatura Linea Sfiato Gas Torcia Serbatoio TT17",
+ // "Massima Temperatura Linea Sfiato Gas Torcia Serbatoio TT17",
+ // "Almeno Un Emergenza Intervenuta",
+ // "Arresto Operativo da PT1(predisposizione)",
+ // "Stato Interruttore Alimentazione Punto Zero",
+ // "##234.11",
+ // "##234.12",
+ // "##234.13",
+ // "##234.14",
+ // "Configurazione Incongruente",
+ // "Pulsante Emergenza 2 SB17.3A Premuto",
+ // "Pulsante Emergenza 1 SB17.3B Premuto",
+ // "Pulsante Emergenza SB17.3C Premuto",
+ // "Pulsante Emergenza 3 SB17.5 Premuto",
+ // "Pulsante Emergenza 4 SB17.7 Premuto",
+ // "##236.5",
+ // "##236.6",
+ // "##236.7",
+ // "GT_TE2A",
+ // "GT_TE1A",
+ // "GT_TE3A",
+ // "GT_TE04",
+ // "GT_LT15",
+ // "GT_PT01",
+ // "GT_PT300R",
+ // "GT_PT16"
+ // ]
+ //},
+ //{
+ // "description": "Allarmi Serbatoio",
+ // "tipoMem": "Boolean",
+ // "memAddr": "DB85.DBB248",
+ // "index": 248,
+ // "size": 2,
+ // "messages": [
+ // "Serbatoio Troppo Pieno",
+ // "Serbatoio Pieno_HH",
+ // "Serbatoio Pieno_H",
+ // "Serbatoio Vuoto_LL",
+ // "H Pressione Serbatoio",
+ // "HH Pressione Serbatoio",
+ // "LL Temperatura Ingresso BoilOff TE08",
+ // "Minima Pressione Serbatoio per Partenza Pompe",
+ // "Timeout Apertura Valvola PV1",
+ // "Timeout Chiusura Valvola PV1",
+ // "Timeout Apertura Valvola PV70",
+ // "Timeout Chiusura Valvola PV70",
+ // "##248.12",
+ // "##248.13",
+ // "##248.14",
+ // "##248.15"
+ // ]
+ //},
+ //{
+ // "description": "Allarmi Pompa Alta Pressione A",
+ // "tipoMem": "Boolean",
+ // "memAddr": "DB85.DBB252",
+ // "index": 252,
+ // "size": 4,
+ // "messages": [
+ // "Ritardo Avvio Pompa PC1B",
+ // "##252.1",
+ // "Temperatura Freddo TE1B NON Raggiunta",
+ // "HH Temperatura Cavitazione TE3B",
+ // "Allarme Temperatura Tenute Pompa TE2B",
+ // "LL Temperatura Ingresso Stoccaggio TE06",
+ // "Allarme Temperatura Ingresso Stoccaggio TE07",
+ // "Aumento Pressione PT01",
+ // "##Max Pressione PT01",
+ // "##256.9",
+ // "##256.10",
+ // "##256.11",
+ // "##256.12",
+ // "##256.13",
+ // "##256.14",
+ // "##256.15",
+ // "Timeout Apertura PV3B",
+ // "Timeout Apertura PV5B",
+ // "Timeout Apertura PV6B",
+ // "Timeout Apertura PV7",
+ // "##258.4",
+ // "##258.5",
+ // "##258.6",
+ // "##258.7",
+ // "##258.8",
+ // "##258.9",
+ // "##258.10",
+ // "##258.11",
+ // "##258.12",
+ // "##258.13",
+ // "##258.14",
+ // "##258.15"
+ // ]
+ //}
]
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj
index feee01e5..ddcbb005 100644
--- a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj
+++ b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj
@@ -90,8 +90,8 @@
False
ExtLib\krcc.dll
-
- ..\packages\MapoSDK.6.13.2105.1421\lib\net40\MapoSDK.dll
+
+ ..\packages\MapoSDK.6.14.2109.2809\lib\net40\MapoSDK.dll
..\packages\MTConnect.NET.2.9.1.28314\lib\net40\MTConnect-NET.dll
@@ -100,7 +100,7 @@
..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll
- ..\packages\NLog.4.7.9\lib\net45\NLog.dll
+ ..\packages\NLog.4.7.11\lib\net45\NLog.dll
..\packages\OmronFinsTCP.Net.3.0.0.0\lib\net40\OmronFinsTCP.Net.dll
@@ -175,6 +175,7 @@
+
diff --git a/IOB-WIN-NEXT/IobGeneric.cs b/IOB-WIN-NEXT/IobGeneric.cs
index 52ed95d7..054dde52 100644
--- a/IOB-WIN-NEXT/IobGeneric.cs
+++ b/IOB-WIN-NEXT/IobGeneric.cs
@@ -536,8 +536,17 @@ namespace IOB_WIN_NEXT
address = IPAddress.Loopback;
int maxRetry = maxPingRetry + 1;
int numRetry = 1; ;
- string ipAdrr = cIobConf.serverData.MPIP.Replace($"{cIobConf.serverData.TRANSP}://", "");
- IPAddress.TryParse(ipAdrr, out address);
+ string ipAddr = cIobConf.serverData.MPIP.Replace($"{cIobConf.serverData.TRANSP}://", "");
+ IPAddress.TryParse(ipAddr, out address);
+ // se null --> provo DNS...
+ if (address == null)
+ {
+ var rawAddresses = Dns.GetHostAddresses(ipAddr);
+ if (rawAddresses.Length > 0)
+ {
+ address = rawAddresses[0];
+ }
+ }
try
{
// se != null --> uso address...
@@ -557,12 +566,12 @@ namespace IOB_WIN_NEXT
// se ho timeout riprovo...
while (reply.Status != IPStatus.Success && numRetry < maxRetry)
{
- lgInfo($"Ping KO | reply: {reply.Status} --> retry");
+ lgInfo($"Server Ping KO | reply: {reply.Status} --> retry");
reply = pingSender.Send(address, pingServerMsTimeout * numRetry / 2);
numRetry++;
if (reply.Status == IPStatus.Success)
{
- lgInfo("PING OK!");
+ lgInfo("Server PING OK!");
break;
}
}
@@ -4072,7 +4081,8 @@ namespace IOB_WIN_NEXT
{ }
///
- /// Effettua processing del recupero delle speed (RPM, feedrate) degli assi
+ /// Effettua processing del recupero dei valori dinamici:
+ /// es: speed (RPM, feedrate) degli assi, valori pressioni, temeprature
///
public void processDynData()
{
diff --git a/IOB-WIN-NEXT/IobModbusTCP.cs b/IOB-WIN-NEXT/IobModbusTCP.cs
index 6be7f7c8..01ba2870 100644
--- a/IOB-WIN-NEXT/IobModbusTCP.cs
+++ b/IOB-WIN-NEXT/IobModbusTCP.cs
@@ -1,116 +1,1246 @@
using EasyModbus;
using IOB_UT_NEXT;
+using MapoSDK;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Linq;
+using System.Net.NetworkInformation;
using System.Text;
+using System.Threading;
using System.Threading.Tasks;
namespace IOB_WIN_NEXT
{
+ /* --------------------------------------------------------------------------------
+ * Controlli ModBusTCP COMECA
+ * - protocollo ModBus TCP
+ *
+ * -------------------------------------------------------------------------------- */
+
public class IobModbusTCP : IobGeneric
{
#region Protected Fields
- protected string serverIp = "hampizzaferri.dyndns.org";
+ protected ModbusClient currPLC;
+
+ ///
+ /// Ultimo controllo ping x evitare ping flood...
+ ///
+ protected DateTime lastPingConn = DateTime.Now.AddMinutes(-10);
+
+ ///
+ /// Esito ultimo ping
+ ///
+ protected bool lastPingOk = false;
+
+ ///
+ /// Setup blocchi memorie read (indirizzo inizio, size)
+ ///
+ protected Dictionary memSetR = new Dictionary();
+
+ ///
+ /// Setup blocchi memorie write (indirizzo inizio, size)
+ ///
+ protected Dictionary memSetW = new Dictionary();
+
+ ///
+ /// parametri di connessione
+ ///
+ protected connParamModBusTCP parametri;
+
+ ///
+ /// Oggetto cronometro x test vari...
+ ///
+ protected Stopwatch sw = new Stopwatch();
#endregion Protected Fields
- //protected string serverIp = "127.0.0.1";
-
#region Public Constructors
- /// Classe base con i metodi x Siemens
+ /// Classe base con i metodi x ModBusTCP
///
///
///
public IobModbusTCP(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf)
{
lgInfo("NEW IOB ModBus TCP");
+ setupMemBlocks();
+ memMap = new plcMemMap();
+ if (IOBConf != null)
+ {
+ // gestione invio ritardato contapezzi
+ pzCountDelay = utils.CRI("pzCountDelay");
+ lastPzCountSend = DateTime.Now;
+ lastWarnODL = DateTime.Now;
+ // inizializzo parametri...
+ parametri = new connParamModBusTCP()
+ {
+ ipAdrr = "127.0.0.1",
+ port = 502,
+ pingMsTimeout = IOBConf.pingMsTimeout,
+ memAddrRead = "40001",
+ memAddrWrite = "41001",
+ memSizeRead = 0,
+ memSizeWrite = 0
+ };
+ setParamPlc();
- testRead();
+ // salvo info su conf IOB...
+ string iobConfSer = "";
+ try
+ {
+ iobConfSer = JsonConvert.SerializeObject(IOBConf, Formatting.Indented);
+ }
+ catch
+ { }
+ // finito!
+ lgInfo($"Init IOB, con {iobConfSer}");
+ }
+ else
+ {
+ lgError("Impossibile avviare, IOBConf nullo/non valido!");
+ }
}
#endregion Public Constructors
+ #region Protected Properties
+
+ ///
+ /// Dizionario delle ultime operazioni di scrittura per OGNI memoria (in modo che fa log ogni x sec...)
+ ///
+ protected Dictionary lastMemWrite { get; set; } = new Dictionary();
+
+ #endregion Protected Properties
+
#region Private Methods
- private void testConf()
+ private static int getScaledInt(dataConf currMem)
{
- BaseModbusConf.VarConf var01 = new BaseModbusConf.VarConf()
+ int valInt;
+ // prima faccio eventuale fattore di scala...
+ int.TryParse(currMem.value, out valInt);
+ if (currMem.factor > 1)
{
- Name = "Giacenza Serbatoio",
- Type = BaseModbusConf.DataType.Real,
- MemAddr = 1,
- Size = 2,
- Direction = BaseModbusConf.MemDirection.R,
- RangeMin = 0,
- RangeMax = 100
- };
- BaseModbusConf.VarConf var02 = new BaseModbusConf.VarConf()
- {
- Name = "Pressione Serbatoio",
- Type = BaseModbusConf.DataType.Real,
- MemAddr = 3,
- Size = 2,
- Direction = BaseModbusConf.MemDirection.R,
- RangeMin = 0,
- RangeMax = 25
- };
- List memList01 = new List();
- memList01.Add(var01);
- memList01.Add(var02);
- BaseModbusConf.ModbusMemArea block01 = new BaseModbusConf.ModbusMemArea()
- {
- RawAddr = "40001",
- Type = BaseModbusConf.MemType.HoldingRegister,
- BaseAddr = 1,
- Size = 50,
- VarList = memList01
- };
- List DemoMem = new List();
- DemoMem.Add(block01);
+ valInt = valInt * currMem.factor;
+ }
- // creo un area di memoria
- BaseModbusConf demoConf = new BaseModbusConf()
- {
- MemoryList = DemoMem
- };
- // salvo conf con json x compilare...
- var rawData = JsonConvert.SerializeObject(demoConf);
+ return valInt;
}
- private void testRead()
+ private static uint getScaledUInt(dataConf currMem)
{
- //Ip-Address and Port of Modbus-TCP-Server
- ModbusClient modbusClient = new ModbusClient(serverIp, 502);
- //Connect to Server
- modbusClient.Connect();
- //modbusClient.WriteMultipleCoils(4, new bool[] { true, true, true, true, true, true, true, true, true, true }); //Write Coils starting with Address 5
- //bool[] readCoils = modbusClient.ReadCoils(9, 10); //Read 10 Coils from Server, starting with address 10
- int[] readHoldingRegisters = modbusClient.ReadHoldingRegisters(0, 34); //Read 10 Holding Registers from Server, starting with Address 1
-
- int[] readHR1000 = modbusClient.ReadHoldingRegisters(0, 100); //Read 10 Holding Registers from Server, starting with Address 1
-
- //Disconnect from Server
- modbusClient.Disconnect();
-
- //// Console Output
- //for (int i = 0; i < readCoils.Length; i++)
- // Console.WriteLine("Value of Coil " + (9 + i + 1) + " " + readCoils[i].ToString());
-
- for (int i = 0; i < readHoldingRegisters.Length; i++)
+ uint valUInt;
+ // prima faccio eventuale fattore di scala...
+ uint.TryParse(currMem.value, out valUInt);
+ if (currMem.factor > 1)
{
- Console.WriteLine("Value of HoldingRegister " + (i + 1) + " " + readHoldingRegisters[i].ToString());
- int[] thisSet = new int[2];
- Array.Copy(readHoldingRegisters, i, thisSet, 0, 2);
- Console.WriteLine("Convert val HoldingRegister " + (i + 1) + " " + ModbusClient.ConvertRegistersToFloat(thisSet));
+ valUInt = valUInt * (uint)currMem.factor;
+ }
+
+ return valUInt;
+ }
+
+ ///
+ /// Verifica SE sia il caso di fare il log della memoria indicata
+ ///
+ ///
+ ///
+ private void maybeLogWrite(string memAddrWrite, string logValue)
+ {
+ bool doWrite = true;
+ DateTime adesso = DateTime.Now;
+ if (!lastMemWrite.ContainsKey(memAddrWrite))
+ {
+ lastMemWrite.Add(memAddrWrite, adesso.AddMinutes(-1));
+ }
+ // ora mi leggo valore ultimas crittura e confronto con adesso
+ try
+ {
+ doWrite = (lastMemWrite[memAddrWrite].AddSeconds(vetoSeconds) < adesso);
+ }
+ catch (Exception exc)
+ {
+ lgError($"Eccezione in maybeLogWrite{Environment.NewLine}{exc}");
+ }
+ // se encessario --> LOG!
+ if (doWrite)
+ {
+ lgInfo(logValue);
+ lastMemWrite[memAddrWrite] = adesso;
}
- Console.Write("Press any key to continue . . . ");
- Console.ReadKey(true);
}
#endregion Private Methods
+
+ #region Protected Methods
+
+ ///
+ /// Decodifica il resto dell'area x i dati accessori (allarmi, ...)
+ ///
+ protected virtual void decodeOtherData()
+ {
+ }
+
+ ///
+ /// Effettua decodifica aree memoria alla bitmap usata x MAPO/GWMS
+ /// - per lo scopo specifico IN REALTA' non conta lo stato macchina.... ma lo inviamo lo stesso
+ ///
+ protected virtual void decodeToBaseBitmap()
+ {
+ // init a zero...
+ B_input = 0;
+ }
+
+ ///
+ /// Override metodo x scrittura parametri su PLC
+ ///
+ ///
+ protected override void plcWriteParams(ref List updatedPar)
+ {
+#if false
+ dataConf currMem = null;
+ int byteSize = 0;
+ byte[] MemBlock = new byte[1];
+ string memAddrWrite = "";
+ bool fatto = false;
+ string serObj = "";
+ if (updatedPar != null)
+ {
+ // controllo i parametri... ne gestisco 4...
+ foreach (var item in updatedPar)
+ {
+ try
+ {
+ memAddrWrite = "";
+ int valInt = 0;
+ uint valUInt = 0;
+ // cerco in area memMapWrite...
+ if (memMap.mMapWrite.ContainsKey(item.uid))
+ {
+ // recupero!
+ currMem = memMap.mMapWrite[item.uid];
+ byteSize = currMem.size;
+ memAddrWrite = currMem.memAddr;
+ MemBlock = new byte[byteSize];
+ // faccio preliminarmente upsertKey...
+ upsertKey(currMem.name, currMem.value);
+ serObj = JsonConvert.SerializeObject(item, Formatting.Indented);
+ lgInfo($"Inizio processing plcWriteParams per {currMem.name} | valore richiesto {currMem.value}{Environment.NewLine}---------------UPDATED PARAM---------------{Environment.NewLine}{serObj}{Environment.NewLine}---------------");
+ serObj = JsonConvert.SerializeObject(currMem, Formatting.Indented);
+ lgInfo($"---------------MEMORY CONTENT---------------{Environment.NewLine}{serObj}{Environment.NewLine}---------------");
+ switch (currMem.tipoMem)
+ {
+ case plcDataType.Boolean:
+ break;
+
+ case plcDataType.Int:
+ valInt = getScaledInt(currMem);
+ saveIntOnMemBlock(ref MemBlock, 0, valInt.ToString());
+ break;
+
+ case plcDataType.DInt:
+ valInt = getScaledInt(currMem);
+ saveDIntOnMemBlock(ref MemBlock, 0, valInt.ToString());
+ break;
+
+ case plcDataType.Word:
+ valUInt = getScaledUInt(currMem);
+ saveWordOnMemBlock(ref MemBlock, 0, valInt.ToString());
+ break;
+
+ case plcDataType.DWord:
+ valUInt = getScaledUInt(currMem);
+ saveDWordOnMemBlock(ref MemBlock, 0, valInt.ToString());
+ break;
+
+ case plcDataType.Real:
+ saveRealOnMemBlock(ref MemBlock, 0, currMem.value);
+ break;
+
+ case plcDataType.String:
+ // se ho writePre --> "allungo" di 2 la dimensione della stringa x MemBlock...
+ if (writePre)
+ {
+ MemBlock = new byte[byteSize + 2];
+ }
+ saveStringOnMemBlock(ref MemBlock, 0, currMem.size, currMem.value);
+ break;
+
+ default:
+ break;
+ }
+ lgInfo($"---------------MemBlock data---------------{Environment.NewLine}{BitConverter.ToString(MemBlock)}{Environment.NewLine}--------------- END data ---------------");
+ if (!string.IsNullOrEmpty(memAddrWrite))
+ {
+ // scrivo su ModBusTCP
+ fatto = S7WriteBB(ref MemBlock, memAddrWrite);
+ // se fatto --> aggiorno!
+ if (fatto)
+ {
+ item.value = item.reqValue;
+ item.reqValue = "";
+ item.lastRead = DateTime.Now;
+ }
+ // se configurato faccio verifica write...
+ if (getOptPar("WRITE_CHECK") == "TRUE")
+ {
+ byte[] MemBlockRead = new byte[MemBlock.Length];
+ S7ReadBB(ref MemBlockRead, memAddrWrite, MemBlock.Length);
+ // se non corrispondessero loggo!
+ if (!MemBlock.SequenceEqual(MemBlockRead))
+ {
+ lgError($"Errore: mancata corrispondenza tra dati scritti e letti:{Environment.NewLine}Write: {BitConverter.ToString(MemBlock)}{Environment.NewLine}read: {BitConverter.ToString(MemBlockRead)}");
+ }
+ else
+ {
+ lgInfo($"Scrittura corretta: {BitConverter.ToString(MemBlockRead)}");
+ }
+ }
+ }
+ else
+ {
+ lgInfo($"Errore: memAddrWrite vuoto!");
+ }
+ }
+ else
+ {
+ lgInfo($"Errore uid non trovato in area write memory: {item.uid}, ci sono {memMap.mMapWrite.Count} in area write");
+ }
+ }
+ catch (Exception exc)
+ {
+ lgError($"Eccezione in fase di plcWriteParams per item {item.uid} con valore {item.value}{Environment.NewLine}{exc}");
+ }
+ }
+ }
+#endif
+ }
+
+ ///
+ /// Imposto parametri PLC
+ ///
+ protected override void setParamPlc()
+ {
+ // Creo oggetto connessione NC
+ parentForm.commPlcActive = true;
+ lgInfo($"Start init Adapter ModBus TCP all'IP {cIobConf.cncIpAddr} | port: {cIobConf.cncPort} | --> IOB {cIobConf.codIOB}");
+ // SE è necessario refresh...
+ if (needRefresh)
+ {
+ lgInfo("Refreshing connection...");
+ if (parametri != null)
+ {
+ try
+ {
+ parametri.ipAdrr = cIobConf.cncIpAddr;
+ parametri.port = int.Parse(cIobConf.cncPort);
+ // leggo file init...
+ lgInfo("Reading ini file...");
+ IniFile fIni = new IniFile(cIobConf.iniFileName);
+ // ora leggo valori speciali
+ parametri.memAddrRead = fIni.ReadString("MEMORY", "ADDR_READ", "");
+ parametri.memAddrWrite = fIni.ReadString("MEMORY", "ADDR_WRITE", "");
+ parametri.memSizeRead = fIni.ReadInteger("MEMORY", "SIZE_READ", 0);
+ parametri.memSizeWrite = fIni.ReadInteger("MEMORY", "SIZE_WRITE", 0);
+ // salvo vettori memoria...
+ lgInfo("Set RawInput dimensions...");
+ RawInput = new byte[parametri.memSizeRead];
+ RawOutput = new byte[parametri.memSizeWrite];
+ // salvo parametri conn!
+ lgInfo(string.Format("Parametri memoria: memAddrRead: {0} | memAddrWrite: {1} | memSizeRead: {2} | memSizeWrite: {3}", parametri.memAddrRead, parametri.memAddrWrite, parametri.memSizeRead, parametri.memSizeWrite));
+ }
+ catch (Exception exc)
+ {
+ lgError(exc, "Errore in parse parametri da IOBConf");
+ }
+ // ora tento avvio PLC... SE PING OK...
+ IPStatus esitoPing = testPingMachine;
+ if (esitoPing == IPStatus.Success)
+ {
+ needRefresh = false;
+ try
+ {
+ //Ip-Address and Port of Modbus-TCP-Server
+ currPLC = new ModbusClient(parametri.ipAdrr, parametri.port);
+
+ // disconnetto e connetto...
+ if (isVerboseLog)
+ {
+ lgInfo("ModBus TCP: tryDisconnect");
+ }
+ tryDisconnect();
+
+ // lo ripeto x evitare che ci sia un loop... e tryConnect richiami la procedura corrente...
+ needRefresh = false;
+ lgInfo("ModBus TCP: tryConnect");
+ tryConnect();
+ lgInfo("End init Adapter ModBusTCP");
+ if (isVerboseLog)
+ {
+ lgInfo("ModBus TCP CONNESSIONE AVVENUTA");
+ }
+ }
+ catch (Exception exc)
+ {
+ lgError(exc, "Errore in INIT ModBusTCP");
+ }
+ }
+ else
+ {
+ lgError($"Errore in ping: esito {esitoPing}");
+ }
+ parentForm.commPlcActive = false;
+ // carico conf vettore memoria...
+ loadMemConf();
+ bool enableByApp = utils.CRB("enableContapezzi");
+ bool enableByIob = (getOptPar("ENABLE_PZCOUNT") == "TRUE");
+ bool disableByIob = (getOptPar("DISABLE_PZCOUNT") == "TRUE");
+ if ((enableByApp || enableByIob) && !(disableByIob))
+ {
+ lgInfo("ModBus TCP: inizio gestione contapezzi");
+ try
+ {
+ // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area)
+ if (cIobConf.optPar.Count > 0 && !string.IsNullOrWhiteSpace(getOptPar("PZCOUNT_MODE")))
+ {
+ if (getOptPar("PZCOUNT_MODE").StartsWith("STD"))
+ {
+ lgInfo("Init contapezzi ModBusTCP: pzCntReload(true)");
+ pzCntReload(true);
+ // refresh associazione Macchina - IOB
+ sendM2IOB();
+ // per adesso imposto lettura PLC == contapezzi (poi farà vera lettura...)
+ contapezziPLC = contapezziIOB;
+ }
+ else
+ {
+ contapezziIOB = 0;
+ lgInfo("Contapezzi STD disabilitato: modalità {0}", getOptPar("PZCOUNT_MODE"));
+ }
+ }
+ else
+ {
+ contapezziIOB = 0;
+ lgInfo("Parametro mancante PZCOUNT_MODE");
+ }
+ }
+ catch (Exception exc)
+ {
+ lgError(exc, "Errore in contapezzi ModBusTCP");
+ }
+ }
+ }
+ else
+ {
+ lgError("Parametri null!");
+ }
+ }
+ }
+
+ ///
+ /// effettua il setup dei memblock da gestire (NON leggo intera memoria ma tanti blocchi...)
+ ///
+ protected virtual void setupMemBlocks()
+ { }
+
+ ///
+ /// Test connessione CNC
+ ///
+ ///
+ protected bool testCncConn()
+ {
+ bool answ = currPLC.Connected;
+ if (!answ)
+ {
+ // riduco i controlli ping.. li faccio solo ogni 5 ping period se precedente positivo...
+ DateTime adesso = DateTime.Now;
+ if (lastPingOk && adesso.Subtract(lastPingConn).TotalMilliseconds < 5 * parametri.pingMsTimeout)
+ {
+ answ = lastPingOk;
+ }
+ else
+ {
+ IPStatus pingStatus = testPingMachine;
+
+ // se non ok riprovo 1 volta dopo attesa
+ if (pingStatus != IPStatus.Success)
+ {
+ Thread.Sleep(2 * cIobConf.pingMsTimeout);
+ pingStatus = testPingMachine;
+ }
+ // se non passa ancora errore!
+ if (pingStatus != IPStatus.Success)
+ {
+ lgError($"Errore in testCncConn | reply Status {pingStatus} | IP: {parametri.ipAdrr} | T.Out: {parametri.pingMsTimeout}ms");
+ }
+ // se passa il ping faccio il resto...
+ else
+ {
+ if (!currPLC.Connected)
+ {
+ currPLC.Connect();
+ }
+
+ if (!currPLC.Available(500))
+ {
+ lgError($"PLC ModBus NON disponibile: {currPLC.IPAddress} | {currPLC.Port}");
+ }
+ else
+ {
+ if (!currPLC.Connected)
+ {
+ lgError($"PLC ModBus NON connesso:{currPLC.IPAddress} | {currPLC.Port}");
+ }
+ else
+ {
+ // tutto ok
+ parentForm.updateComStats("Connection OK");
+ answ = true;
+ }
+ }
+ }
+ // salvo stato ping
+ lastPingConn = adesso;
+ }
+ lastPingOk = answ;
+ }
+
+ return answ;
+ }
+
+ #endregion Protected Methods
+
+ #region Public Methods
+
+ ///
+ /// Metodo dispose x il currPLC contenuto
+ ///
+ public void Dispose()
+ {
+ currPLC.Disconnect();
+ }
+
+ ///
+ /// Processo i task richiesti e li elimino dalla coda 1:1
+ ///
+ ///
+ public override Dictionary executeTasks(Dictionary task2exe)
+ {
+ lgInfo($"Chiamata executeTasks specifica ModBus TCP: {task2exe.Count} task ricevuti");
+ // Verificare il protocollo: dovrebeb togliere SOLO i task eseguiti...
+ Dictionary taskDone = new Dictionary();
+ return taskDone;
+ }
+
+ ///
+ /// decodifica tipo indirizzo dal codice
+ ///
+ ///
+ ///
+ public modBusAddrType getAddrType(string memAddr)
+ {
+ modBusAddrType answ = modBusAddrType.Coil;
+ // leggo prima cifra...
+ answ = (modBusAddrType)Enum.Parse(typeof(modBusAddrType), memAddr.Substring(0, 1));
+ return answ;
+ }
+
+ ///
+ /// Recupero dati dinamici...
+ /// ATTENZIONE factor usato come FONDOSCALA.... quindi 28'000 --> MOLTIPLICO per 28'000
+ ///
+ public override Dictionary getDynData()
+ {
+ // valore non presente in vers default... se gestito fare override
+ Dictionary outVal = new Dictionary();
+ if (utils.CRB("enableTSVC"))
+ {
+ // processing SOLO SE ho in memoria abbastanza dati...
+ if (RawInput.Length < parametri.memSizeRead)
+ {
+ lgError($"Impossibile processare getDynData x ModBus TCP PLC, vettore memoria troppo piccolo: {RawInput.Length} byte / {parametri.memSizeRead} byte presenti/richiesti)");
+ }
+ else
+ {
+ try
+ {
+ // processo x ogni valore configurato...
+ if (memMap.mMapRead.Count > 0)
+ {
+ // inizializzo i valori
+ bool[] listBool = new bool[1];
+ int[] listInt = new int[2];
+ double valore = 0;
+ // procedo x ogni valore configurato......
+ foreach (var item in memMap.mMapRead)
+ {
+ // in primis DEVO determinare di quale TIPO di valore ho bisogno... dalla PRIMA cifra di memAddr...
+ modBusAddrType memAddrType = getAddrType(item.Value.memAddr);
+ // in base al tipo leggo array...
+ switch (memAddrType)
+ {
+ case modBusAddrType.Coil:
+ listBool = readCoil(item.Value.index, item.Value.size);
+ valore = listBool[0] ? 1 : 0;
+ break;
+
+ case modBusAddrType.DiscreteInput:
+ listBool = readDiscrInputs(item.Value.index, item.Value.size);
+ valore = listBool[0] ? 1 : 0;
+ break;
+
+ case modBusAddrType.InputRegister:
+ listInt = readInputReg(item.Value.index, item.Value.size);
+ //verifico se sia INT o real x convertire...
+ switch (item.Value.tipoMem)
+ {
+ case plcDataType.Real:
+ if (item.Value.size == 4)
+ {
+ valore = ModbusClient.ConvertRegistersToDouble(listInt) * item.Value.factor;
+ }
+ else if (item.Value.size == 2)
+ {
+ valore = ModbusClient.ConvertRegistersToFloat(listInt) * item.Value.factor;
+ }
+ break;
+
+ case plcDataType.Int:
+ default:
+ if (item.Value.size == 4)
+ {
+ valore = ModbusClient.ConvertRegistersToLong(listInt) * item.Value.factor;
+ }
+ else if (item.Value.size == 2)
+ {
+ valore = ModbusClient.ConvertRegistersToInt(listInt) * item.Value.factor;
+ }
+ break;
+ }
+ break;
+
+ case modBusAddrType.HoldingRegister:
+ listInt = readHoldReg(item.Value.index - 1, item.Value.size);
+ //verifico se sia INT o real x convertire...
+ switch (item.Value.tipoMem)
+ {
+ case plcDataType.Real:
+ if (item.Value.size == 4)
+ {
+ valore = ModbusClient.ConvertRegistersToDouble(listInt) * item.Value.factor;
+ }
+ else if (item.Value.size == 2)
+ {
+ valore = ModbusClient.ConvertRegistersToFloat(listInt) * item.Value.factor;
+ }
+ break;
+
+ case plcDataType.Int:
+ default:
+ if (item.Value.size == 4)
+ {
+ valore = ModbusClient.ConvertRegistersToLong(listInt) * item.Value.factor;
+ }
+ else if (item.Value.size == 2)
+ {
+ valore = ModbusClient.ConvertRegistersToInt(listInt) * item.Value.factor;
+ }
+ break;
+ }
+ break;
+
+ default:
+ break;
+ }
+ saveValue(ref outVal, valore, item.Key);
+ }
+ }
+ else
+ {
+ lgInfo($"getDynData: {memMap.mMapRead.Count} record in mMapRead");
+ }
+ }
+ catch (Exception exc)
+ {
+ lgError(exc, "Errore in getDynData x ModBus TCP PLC");
+ }
+ }
+ }
+ else
+ {
+ lgInfo($"Non processo getDynData: enableTSVC = false");
+ }
+ if (periodicLog || outVal.Count > 0)
+ {
+ lgInfo($"Esito getDynData: {outVal.Count} valori VALIDI in outVal");
+ }
+ return outVal;
+ }
+
+ ///
+ /// Lettura valori Coils (1...)
+ ///
+ ///
+ ///
+ ///
+ public bool[] readCoil(int startAddr, int qty)
+ {
+ bool[] answ = new bool[1];
+ if (currPLC.Connected)
+ {
+ answ = currPLC.ReadCoils(startAddr, qty);
+ }
+ return answ;
+ }
+
+ ///
+ /// Lettura valori DiscreteInputs (2...)
+ ///
+ ///
+ ///
+ ///
+ public bool[] readDiscrInputs(int startAddr, int qty)
+ {
+ bool[] answ = new bool[1];
+ if (currPLC.Connected)
+ {
+ answ = currPLC.ReadDiscreteInputs(startAddr, qty);
+ }
+ return answ;
+ }
+
+ ///
+ /// Lettura valori Holding Register (3...)
+ ///
+ ///
+ ///
+ ///
+ public int[] readHoldReg(int startAddr, int qty)
+ {
+ int[] answ = new int[2];
+ if (currPLC.Connected)
+ {
+ answ = currPLC.ReadHoldingRegisters(startAddr, qty);
+ }
+ return answ;
+ }
+
+ ///
+ /// Lettura valori Input Register (4...)
+ ///
+ ///
+ ///
+ ///
+ public int[] readInputReg(int startAddr, int qty)
+ {
+ int[] answ = new int[2];
+ if (currPLC.Connected)
+ {
+ answ = currPLC.ReadInputRegisters(startAddr, qty);
+ }
+ return answ;
+ }
+
+ ///
+ /// Effettua lettura semafori principale
+ /// Parametri da aggiornare x display in form
+ ///
+ public override void readSemafori(ref newDisplayData currDispData)
+ {
+ base.readSemafori(ref currDispData);
+ byte[] MemBlock = new byte[2];
+ try
+ {
+ currDispData.semIn = Semaforo.SV;
+
+ if (verboseLog)
+ {
+ lgInfo("inizio read semafori");
+ }
+
+ //// ciclo a leggere TUTTI i blocchi di memoria impostati
+ //foreach (var item in memSetR)
+ //{
+ // // leggo TUTTI i byte configurati...
+ // MemBlock = new byte[item.Value];
+ // S7ReadBB(ref MemBlock, $"{item.Key}", item.Value);
+ // Buffer.BlockCopy(MemBlock, 0, RawInput, item.Key, item.Value);
+ //}
+
+ //// leggo TUTTI i byte configurati...
+ //MemBlock = new byte[parametri.memSizeRead];
+ //bool fatto = S7ReadBB(ref MemBlock);
+ //Buffer.BlockCopy(MemBlock, 0, RawInput, 0, parametri.memSizeRead);
+ if (verboseLog)
+ {
+ lgInfo(string.Format("RawInput[0]: {0}", utils.binaryForm(RawInput[0])));
+ }
+
+ // salvo il solo BYTE dell'input decifrando il semaforo...
+ decodeToBaseBitmap();
+ decodeOtherData();
+ // riporto bitmap...
+ reportRawInput(ref currDispData);
+ }
+ catch
+ {
+ currDispData.semIn = Semaforo.SR;
+ }
+ }
+
+ ///
+ /// wrapper chiamata LETTURA in blocco MULTI BYTE dell'area read DI DEFAULT...
+ ///
+ ///
+ ///
+ public bool S7ReadBB(ref byte[] Value)
+ {
+ return S7ReadBB(ref Value, parametri.memAddrRead, parametri.memSizeRead);
+ }
+
+ ///
+ /// wrapper chiamata LETTURA in blocco MULTI BYTE...
+ ///
+ /// MATRICE valori letti
+ /// Area memoria da leggere...
+ /// Numero byte da leggere
+ ///
+ public bool S7ReadBB(ref byte[] Value, string memAddrRead, int numByte)
+ {
+ bool answ = false;
+ if (Value != null)
+ {
+ sw.Restart();
+ parentForm.commPlcActive = true;
+#if false
+ if (testCncConn())
+ {
+ // decodifico memoria...
+ memAreaSiemens memoria = new memAreaSiemens(memAddrRead);
+ Byte[] memByteRead = currPLC.ReadBytes(DataType.DataBlock, memoria.DbNum, memoria.indiceMem, numByte);
+ // copio in value, sennò do errore...
+ if (memByteRead.Length == Value.Length)
+ {
+ Value = memByteRead;
+ }
+ else
+ {
+ lgError($"Mismatch dimensione array memoria: indirizzo: {memAddrRead} | passato array di {Value.Length} byte, letti da S7 {memByteRead.Length} byte");
+ }
+ string titolo = $"READ BLOCK MEM BYTE: {parametri.memAddrRead} --> {numByte} byte";
+ if (verboseLog)
+ {
+ lgInfo(titolo);
+ }
+
+ string contenuto = $"Contenuto area memoria acquisita{Environment.NewLine}";
+ string byteVal = "";
+ for (int i = 0; i < memByteRead.Length; i++)
+ {
+ byteVal = Convert.ToString(memByteRead[i], 2).PadLeft(8, '0');
+ contenuto += string.Format("B{0:000}: {1} | {2}{3}", i, byteVal, memByteRead[i], Environment.NewLine);
+ }
+ // loggo lettura...
+ if (verboseLog)
+ {
+ lgInfo(contenuto);
+ }
+ }
+ else
+ {
+ connectionOk = false;
+ }
+#endif
+ parentForm.commPlcActive = false;
+ sw.Stop();
+ if (utils.CRB("recTime"))
+ {
+ TimingData.addResult(cIobConf.codIOB, string.Format("{0}|{1}", parametri.memAddrRead, numByte), sw.ElapsedTicks);
+ }
+ }
+ return answ;
+ }
+
+ ///
+ /// wrapper chiamata LETTURA in blocco MULTI BYTE... default size a parametri.memSizeRead
+ ///
+ ///
+ /// Area memoria da leggere...
+ ///
+ public bool S7ReadBB(ref byte[] Value, string memAddrRead)
+ {
+ bool answ = false;
+ answ = S7ReadBB(ref Value, memAddrRead, parametri.memSizeRead);
+ return answ;
+ }
+
+ ///
+ /// wrapper chiamata SCRITTURA in blocco MULTI BYTE, DI DEFAULT su area configurata x scrittura CONTINUA...
+ ///
+ ///
+ ///
+ public bool S7WriteBB(ref byte[] Value)
+ {
+ return S7WriteBB(ref Value, parametri.memAddrWrite);
+ }
+
+ ///
+ /// Override scrittura in area DBB
+ ///
+ ///
+ ///
+ ///
+ public bool S7WriteBB(ref byte[] Value, string memAddrWrite)
+ {
+ bool answ = false;
+ if (Value == null)
+ {
+ lgError($"Errore in S7WriteBB: Value è null");
+ }
+ else
+ {
+ if (string.IsNullOrEmpty(memAddrWrite))
+ {
+ lgError($"Errore in S7WriteBB: memAddrWrite è vuoto");
+ }
+ else
+ {
+ sw.Restart();
+#if false
+ if (testCncConn())
+ {
+ try
+ {
+ // decodifico memoria...
+ memAreaSiemens memoria = new memAreaSiemens(memAddrWrite);
+ int numByte = Value.Length;
+ ErrorCode errorCode = currPLC.WriteBytes(DataType.DataBlock, memoria.DbNum, memoria.indiceMem, Value);
+ switch (errorCode)
+ {
+ case ErrorCode.NoError:
+ answ = true;
+ maybeLogWrite(memAddrWrite, $"S7WriteBB-01 Effettuata correttamente scrittura su PLC: MEMORIA {memAddrWrite} | numByte: {Value.Length} | ValOriginale: {Value}");
+ break;
+
+ case ErrorCode.WrongCPU_Type:
+ case ErrorCode.ConnectionError:
+ case ErrorCode.IPAddressNotAvailable:
+ case ErrorCode.WrongVarFormat:
+ case ErrorCode.WrongNumberReceivedBytes:
+ case ErrorCode.SendData:
+ case ErrorCode.ReadData:
+ case ErrorCode.WriteData:
+ lgError($"Errore in S7WriteBB su {memAddrWrite}: {errorCode.ToString()} | numByte: {Value.Length}| {Value.ValToBinString()}");
+ answ = false;
+ break;
+
+ default:
+ break;
+ }
+ }
+ catch (Exception exc)
+ {
+ lgError($"Eccezione in S7WriteBB | memAddrWrite {memAddrWrite} | numByte: {Value.Length}{Environment.NewLine}{exc}");
+ }
+ }
+#endif
+ sw.Stop();
+ }
+ }
+ return answ;
+ }
+
+ ///
+ /// Override scrittura in area DBB
+ ///
+ /// Valore byte[] da scrivere
+ /// Numero del DB (es 700 per DB700)
+ /// Indice interno al datablock del byte da cui partire
+ ///
+ public bool S7WriteBB(ref byte[] Value, int DbNum, int IndiceMem)
+ {
+ bool answ = false;
+ if (Value == null)
+ {
+ lgError($"Errore in S7WriteBB: Value è null");
+ }
+ else
+ {
+ if (DbNum < 0 || IndiceMem < 0)
+ {
+ lgError($"Errore in S7WriteBB | DbNum: {DbNum} | IndiceMem: {IndiceMem}");
+ }
+ else
+ {
+ sw.Restart();
+#if false
+ if (testCncConn())
+ {
+ try
+ {
+ int numByte = Value.Length;
+ ErrorCode errorCode = currPLC.WriteBytes(DataType.DataBlock, DbNum, IndiceMem, Value);
+ switch (errorCode)
+ {
+ case ErrorCode.NoError:
+ lgInfo($"S7WriteBB-02 Effettuata correttamente scrittura su PLC: DB {DbNum}.{IndiceMem} | numByte: {Value.Length}| {Value.ValToBinString()}");
+ break;
+
+ case ErrorCode.WrongCPU_Type:
+ case ErrorCode.ConnectionError:
+ case ErrorCode.IPAddressNotAvailable:
+ case ErrorCode.WrongVarFormat:
+ case ErrorCode.WrongNumberReceivedBytes:
+ case ErrorCode.SendData:
+ case ErrorCode.ReadData:
+ case ErrorCode.WriteData:
+ lgError($"Errore in S7WriteBB su DB {DbNum}.{IndiceMem}: {errorCode.ToString()} | numByte: {Value.Length}| {Value.ValToBinString()}");
+ break;
+
+ default:
+ break;
+ }
+ answ = true;
+ }
+ catch (Exception exc)
+ {
+ lgError($"Eccezione in S7WriteBB: DbNum {DbNum}, IndiceMem: {IndiceMem}, numByte: {Value.Length}{Environment.NewLine}{exc}");
+ }
+ }
+#endif
+ sw.Stop();
+ }
+ }
+ return answ;
+ }
+
+ ///
+ /// Salvo in memblock il valore Int indicato con formattazione ModBus TCP
+ ///
+ /// Blocco memoria come byte[] dove scrivere
+ /// Posizione inizio scrittura
+ /// valore da scrivere
+ public void saveIntOnMemBlock(ref byte[] MemBlock, int startPos, string valore)
+ {
+ try
+ {
+ short valInt = 0;
+ short.TryParse(valore, out valInt);
+ byte[] strByte = S7.Net.Types.Int.ToByteArray(valInt);
+ int byteLen = 2;
+ Buffer.BlockCopy(strByte, 0, MemBlock, startPos, byteLen);
+ //var verifica = S7.Net.Types.String.FromByteArray(MemBlock);
+ }
+ catch (Exception exc)
+ {
+ lgError($"Errore in gestione scrittura INT {valore} alla posizione {startPos} byte{Environment.NewLine}{exc}");
+ }
+ }
+
+ ///
+ /// Salvo in memblock il valore Int indicato con formattazione ModBus TCP
+ ///
+ /// Blocco memoria come byte[] dove scrivere
+ /// Nome del parametro da recuperare da prodData x scrivere
+ /// Posizione inizio scrittura
+ public void saveIntOnMemBlock(ref byte[] MemBlock, string stringKey, int startPos)
+ {
+ if (currProdData.ContainsKey(stringKey))
+ {
+ try
+ {
+ string valore = currProdData[stringKey];
+ saveIntOnMemBlock(ref MemBlock, startPos, valore);
+ }
+ catch (Exception exc)
+ {
+ lgError($"Errore in gestione scrittura INT {stringKey}{Environment.NewLine}{exc}");
+ }
+ }
+ }
+
+ ///
+ /// Salvo in memblock il valore stringa indicato con formattazione ModBus TCP
+ ///
+ /// Blocco memoria come byte[] dove scrivere
+ /// Posizione inizio scrittura
+ /// Valore scrivere
+ public void saveRealOnMemBlock(ref byte[] MemBlock, int startPos, string valore)
+ {
+ try
+ {
+ byte[] stringPar = new byte[2];
+
+ double valReal = 0;
+ double.TryParse(valore, out valReal);
+ byte[] strByte = S7.Net.Types.Double.ToByteArray(valReal);
+ int byteLen = 4;
+ Buffer.BlockCopy(strByte, 0, MemBlock, startPos, byteLen);
+ //var verifica = S7.Net.Types.String.FromByteArray(MemBlock);
+ }
+ catch (Exception exc)
+ {
+ lgError($"Errore in gestione scrittura REAL {valore} alla posizione {startPos} byte{Environment.NewLine}{exc}");
+ }
+ }
+
+ ///
+ /// Salvo in memblock il valore stringa indicato con formattazione ModBus TCP
+ ///
+ /// Blocco memoria come byte[] dove scrivere
+ /// Valore scrivere
+ /// Posizione inizio scrittura
+ public void saveRealOnMemBlock(ref byte[] MemBlock, string stringKey, int startPos)
+ {
+ if (currProdData.ContainsKey(stringKey))
+ {
+ try
+ {
+ string valore = currProdData[stringKey];
+ saveRealOnMemBlock(ref MemBlock, startPos, valore);
+ }
+ catch (Exception exc)
+ {
+ lgError($"Errore in gestione scrittura REAL {stringKey}{Environment.NewLine}{exc}");
+ }
+ }
+ }
+
+ ///
+ /// Effettua salvataggio in LUT del valore ricevuto (double)
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void saveValue(ref Dictionary outVal, double valore, string chiave)
+ {
+ //check obj preliminare
+ if (outVal == null)
+ {
+ outVal = new Dictionary();
+ }
+ bool scaduto = stackVal_TSVC(chiave, valore);
+ // recupero VC
+ valore = getVal_TSVC(chiave, scaduto);
+ if (scaduto)
+ {
+ outVal.Add(chiave, $"{valore}");
+ }
+ LastTSVC[chiave] = valore;
+ }
+
+ ///
+ /// Override connessione
+ ///
+ public override void tryConnect()
+ {
+ bool doLog = (verboseLog || periodicLog);
+ lgInfo("ModBus TCP: tryConnect step 01");
+ if (!connectionOk)
+ {
+ // SE è necessario refresh...
+ if (needRefresh)
+ {
+ lgInfo("ModBus TCP: tryConnect step 02");
+
+ // reimporto parametri PLC se necessario...
+ setParamPlc();
+ }
+ lgInfo("ModBus TCP: tryConnect step 03");
+
+ // controllo che il ping sia stato tentato almeno pingTestSec fa...
+ if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec"))
+ {
+ if (doLog)
+ {
+ lgInfo("ModBus TCP: ConnKO - tryConnect");
+ }
+ lgInfo("ModBus TCP: tryConnect step 04");
+
+ // in primis salvo data ping...
+ lastPING = DateTime.Now;
+ // se passa il ping faccio il resto...
+ if (testPingMachine == IPStatus.Success)
+ {
+ string szStatusConnection = "ND";
+ try
+ {
+ // ora provo connessione...
+ parentForm.commPlcActive = true;
+ currPLC.Connect();
+ szStatusConnection = "OPEN";
+ parentForm.commPlcActive = false;
+ connectionOk = currPLC.Connected;
+ lgInfo($"StatusConnection: {szStatusConnection}");
+ // refresh stato allarmi!!!
+ if (connectionOk)
+ {
+ if (adpRunning)
+ {
+ lgInfo($"Connessione OK: {connectionOk} | adpRunning: {adpRunning}");
+ }
+ }
+ else
+ {
+ lgError("Impossibile procedere, connessione mancante...");
+ }
+ }
+ catch (Exception exc)
+ {
+ lgFatal($"Errore in TryConnect adapter ModBusTCP | szStatusConnection {szStatusConnection}{Environment.NewLine}{exc}");
+ connectionOk = false;
+ needRefresh = true;
+ }
+ }
+ else
+ {
+ // loggo no risposta ping ...
+ connectionOk = false;
+ if (doLog)
+ {
+ lgInfo($"Attenzione: ModBusTCP controllo PING fallito per IP {cIobConf.cncIpAddr}");
+ }
+ }
+ }
+ }
+ // se non è ancora connesso faccio procesisng memoria caso disconnesso...
+ if (!connectionOk)
+ {
+ // processo semafori ed invio...
+ processMemoryDiscon();
+ }
+ }
+
+ ///
+ /// Override disconnessione
+ ///
+ public override void tryDisconnect()
+ {
+ if (connectionOk)
+ {
+ string szStatusConnection = "";
+ try
+ {
+ currPLC.Disconnect();
+ connectionOk = false;
+ lgInfo(szStatusConnection);
+ lgInfo("Effettuata disconnessione adapter ModBusTCP!");
+ }
+ catch (Exception exc)
+ {
+ lgFatal(exc, "Errore nella disconnessione dall'adapter ModBusTCP");
+ }
+ }
+ else
+ {
+ lgError("IMPOSSIBILE effettuare disconnessione ModBusTCP: Connessione non disponibile...");
+ }
+ }
+
+ #endregion Public Methods
}
}
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/IobModbusTCPHam.cs b/IOB-WIN-NEXT/IobModbusTCPHam.cs
new file mode 100644
index 00000000..f98c9cbb
--- /dev/null
+++ b/IOB-WIN-NEXT/IobModbusTCPHam.cs
@@ -0,0 +1,421 @@
+using EasyModbus;
+using IOB_UT_NEXT;
+using MapoSDK;
+using Newtonsoft.Json;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Net.NetworkInformation;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace IOB_WIN_NEXT
+{
+ /* --------------------------------------------------------------------------------
+ * Controlli ModBusTCP COMECA
+ * - protocollo ModBus TCP HAM
+ * - specifico comportamento impianti HAM Pizzaferri
+ *
+ * STRUTTURA MEMORIA a banchi di byte, convertiti successivamente in bit/int/real:
+ * lettura: xxx byte,
+ * scrittura yyy byte
+ * G:\Drive condivisi\30_Clienti\Pizzaferri\Impianti\HAM
+ * *
+ * -------------------------------------------------------------------------------- */
+
+ public class IobModbusTCPHam : IobModbusTCP
+ {
+ #region Public Constructors
+
+ /// Classe base con i metodi x ModBusTCP
+ ///
+ ///
+ ///
+ public IobModbusTCPHam(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf)
+ {
+ lgInfo("NEW IOB ModBus TCP HAM");
+
+ // provo lettura una prima volta i dati DYN
+ if (currPLC.Connected)
+ {
+ try
+ {
+ processDynData();
+ }
+ catch (Exception exc)
+ { }
+ }
+ }
+
+ #endregion Public Constructors
+
+ #region Protected Properties
+
+ protected bool hasAlarms
+ {
+ get
+ {
+ bool answ = false;
+#if false
+ int numErrors = 0;
+ uint currStatus = 0;
+ if (alarmMaps != null)
+ {
+ // leggo a ciclo le aree degli allarmi CONFIGURATI, se ne trovo --> segnalo allarme...
+ foreach (var item in alarmMaps)
+ {
+ // in primis decremento eventuali blink...
+ item.decreaseBlinkCounter();
+ // banchi in WORD (2 byte) --> scompongo
+ for (int i = 0; i < item.size / 2; i++)
+ {
+ currStatus = S7.Net.Types.Counter.FromByteArray(RawInput.Skip(item.index + 2 * i).Take(2).ToArray());
+ // verifico SE sia variato...
+ if (item.isChanged(i, currStatus))
+ {
+ numErrors++;
+ answ = true;
+ // registro gli allarmi attivi e trasmetto...
+ if (sendAlarmVariations(item.memAddr, i, item.alarmsState[i], currStatus))
+ {
+ // se inviato --> salvo stato da current...
+ item.updStatusVal(i, currStatus);
+ }
+ }
+ }
+ }
+ }
+#endif
+
+ return answ;
+ }
+ }
+
+ #endregion Protected Properties
+
+ #region Private Methods
+
+ private void testRead()
+ {
+ //Ip-Address and Port of Modbus-TCP-Server
+ //currPLC = new ModbusClient(cIobConf.cncIpAddr, 502);
+ ////Connect to Server
+ //currPLC.Connect();
+ //modbusClient.WriteMultipleCoils(4, new bool[] { true, true, true, true, true, true, true, true, true, true }); //Write Coils starting with Address 5
+ //bool[] readCoils = modbusClient.ReadCoils(9, 10); //Read 10 Coils from Server, starting with address 10
+ //int[] readHoldingRegisters = currPLC.ReadHoldingRegisters(0, 34); //Read 10 Holding Registers from Server, starting with Address 1
+
+ int[] readHR1000 = currPLC.ReadHoldingRegisters(0, 100); //Read 10 Holding Registers from Server, starting with Address 1
+
+ //// Console Output
+ //for (int i = 0; i < readCoils.Length; i++)
+ // Console.WriteLine("Value of Coil " + (9 + i + 1) + " " + readCoils[i].ToString());
+
+ for (int i = 0; i < readHR1000.Length / 2; i++)
+ {
+ Console.WriteLine($"Value of HoldingRegister {(i)} | {readHR1000[i]} / {readHR1000[i + 1]}");
+ int[] thisSet = new int[2];
+ Array.Copy(readHR1000, i, thisSet, 0, 2);
+ Console.WriteLine($"Convert val HoldingRegister {(i)} | {ModbusClient.ConvertRegistersToFloat(thisSet)}");
+ }
+ //Console.Write("Press any key to continue . . . ");
+ //Console.ReadKey(true);
+ }
+
+ #endregion Private Methods
+
+ #region Protected Methods
+
+ ///
+ /// Effettua decodifica aree memoria alla bitmap usata x MAPO/GWMS
+ /// - per lo scopo specifico IN REALTA' non conta lo stato macchina.... ma lo inviamo lo stesso
+ ///
+ protected override void decodeToBaseBitmap()
+ {
+ // init a zero...
+ B_input = 0;
+
+ /* -----------------------------------------------------
+ * bitmap MAPO STANDARD
+ * B0: POWER_ON
+ * B1: RUN
+ * B2: pzCount
+ * B3: allarme
+ *
+ ----------------------------------------------------- */
+
+ var MemInt = new byte[2];
+
+ int byteSignals = 0;
+ // bit 0 (poweron) imposto a 1 SE connected...
+ if (currPLC.Connected)
+ {
+ byteSignals += (1 << 0);
+ }
+
+ // processo dagli stati + gravi...
+ if (hasAlarms)
+ {
+ byteSignals += (1 << 3);
+ }
+ else
+ {
+ byteSignals += (1 << 1);
+ }
+
+ // salvo!
+ B_input = byteSignals;
+ }
+
+ ///
+ /// effettua il setup dei memblock da gestire (NON leggo intera memoria ma tanti blocchi...)
+ ///
+ protected override void setupMemBlocks()
+ {
+ // da calcolare... ora setup cablato...
+ memSetR.Add(1, 34);
+ }
+
+ #endregion Protected Methods
+
+ #region Public Methods
+
+ ///
+ /// Processo i task richiesti e li elimino dalla coda 1:1
+ ///
+ ///
+ public override Dictionary executeTasks(Dictionary task2exe)
+ {
+ lgInfo($"Chiamata executeTasks specifica ModBus TCP HAM: {task2exe.Count} task ricevuti");
+ // Verificare il protocollo: dovrebeb togliere SOLO i task eseguiti...
+ Dictionary taskDone = new Dictionary();
+ bool taskOk = false;
+ string taskVal = "";
+ // inizio con 1 byte di default
+ byte[] MemBlock = new byte[1];
+ string memAddrWrite = "";
+ if (task2exe != null)
+ {
+#if false
+ // cerco task specifici
+ foreach (var item in task2exe)
+ {
+ taskOk = false;
+ taskVal = "";
+ // converto richiesta in enum...
+ taskType tName = taskType.nihil;
+ Enum.TryParse(item.Key, out tName);
+ // controllo sulla KEY
+ switch (tName)
+ {
+ case taskType.nihil:
+ case taskType.fixStopSetup:
+ case taskType.forceResetPzCount:
+ case taskType.forceSetPzCount:
+ case taskType.setProg:
+ case taskType.sendWatchDogMes2Plc:
+ taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC";
+ break;
+
+ case taskType.setPzComm:
+ case taskType.setArt:
+ case taskType.setComm:
+ saveProdData(item);
+ int byteSize = 0;
+ // recupero dati da memMap... altrimenti NULLA
+ if (memMap.mMapWrite.ContainsKey(item.Key))
+ {
+ dataConf currMem = memMap.mMapWrite[item.Key];
+ byteSize = currMem.size;
+ memAddrWrite = currMem.memAddr;
+ MemBlock = new byte[byteSize];
+ if (currMem.tipoMem == plcDataType.String)
+ {
+ saveStringOnMemBlock(ref MemBlock, item.Key, 0, byteSize);
+ }
+ else if (currMem.tipoMem == plcDataType.DInt)
+ {
+ int valDInt = 0;
+ int.TryParse(item.Value, out valDInt);
+ MemBlock = S7.Net.Types.DInt.ToByteArray(valDInt);
+ }
+ else if (currMem.tipoMem == plcDataType.Int)
+ {
+ short valInt = 0;
+ short.TryParse(item.Value, out valInt);
+ MemBlock = S7.Net.Types.Int.ToByteArray(valInt);
+ }
+ }
+ else
+ {
+ lgError($"Errore: non trovata chiave write in memMap.mMapWrite per {item.Key}");
+ }
+ taskVal = item.Value;
+ break;
+
+ case taskType.startSetup:
+ // processo scrittura BIT su DB6.DBDW216
+ MemBlock = new byte[1];
+ MemBlock[0] = (byte)1;
+ memAddrWrite = "DB6.DBDW216";
+ break;
+
+ case taskType.stopSetup:
+ // processo scrittura BIT su DB6.DBDW216
+ MemBlock = new byte[1];
+ MemBlock[0] = (byte)0;
+ memAddrWrite = "DB6.DBDW216";
+ break;
+
+ case taskType.setParameter:
+ // richiedo da URL i parametri WRITE da popolare
+ lgInfo("Chiamata 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 = "SKIPPED | NO EXEC";
+ break;
+ }
+ // aggiungo task!
+ taskDone.Add(item.Key, taskVal);
+ if (!string.IsNullOrEmpty(memAddrWrite))
+ {
+ // scrivo!
+ taskOk = S7WriteBB(ref MemBlock, memAddrWrite);
+ }
+ if (!taskOk)
+ {
+ lgError($"Errore in S7WriteBB durante executeTasks: {item.Key} | {item.Value}");
+ }
+ }
+#endif
+ }
+ return taskDone;
+ }
+
+ ///
+ /// Override connessione
+ ///
+ public override void tryConnect()
+ {
+ bool doLog = (verboseLog || periodicLog);
+ lgInfo("ModBus TCP HAM: tryConnect step 01");
+ if (!connectionOk)
+ {
+ // SE è necessario refresh...
+ if (needRefresh)
+ {
+ lgInfo("ModBus TCP HAM: tryConnect step 02");
+
+ // reimporto parametri PLC se necessario...
+ setParamPlc();
+ }
+ lgInfo("ModBus TCP HAM: tryConnect step 03");
+
+ // controllo che il ping sia stato tentato almeno pingTestSec fa...
+ if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec"))
+ {
+ if (doLog)
+ {
+ lgInfo("ModBus TCP HAM: ConnKO - tryConnect");
+ }
+ lgInfo("ModBus TCP HAM: tryConnect step 04");
+
+ // in primis salvo data ping...
+ lastPING = DateTime.Now;
+ // se passa il ping faccio il resto...
+ if (testPingMachine == IPStatus.Success)
+ {
+ string szStatusConnection = "ND";
+ try
+ {
+ // ora provo connessione...
+ parentForm.commPlcActive = true;
+ currPLC.Connect();
+ szStatusConnection = "OPEN";
+ parentForm.commPlcActive = false;
+ connectionOk = currPLC.Connected;
+ lgInfo($"StatusConnection: {szStatusConnection}");
+ // refresh stato allarmi!!!
+ if (connectionOk)
+ {
+ if (adpRunning)
+ {
+ lgInfo($"Connessione OK: {connectionOk} | adpRunning: {adpRunning}");
+ }
+ }
+ else
+ {
+ lgError("Impossibile procedere, connessione mancante...");
+ }
+ }
+ catch (Exception exc)
+ {
+ lgFatal($"Errore in TryConnect adapter ModBusTCP | szStatusConnection {szStatusConnection}{Environment.NewLine}{exc}");
+ connectionOk = false;
+ needRefresh = true;
+ }
+ }
+ else
+ {
+ // loggo no risposta ping ...
+ connectionOk = false;
+ if (doLog)
+ {
+ lgInfo($"Attenzione: ModBusTCP controllo PING fallito per IP {cIobConf.cncIpAddr}");
+ }
+ }
+ }
+ }
+ // se non è ancora connesso faccio procesisng memoria caso disconnesso...
+ if (!connectionOk)
+ {
+ // processo semafori ed invio...
+ processMemoryDiscon();
+ }
+ }
+
+ ///
+ /// Override disconnessione
+ ///
+ public override void tryDisconnect()
+ {
+ if (connectionOk)
+ {
+ string szStatusConnection = "";
+ try
+ {
+ currPLC.Disconnect();
+ connectionOk = false;
+ lgInfo(szStatusConnection);
+ lgInfo("Effettuata disconnessione adapter ModBusTCP!");
+ }
+ catch (Exception exc)
+ {
+ lgFatal(exc, "Errore nella disconnessione dall'adapter ModBusTCP");
+ }
+ }
+ else
+ {
+ lgError("IMPOSSIBILE effettuare disconnessione ModBusTCP: Connessione non disponibile...");
+ }
+ }
+
+ #endregion Public Methods
+ }
+}
\ No newline at end of file
diff --git a/IOB-WIN-NEXT/IobSiemens.cs b/IOB-WIN-NEXT/IobSiemens.cs
index 62a86bfa..20ffab30 100644
--- a/IOB-WIN-NEXT/IobSiemens.cs
+++ b/IOB-WIN-NEXT/IobSiemens.cs
@@ -129,7 +129,7 @@ namespace IOB_WIN_NEXT
#region Protected Properties
///
- /// Dizionario delel ultime operazioni dis crittura per OGNI memoria (in modo che fa log ogni x sec...)
+ /// Dizionario delle ultime operazioni di scrittura per OGNI memoria (in modo che fa log ogni x sec...)
///
protected Dictionary lastMemWrite { get; set; } = new Dictionary();
@@ -416,7 +416,7 @@ namespace IOB_WIN_NEXT
}
///
- /// OVerride metodo x scrittura parametri su PLC
+ /// Override metodo x scrittura parametri su PLC
///
///
protected override void plcWriteParams(ref List updatedPar)
diff --git a/IOB-WIN-NEXT/MainForm.cs b/IOB-WIN-NEXT/MainForm.cs
index 71aaeec1..216bcc53 100644
--- a/IOB-WIN-NEXT/MainForm.cs
+++ b/IOB-WIN-NEXT/MainForm.cs
@@ -466,7 +466,10 @@ namespace IOB_WIN_NEXT
try
{
var currForm = (AdapterForm)item;
- numAttivi += currForm.iobObj.IobOnline ? 1 : 0;
+ if (currForm.iobObj != null)
+ {
+ numAttivi += currForm.iobObj.IobOnline ? 1 : 0;
+ }
}
catch
{ }
diff --git a/IOB-WIN-NEXT/packages.config b/IOB-WIN-NEXT/packages.config
index 4e1386f8..5d6bf35d 100644
--- a/IOB-WIN-NEXT/packages.config
+++ b/IOB-WIN-NEXT/packages.config
@@ -2,12 +2,12 @@
-
+
-
+
diff --git a/IOB-WIN-NEXT/specialConfig.cs b/IOB-WIN-NEXT/specialConfig.cs
index 6a867dcf..c85e2f94 100644
--- a/IOB-WIN-NEXT/specialConfig.cs
+++ b/IOB-WIN-NEXT/specialConfig.cs
@@ -2,6 +2,52 @@
namespace IOB_WIN_NEXT
{
+ ///
+ /// Implementazione classe connessione ModBus TCP,
+ /// comprensiva dei parametri delle aree di memoria
+ ///
+ public class connParamModBusTCP
+ {
+ #region Public Fields
+
+ ///
+ /// Indirizzo IP del PLC
+ ///
+ public string ipAdrr = "";
+
+ ///
+ /// Base area x lettura
+ ///
+ public string memAddrRead = "";
+
+ ///
+ /// Base area x scrittura
+ ///
+ public string memAddrWrite = "";
+
+ ///
+ /// Size memoria lettura
+ ///
+ public int memSizeRead = 0;
+
+ ///
+ /// Size memoria scrittura
+ ///
+ public int memSizeWrite = 0;
+
+ ///
+ /// Timeout ping
+ ///
+ public int pingMsTimeout = 250;
+
+ ///
+ /// Porta di comunicazione
+ ///
+ public int port;
+
+ #endregion Public Fields
+ }
+
///
/// Implementazione classe connessione SIEMENS con S7.net,
/// comprensiva dei parametri delle aree di memoria