From af0dcd1ce82acf10364f0885f7057d81fcde2cf8 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Sat, 25 Sep 2021 10:22:25 +0200 Subject: [PATCH 01/10] commentato parte modbus (uso std paramPLC --- IOB-UT-NEXT/ToMapo.cs | 70 +++++++++++++++++++++---------------------- 1 file changed, 34 insertions(+), 36 deletions(-) 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, ...) From c471d1dd3b58f7f47b4fef1bf66feb8087d12f1e Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Sat, 25 Sep 2021 11:35:15 +0200 Subject: [PATCH 02/10] Bozza conf HAM --- IOB-WIN-NEXT/DATA/CONF/PIZ04.ini | 19 +- IOB-WIN-NEXT/DATA/CONF/PIZ04.json | 450 ++++++++++++------------ IOB-WIN-NEXT/DATA/CONF/PIZ04_alarm.json | 246 ++++++------- 3 files changed, 360 insertions(+), 355 deletions(-) diff --git a/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini b/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini index 04480fbe..5f2afe0a 100644 --- a/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini +++ b/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini @@ -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,10 @@ 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=5046 +SIZE_WRITE=358 [BLINK] @@ -50,7 +47,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 @@ -62,11 +59,11 @@ FORCE_DYN_DATA=TRUE timerIntMs=20 ; 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..5d3b2acd 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": 1, + "minVal": 0, + "maxVal": 100 }, "MainPress": { - "name": "PT16", + "name": "PressSerb", "description": "Pressione Serbatoio", - "memAddr": "DB85.DBB28", + "memAddr": "40003", "tipoMem": "Real", "index": 28, "size": 4, "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 From aa18a31360facec93b6f5f0a81f6546196da7b2e Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Sat, 25 Sep 2021 11:35:21 +0200 Subject: [PATCH 03/10] Bozza TPC test HAM --- IOB-WIN-NEXT/IobModbusTCP.cs | 486 ++++++++++++++++++++++++++++++---- IOB-WIN-NEXT/IobSiemens.cs | 2 +- IOB-WIN-NEXT/specialConfig.cs | 46 ++++ 3 files changed, 480 insertions(+), 54 deletions(-) diff --git a/IOB-WIN-NEXT/IobModbusTCP.cs b/IOB-WIN-NEXT/IobModbusTCP.cs index 6be7f7c8..2b422082 100644 --- a/IOB-WIN-NEXT/IobModbusTCP.cs +++ b/IOB-WIN-NEXT/IobModbusTCP.cs @@ -1,9 +1,11 @@ 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; @@ -13,22 +15,72 @@ namespace IOB_WIN_NEXT { #region Protected Fields - protected string serverIp = "hampizzaferri.dyndns.org"; + protected ModbusClient currPLC; + + /// + /// 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; #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(); + // 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!"); + } + + // provo una lettura testRead(); } @@ -36,65 +88,26 @@ namespace IOB_WIN_NEXT #region Private Methods - private void testConf() + /// + /// effettua il setup dei memblock da gestire (NON leggo intera memoria ma tanti blocchi...) + /// + private void setupMemBlocks() { - BaseModbusConf.VarConf var01 = new BaseModbusConf.VarConf() - { - 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); - - // creo un area di memoria - BaseModbusConf demoConf = new BaseModbusConf() - { - MemoryList = DemoMem - }; - // salvo conf con json x compilare... - var rawData = JsonConvert.SerializeObject(demoConf); + // da calcolare... ora setup cablato... + memSetR.Add(1, 34); } private void testRead() { //Ip-Address and Port of Modbus-TCP-Server - ModbusClient modbusClient = new ModbusClient(serverIp, 502); + currPLC = new ModbusClient(cIobConf.cncIpAddr, 502); //Connect to Server - modbusClient.Connect(); + 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 = modbusClient.ReadHoldingRegisters(0, 34); //Read 10 Holding Registers from Server, starting with Address 1 + int[] readHoldingRegisters = currPLC.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(); + 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++) @@ -109,8 +122,375 @@ namespace IOB_WIN_NEXT } Console.Write("Press any key to continue . . . "); Console.ReadKey(true); + +#if false + //Disconnect from Server + currPLC.Disconnect(); +#endif } #endregion Private Methods + + #region Protected Methods + + /// + /// 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("ModBusTCP: tryDisconnect"); + } + tryDisconnect(); + + // lo ripeto x evitare che ci sia un loop... e tryConnect richiami la procedura corrente... + needRefresh = false; + lgInfo("ModBusTCP: tryConnect"); + tryConnect(); + lgInfo("End init Adapter ModBusTCP"); + if (isVerboseLog) + { + lgInfo("ModBusTCP 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("ModBusTCP: 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!"); + } + } + } + + #endregion Protected Methods + + #region Public Methods + + /// + /// Override connessione + /// + public override void tryConnect() + { + bool doLog = (verboseLog || periodicLog); + lgInfo("ModBusTCP: tryConnect step 01"); + if (!connectionOk) + { + // SE è necessario refresh... + if (needRefresh) + { + lgInfo("ModBusTCP: tryConnect step 02"); + + // reimporto parametri PLC se necessario... + setParamPlc(); + } + lgInfo("ModBusTCP: 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("ModBusTCP: ConnKO - tryConnect"); + } + lgInfo("ModBusTCP: 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..b82ab5ec 100644 --- a/IOB-WIN-NEXT/IobSiemens.cs +++ b/IOB-WIN-NEXT/IobSiemens.cs @@ -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/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 From 360c68a37c2af0785fb46c2b7737ecdac164e6ff Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Sat, 25 Sep 2021 11:46:48 +0200 Subject: [PATCH 04/10] Separazione classe base ModBus TCP e versione specifica HAM (iniziato) --- IOB-UT-NEXT/Enums.cs | 7 +- IOB-WIN-NEXT/AdapterForm.cs | 5 + IOB-WIN-NEXT/DATA/CONF/PIZ04.ini | 4 +- IOB-WIN-NEXT/IOB-WIN-NEXT.csproj | 1 + IOB-WIN-NEXT/IobModbusTCP.cs | 92 +++-- IOB-WIN-NEXT/IobModbusTCPHam.cs | 560 +++++++++++++++++++++++++++++++ 6 files changed, 613 insertions(+), 56 deletions(-) create mode 100644 IOB-WIN-NEXT/IobModbusTCPHam.cs 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-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 5f2afe0a..324a1cac 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] diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj index feee01e5..936dc541 100644 --- a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj +++ b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj @@ -175,6 +175,7 @@ + diff --git a/IOB-WIN-NEXT/IobModbusTCP.cs b/IOB-WIN-NEXT/IobModbusTCP.cs index 2b422082..7f77eded 100644 --- a/IOB-WIN-NEXT/IobModbusTCP.cs +++ b/IOB-WIN-NEXT/IobModbusTCP.cs @@ -11,6 +11,12 @@ using System.Threading.Tasks; namespace IOB_WIN_NEXT { + /* -------------------------------------------------------------------------------- + * Controlli ModBusTCP COMECA + * - protocollo ModBus TCP + * + * -------------------------------------------------------------------------------- */ + public class IobModbusTCP : IobGeneric { #region Protected Fields @@ -79,60 +85,22 @@ namespace IOB_WIN_NEXT { lgError("Impossibile avviare, IOBConf nullo/non valido!"); } - - // provo una lettura - testRead(); } #endregion Public Constructors - #region Private Methods + #region Protected Methods /// - /// effettua il setup dei memblock da gestire (NON leggo intera memoria ma tanti blocchi...) + /// 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 /// - private void setupMemBlocks() + protected virtual void decodeToBaseBitmap() { - // da calcolare... ora setup cablato... - memSetR.Add(1, 34); + // init a zero... + B_input = 0; } - 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 < readHoldingRegisters.Length; i++) - { - 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)); - } - Console.Write("Press any key to continue . . . "); - Console.ReadKey(true); - -#if false - //Disconnect from Server - currPLC.Disconnect(); -#endif - } - - #endregion Private Methods - - #region Protected Methods - /// /// Override metodo x scrittura parametri su PLC /// @@ -308,18 +276,18 @@ namespace IOB_WIN_NEXT // disconnetto e connetto... if (isVerboseLog) { - lgInfo("ModBusTCP: tryDisconnect"); + lgInfo("ModBus TCP: tryDisconnect"); } tryDisconnect(); // lo ripeto x evitare che ci sia un loop... e tryConnect richiami la procedura corrente... needRefresh = false; - lgInfo("ModBusTCP: tryConnect"); + lgInfo("ModBus TCP: tryConnect"); tryConnect(); lgInfo("End init Adapter ModBusTCP"); if (isVerboseLog) { - lgInfo("ModBusTCP CONNESSIONE AVVENUTA"); + lgInfo("ModBus TCP CONNESSIONE AVVENUTA"); } } catch (Exception exc) @@ -339,7 +307,7 @@ namespace IOB_WIN_NEXT bool disableByIob = (getOptPar("DISABLE_PZCOUNT") == "TRUE"); if ((enableByApp || enableByIob) && !(disableByIob)) { - lgInfo("ModBusTCP: inizio gestione contapezzi"); + lgInfo("ModBus TCP: inizio gestione contapezzi"); try { // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) @@ -379,37 +347,55 @@ namespace IOB_WIN_NEXT } } + /// + /// effettua il setup dei memblock da gestire (NON leggo intera memoria ma tanti blocchi...) + /// + protected virtual void setupMemBlocks() + { } + #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: {task2exe.Count} task ricevuti"); + // Verificare il protocollo: dovrebeb togliere SOLO i task eseguiti... + Dictionary taskDone = new Dictionary(); + return taskDone; + } + /// /// Override connessione /// public override void tryConnect() { bool doLog = (verboseLog || periodicLog); - lgInfo("ModBusTCP: tryConnect step 01"); + lgInfo("ModBus TCP: tryConnect step 01"); if (!connectionOk) { // SE è necessario refresh... if (needRefresh) { - lgInfo("ModBusTCP: tryConnect step 02"); + lgInfo("ModBus TCP: tryConnect step 02"); // reimporto parametri PLC se necessario... setParamPlc(); } - lgInfo("ModBusTCP: tryConnect step 03"); + 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("ModBusTCP: ConnKO - tryConnect"); + lgInfo("ModBus TCP: ConnKO - tryConnect"); } - lgInfo("ModBusTCP: tryConnect step 04"); + lgInfo("ModBus TCP: tryConnect step 04"); // in primis salvo data ping... lastPING = DateTime.Now; diff --git a/IOB-WIN-NEXT/IobModbusTCPHam.cs b/IOB-WIN-NEXT/IobModbusTCPHam.cs new file mode 100644 index 00000000..02cfd77c --- /dev/null +++ b/IOB-WIN-NEXT/IobModbusTCPHam.cs @@ -0,0 +1,560 @@ +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 Protected Fields + + protected ModbusClient currPLC; + + /// + /// 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; + + #endregion Protected Fields + + #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 una lettura + testRead(); + } + + #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 < readHoldingRegisters.Length; i++) + { + 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)); + } + Console.Write("Press any key to continue . . . "); + Console.ReadKey(true); + +#if true + //Disconnect from Server + currPLC.Disconnect(); +#endif + } + + #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; + } + + /// + /// Imposto parametri PLC + /// + protected override void setParamPlc() + { + // Creo oggetto connessione NC + parentForm.commPlcActive = true; + lgInfo($"Start init Adapter ModBus TCP HAM 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 HAM: tryDisconnect"); + } + tryDisconnect(); + + // lo ripeto x evitare che ci sia un loop... e tryConnect richiami la procedura corrente... + needRefresh = false; + lgInfo("ModBus TCP HAM: tryConnect"); + tryConnect(); + lgInfo("End init Adapter ModBusTCP"); + if (isVerboseLog) + { + lgInfo("ModBus TCP HAM 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 HAM: 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 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 From 992f8f457a64f745266c9c06a47bf4e19707ed4a Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Sat, 25 Sep 2021 12:31:27 +0200 Subject: [PATCH 05/10] update x gestione "stile siemens" dei dati da leggere da memoria --- IOB-WIN-NEXT/IobModbusTCP.cs | 543 +++++++++++++++++++++++++++++++++++ 1 file changed, 543 insertions(+) diff --git a/IOB-WIN-NEXT/IobModbusTCP.cs b/IOB-WIN-NEXT/IobModbusTCP.cs index 7f77eded..af654559 100644 --- a/IOB-WIN-NEXT/IobModbusTCP.cs +++ b/IOB-WIN-NEXT/IobModbusTCP.cs @@ -4,9 +4,11 @@ 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 @@ -23,6 +25,16 @@ namespace IOB_WIN_NEXT 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) /// @@ -38,6 +50,11 @@ namespace IOB_WIN_NEXT /// protected connParamModBusTCP parametri; + /// + /// Oggetto cronometro x test vari... + /// + protected Stopwatch sw = new Stopwatch(); + #endregion Protected Fields #region Public Constructors @@ -91,6 +108,13 @@ namespace IOB_WIN_NEXT #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 @@ -353,10 +377,83 @@ namespace IOB_WIN_NEXT 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 /// @@ -369,6 +466,452 @@ namespace IOB_WIN_NEXT return taskDone; } + /// + /// Recupero dati dinamici... + /// + 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 valBool = false; + double valore = 0; + string valString = ""; + // procedo x ogni valore configurato...... + foreach (var item in memMap.mMapRead) + { +#if false + // in primis DEVO determinare di quale TIPO di valore ho bisogno... + switch (item.Value.tipoMem) + { + case plcDataType.Boolean: + valBool = S7.Net.Types.Boolean.GetValue(RawInput[item.Value.index], item.Value.size); + break; + + case plcDataType.Int: + valore = ((double)S7.Net.Types.Int.FromByteArray(RawInput.Skip(item.Value.index).Take(item.Value.size).ToArray())) / item.Value.factor; + saveValue(ref outVal, valore, item.Key); + break; + + case plcDataType.DInt: + valore = ((double)S7.Net.Types.DInt.FromByteArray(RawInput.Skip(item.Value.index).Take(item.Value.size).ToArray())) / item.Value.factor; + saveValue(ref outVal, valore, item.Key); + break; + + case plcDataType.Word: + valore = ((double)S7.Net.Types.Word.FromByteArray(RawInput.Skip(item.Value.index).Take(item.Value.size).ToArray())) / item.Value.factor; + saveValue(ref outVal, valore, item.Key); + break; + + case plcDataType.DWord: + valore = ((double)S7.Net.Types.DWord.FromByteArray(RawInput.Skip(item.Value.index).Take(item.Value.size).ToArray())) / item.Value.factor; + saveValue(ref outVal, valore, item.Key); + break; + + case plcDataType.Real: + valore = S7.Net.Types.Double.FromByteArray(RawInput.Skip(item.Value.index).Take(item.Value.size).ToArray()) / item.Value.factor; + saveValue(ref outVal, valore, item.Key); + break; + + case plcDataType.String: + valString = S7.Net.Types.String.FromByteArray(RawInput.Skip(item.Value.index).Take(item.Value.size).ToArray()); + break; + + default: + break; + } +#endif + } + } + 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; + } + + /// + /// Effettua lettura semafori principale + /// Parametri da aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) + { + base.readSemafori(ref currDispData); + try + { + currDispData.semIn = Semaforo.SV; + + if (verboseLog) + { + lgInfo("inizio read semafori"); + } + // leggo TUTTI i byte configurati... + byte[] 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}"); + } + } + } + /// /// Override connessione /// From 57abf637d9e4a04faf70c7f1e88b9fdcb50a602b Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Sat, 25 Sep 2021 12:33:52 +0200 Subject: [PATCH 06/10] Ancora update conf ModBus --- IOB-WIN-NEXT/IobModbusTCP.cs | 69 ++++++++++++++++++++++++++++++++++++ IOB-WIN-NEXT/IobSiemens.cs | 2 +- 2 files changed, 70 insertions(+), 1 deletion(-) diff --git a/IOB-WIN-NEXT/IobModbusTCP.cs b/IOB-WIN-NEXT/IobModbusTCP.cs index af654559..45716fb7 100644 --- a/IOB-WIN-NEXT/IobModbusTCP.cs +++ b/IOB-WIN-NEXT/IobModbusTCP.cs @@ -106,6 +106,75 @@ namespace IOB_WIN_NEXT #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 static int getScaledInt(dataConf currMem) + { + int valInt; + // prima faccio eventuale fattore di scala... + int.TryParse(currMem.value, out valInt); + if (currMem.factor > 1) + { + valInt = valInt * currMem.factor; + } + + return valInt; + } + + private static uint getScaledUInt(dataConf currMem) + { + uint valUInt; + // prima faccio eventuale fattore di scala... + uint.TryParse(currMem.value, out valUInt); + if (currMem.factor > 1) + { + 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; + } + } + + #endregion Private Methods + #region Protected Methods /// diff --git a/IOB-WIN-NEXT/IobSiemens.cs b/IOB-WIN-NEXT/IobSiemens.cs index b82ab5ec..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(); From 3c758d43ff747fddede6f8750325f169ec649497 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Sat, 25 Sep 2021 12:40:35 +0200 Subject: [PATCH 07/10] Ancora update x ModBus TCP --- IOB-WIN-NEXT/DATA/CONF/PIZ04.ini | 3 +- IOB-WIN-NEXT/IobModbusTCP.cs | 20 ++++- IOB-WIN-NEXT/IobModbusTCPHam.cs | 142 ------------------------------- 3 files changed, 18 insertions(+), 147 deletions(-) diff --git a/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini b/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini index 324a1cac..15723160 100644 --- a/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini +++ b/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini @@ -26,7 +26,8 @@ CMDREBO=/IOB/sendReboot?idxMacchina= [MEMORY] ADDR_READ=40001 ADDR_WRITE=40401 -SIZE_READ=5046 +SIZE_READ=34 +;SIZE_READ=5046 SIZE_WRITE=358 diff --git a/IOB-WIN-NEXT/IobModbusTCP.cs b/IOB-WIN-NEXT/IobModbusTCP.cs index 45716fb7..c19697c4 100644 --- a/IOB-WIN-NEXT/IobModbusTCP.cs +++ b/IOB-WIN-NEXT/IobModbusTCP.cs @@ -635,6 +635,7 @@ namespace IOB_WIN_NEXT public override void readSemafori(ref newDisplayData currDispData) { base.readSemafori(ref currDispData); + byte[] MemBlock = new byte[2]; try { currDispData.semIn = Semaforo.SV; @@ -643,14 +644,25 @@ namespace IOB_WIN_NEXT { lgInfo("inizio read semafori"); } - // leggo TUTTI i byte configurati... - byte[] MemBlock = new byte[parametri.memSizeRead]; - bool fatto = S7ReadBB(ref MemBlock); - Buffer.BlockCopy(MemBlock, 0, RawInput, 0, parametri.memSizeRead); + + // 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, 0, parametri.memSizeRead); + } + + //// 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(); diff --git a/IOB-WIN-NEXT/IobModbusTCPHam.cs b/IOB-WIN-NEXT/IobModbusTCPHam.cs index 02cfd77c..5c2702c3 100644 --- a/IOB-WIN-NEXT/IobModbusTCPHam.cs +++ b/IOB-WIN-NEXT/IobModbusTCPHam.cs @@ -25,27 +25,6 @@ namespace IOB_WIN_NEXT public class IobModbusTCPHam : IobModbusTCP { - #region Protected Fields - - protected ModbusClient currPLC; - - /// - /// 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; - - #endregion Protected Fields - #region Public Constructors /// Classe base con i metodi x ModBusTCP @@ -185,127 +164,6 @@ namespace IOB_WIN_NEXT B_input = byteSignals; } - /// - /// Imposto parametri PLC - /// - protected override void setParamPlc() - { - // Creo oggetto connessione NC - parentForm.commPlcActive = true; - lgInfo($"Start init Adapter ModBus TCP HAM 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 HAM: tryDisconnect"); - } - tryDisconnect(); - - // lo ripeto x evitare che ci sia un loop... e tryConnect richiami la procedura corrente... - needRefresh = false; - lgInfo("ModBus TCP HAM: tryConnect"); - tryConnect(); - lgInfo("End init Adapter ModBusTCP"); - if (isVerboseLog) - { - lgInfo("ModBus TCP HAM 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 HAM: 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...) /// From 7f4671fe11cb997012aff0ad2b797a2ceaa45ddd Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Tue, 28 Sep 2021 08:21:09 +0200 Subject: [PATCH 08/10] Continuo implementazione ModBus --- IOB-WIN-NEXT/DATA/CONF/PIZ04.ini | 2 +- IOB-WIN-NEXT/DATA/CONF/PIZ04.json | 4 +- IOB-WIN-NEXT/IOB-WIN-NEXT.csproj | 2 +- IOB-WIN-NEXT/IobGeneric.cs | 3 +- IOB-WIN-NEXT/IobModbusTCP.cs | 82 +++++++++++++++++++++++++++---- IOB-WIN-NEXT/IobModbusTCPHam.cs | 2 +- IOB-WIN-NEXT/MainForm.cs | 5 +- IOB-WIN-NEXT/packages.config | 2 +- 8 files changed, 84 insertions(+), 18 deletions(-) diff --git a/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini b/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini index 15723160..b2c6e223 100644 --- a/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini +++ b/IOB-WIN-NEXT/DATA/CONF/PIZ04.ini @@ -57,7 +57,7 @@ ENABLE_DYN_DATA=TRUE FORCE_DYN_DATA=TRUE ; clock base (da 10ms) -timerIntMs=20 +timerIntMs=100 ; conf parametri memoria READ/WRITE PARAM_CONF=PIZ04.json diff --git a/IOB-WIN-NEXT/DATA/CONF/PIZ04.json b/IOB-WIN-NEXT/DATA/CONF/PIZ04.json index 5d3b2acd..beb146b0 100644 --- a/IOB-WIN-NEXT/DATA/CONF/PIZ04.json +++ b/IOB-WIN-NEXT/DATA/CONF/PIZ04.json @@ -52,8 +52,8 @@ "description": "Pressione Serbatoio", "memAddr": "40003", "tipoMem": "Real", - "index": 28, - "size": 4, + "index": 3, + "size": 2, "func": "MAX", "period": 60, "factor": 1, diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj index 936dc541..75fd1a6e 100644 --- a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj +++ b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj @@ -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 diff --git a/IOB-WIN-NEXT/IobGeneric.cs b/IOB-WIN-NEXT/IobGeneric.cs index 52ed95d7..0582df31 100644 --- a/IOB-WIN-NEXT/IobGeneric.cs +++ b/IOB-WIN-NEXT/IobGeneric.cs @@ -4072,7 +4072,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 c19697c4..af055825 100644 --- a/IOB-WIN-NEXT/IobModbusTCP.cs +++ b/IOB-WIN-NEXT/IobModbusTCP.cs @@ -563,7 +563,6 @@ namespace IOB_WIN_NEXT // procedo x ogni valore configurato...... foreach (var item in memMap.mMapRead) { -#if false // in primis DEVO determinare di quale TIPO di valore ho bisogno... switch (item.Value.tipoMem) { @@ -603,7 +602,6 @@ namespace IOB_WIN_NEXT default: break; } -#endif } } else @@ -628,6 +626,70 @@ namespace IOB_WIN_NEXT 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[] readInReg(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 @@ -645,14 +707,14 @@ namespace IOB_WIN_NEXT 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, 0, parametri.memSizeRead); - } + //// 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]; diff --git a/IOB-WIN-NEXT/IobModbusTCPHam.cs b/IOB-WIN-NEXT/IobModbusTCPHam.cs index 5c2702c3..31661323 100644 --- a/IOB-WIN-NEXT/IobModbusTCPHam.cs +++ b/IOB-WIN-NEXT/IobModbusTCPHam.cs @@ -36,7 +36,7 @@ namespace IOB_WIN_NEXT lgInfo("NEW IOB ModBus TCP HAM"); // provo una lettura - testRead(); + //testRead(); } #endregion Public Constructors 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..2004baf8 100644 --- a/IOB-WIN-NEXT/packages.config +++ b/IOB-WIN-NEXT/packages.config @@ -7,7 +7,7 @@ - + From 73c09ec3fa237045f531c489bb3f186b9d23d628 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Tue, 28 Sep 2021 08:21:48 +0200 Subject: [PATCH 09/10] Nuget update MapoSDK x tipo memorie ModBus --- IOB-WIN-NEXT/IOB-WIN-NEXT.csproj | 4 ++-- IOB-WIN-NEXT/packages.config | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj index 75fd1a6e..75b71d58 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.2808\lib\net40\MapoSDK.dll ..\packages\MTConnect.NET.2.9.1.28314\lib\net40\MTConnect-NET.dll diff --git a/IOB-WIN-NEXT/packages.config b/IOB-WIN-NEXT/packages.config index 2004baf8..485874d0 100644 --- a/IOB-WIN-NEXT/packages.config +++ b/IOB-WIN-NEXT/packages.config @@ -2,7 +2,7 @@ - + From 93535a3e6ce9f5c496b65bbea97a430fd196b129 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Tue, 28 Sep 2021 10:46:37 +0200 Subject: [PATCH 10/10] COmpletata prima release adapter ModBus HAM x Pizzaferri --- CVCncLib/CVCncLib.dll | Bin 967680 -> 967680 bytes IOB-UT-NEXT/IOB-UT-NEXT.csproj | 4 +- IOB-UT-NEXT/packages.config | 2 +- IOB-WIN-NEXT/DATA/CONF/PIZ04.json | 2 +- IOB-WIN-NEXT/IOB-WIN-NEXT.csproj | 4 +- IOB-WIN-NEXT/IobGeneric.cs | 17 +++- IOB-WIN-NEXT/IobModbusTCP.cs | 136 +++++++++++++++++++++++------- IOB-WIN-NEXT/IobModbusTCPHam.cs | 31 ++++--- IOB-WIN-NEXT/packages.config | 2 +- 9 files changed, 144 insertions(+), 54 deletions(-) diff --git a/CVCncLib/CVCncLib.dll b/CVCncLib/CVCncLib.dll index fa1d7911f7cf8612160978df887706d174042197..77ac5221039597180a4a8eac0b9a46d27b802fe4 100644 GIT binary patch delta 134 zcmZqZux{wEp3uR(abHklcWXCeYd2GCH*;$@OKUf4Yd2eKH+yS0M{74{Yd2SGH}}?V z9?OLSar>9E1=t#UPA>fXWARDu5A9bL@&GaK_A3kd{_yDljY?zy0wy4qVPs%7VaM4YfotEnE?6wSw0gnLo9$N?@&GaK_A3kd{_yDljY?zy0wy4qVPs% ..\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/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/DATA/CONF/PIZ04.json b/IOB-WIN-NEXT/DATA/CONF/PIZ04.json index beb146b0..4889aa31 100644 --- a/IOB-WIN-NEXT/DATA/CONF/PIZ04.json +++ b/IOB-WIN-NEXT/DATA/CONF/PIZ04.json @@ -43,7 +43,7 @@ "size": 2, "func": "MAX", "period": 60, - "factor": 1, + "factor": 280, "minVal": 0, "maxVal": 100 }, diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj index 75b71d58..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.14.2109.2808\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 diff --git a/IOB-WIN-NEXT/IobGeneric.cs b/IOB-WIN-NEXT/IobGeneric.cs index 0582df31..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; } } diff --git a/IOB-WIN-NEXT/IobModbusTCP.cs b/IOB-WIN-NEXT/IobModbusTCP.cs index af055825..01ba2870 100644 --- a/IOB-WIN-NEXT/IobModbusTCP.cs +++ b/IOB-WIN-NEXT/IobModbusTCP.cs @@ -535,8 +535,22 @@ namespace IOB_WIN_NEXT 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() { @@ -557,51 +571,91 @@ namespace IOB_WIN_NEXT if (memMap.mMapRead.Count > 0) { // inizializzo i valori - bool valBool = false; + bool[] listBool = new bool[1]; + int[] listInt = new int[2]; double valore = 0; - string valString = ""; // procedo x ogni valore configurato...... foreach (var item in memMap.mMapRead) { - // in primis DEVO determinare di quale TIPO di valore ho bisogno... - switch (item.Value.tipoMem) + // 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 plcDataType.Boolean: - valBool = S7.Net.Types.Boolean.GetValue(RawInput[item.Value.index], item.Value.size); + case modBusAddrType.Coil: + listBool = readCoil(item.Value.index, item.Value.size); + valore = listBool[0] ? 1 : 0; break; - case plcDataType.Int: - valore = ((double)S7.Net.Types.Int.FromByteArray(RawInput.Skip(item.Value.index).Take(item.Value.size).ToArray())) / item.Value.factor; - saveValue(ref outVal, valore, item.Key); + case modBusAddrType.DiscreteInput: + listBool = readDiscrInputs(item.Value.index, item.Value.size); + valore = listBool[0] ? 1 : 0; break; - case plcDataType.DInt: - valore = ((double)S7.Net.Types.DInt.FromByteArray(RawInput.Skip(item.Value.index).Take(item.Value.size).ToArray())) / item.Value.factor; - saveValue(ref outVal, valore, item.Key); + 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 plcDataType.Word: - valore = ((double)S7.Net.Types.Word.FromByteArray(RawInput.Skip(item.Value.index).Take(item.Value.size).ToArray())) / item.Value.factor; - saveValue(ref outVal, valore, item.Key); - 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.DWord: - valore = ((double)S7.Net.Types.DWord.FromByteArray(RawInput.Skip(item.Value.index).Take(item.Value.size).ToArray())) / item.Value.factor; - saveValue(ref outVal, valore, item.Key); - break; - - case plcDataType.Real: - valore = S7.Net.Types.Double.FromByteArray(RawInput.Skip(item.Value.index).Take(item.Value.size).ToArray()) / item.Value.factor; - saveValue(ref outVal, valore, item.Key); - break; - - case plcDataType.String: - valString = S7.Net.Types.String.FromByteArray(RawInput.Skip(item.Value.index).Take(item.Value.size).ToArray()); + 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 @@ -680,7 +734,7 @@ namespace IOB_WIN_NEXT /// /// /// - public int[] readInReg(int startAddr, int qty) + public int[] readInputReg(int startAddr, int qty) { int[] answ = new int[2]; if (currPLC.Connected) @@ -1055,6 +1109,30 @@ namespace IOB_WIN_NEXT } } + /// + /// 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 /// diff --git a/IOB-WIN-NEXT/IobModbusTCPHam.cs b/IOB-WIN-NEXT/IobModbusTCPHam.cs index 31661323..f98c9cbb 100644 --- a/IOB-WIN-NEXT/IobModbusTCPHam.cs +++ b/IOB-WIN-NEXT/IobModbusTCPHam.cs @@ -35,8 +35,16 @@ namespace IOB_WIN_NEXT { lgInfo("NEW IOB ModBus TCP HAM"); - // provo una lettura - //testRead(); + // provo lettura una prima volta i dati DYN + if (currPLC.Connected) + { + try + { + processDynData(); + } + catch (Exception exc) + { } + } } #endregion Public Constructors @@ -95,7 +103,7 @@ namespace IOB_WIN_NEXT //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[] 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 @@ -103,20 +111,15 @@ namespace IOB_WIN_NEXT //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++) + for (int i = 0; i < readHR1000.Length / 2; i++) { - Console.WriteLine("Value of HoldingRegister " + (i + 1) + " " + readHoldingRegisters[i].ToString()); + Console.WriteLine($"Value of HoldingRegister {(i)} | {readHR1000[i]} / {readHR1000[i + 1]}"); int[] thisSet = new int[2]; - Array.Copy(readHoldingRegisters, i, thisSet, 0, 2); - Console.WriteLine("Convert val HoldingRegister " + (i + 1) + " " + ModbusClient.ConvertRegistersToFloat(thisSet)); + 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); - -#if true - //Disconnect from Server - currPLC.Disconnect(); -#endif + //Console.Write("Press any key to continue . . . "); + //Console.ReadKey(true); } #endregion Private Methods diff --git a/IOB-WIN-NEXT/packages.config b/IOB-WIN-NEXT/packages.config index 485874d0..5d6bf35d 100644 --- a/IOB-WIN-NEXT/packages.config +++ b/IOB-WIN-NEXT/packages.config @@ -2,7 +2,7 @@ - +