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