using EasyModbus; using IOB_UT_NEXT; using MapoSDK; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Net.NetworkInformation; using System.Text; using System.Threading.Tasks; namespace IOB_WIN_NEXT { /* -------------------------------------------------------------------------------- * Controlli ModBusTCP COMECA * - protocollo ModBus TCP HAM * - specifico comportamento impianti HAM Pizzaferri * * STRUTTURA MEMORIA a banchi di byte, convertiti successivamente in bit/int/real: * lettura: xxx byte, * scrittura yyy byte * G:\Drive condivisi\30_Clienti\Pizzaferri\Impianti\HAM * * * -------------------------------------------------------------------------------- */ public class IobModbusTCPHam : IobModbusTCP { #region Public Constructors /// Classe base con i metodi x ModBusTCP /// /// /// public IobModbusTCPHam(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { lgInfo("NEW IOB ModBus TCP HAM"); // provo lettura una prima volta i dati DYN if (currPLC != null && currPLC.Connected) { try { processDynData(); } catch (Exception exc) { lgError($"Eccezione in processDynData iniziale x ModBus TCP HAM:{Environment.NewLine}{exc}"); } } } #endregion Public Constructors #region Protected Properties protected override bool hasAlarms { get { bool answ = false; int numErrors = 0; int currStatus = 0; int[] listInt; 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 array Int16 --> scompongo for (int i = 0; i < item.size / 2; i++) { listInt = readInputReg(item.index, item.size); currStatus = ModbusClient.ConvertRegistersToInt(listInt); //currStatus = listInt[0]; // verifico SE sia variato... confronto allarmi filtrato stile blink per bit status: // - allarmi che iniziano per # IGNORATI // - altri allarmi con un countdown da MAX_COUNTER_BLINK a 0 per il fronte di discesa if (item.isChanged(i, (uint)currStatus)) { answ = currStatus > 0; if (answ) { numErrors++; } // registro gli allarmi attivi e trasmetto... if (sendAlarmVariations(item.memAddr, i, item.alarmsState[i], (uint)(item.alarmsMask[i] & currStatus), item.messages)) { // se inviato --> salvo stato da current... item.updStatusVal(i, (uint)(item.alarmsMask[i] & currStatus)); } } } } } return answ; } } #endregion Protected Properties #region Private Methods private void testRead() { //Ip-Address and Port of Modbus-TCP-Server //currPLC = new ModbusClient(cIobConf.cncIpAddr, 502); ////Connect to Server //currPLC.Connect(); //modbusClient.WriteMultipleCoils(4, new bool[] { true, true, true, true, true, true, true, true, true, true }); //Write Coils starting with Address 5 //bool[] readCoils = modbusClient.ReadCoils(9, 10); //Read 10 Coils from Server, starting with address 10 //int[] readHoldingRegisters = currPLC.ReadHoldingRegisters(0, 34); //Read 10 Holding Registers from Server, starting with Address 1 int[] readHR1000 = currPLC.ReadHoldingRegisters(0, 100); //Read 10 Holding Registers from Server, starting with Address 1 //// Console Output //for (int i = 0; i < readCoils.Length; i++) // Console.WriteLine("Value of Coil " + (9 + i + 1) + " " + readCoils[i].ToString()); for (int i = 0; i < readHR1000.Length / 2; i++) { Console.WriteLine($"Value of HoldingRegister {(i)} | {readHR1000[i]} / {readHR1000[i + 1]}"); int[] thisSet = new int[2]; Array.Copy(readHR1000, i, thisSet, 0, 2); Console.WriteLine($"Convert val HoldingRegister {(i)} | {ModbusClient.ConvertRegistersToFloat(thisSet)}"); } //Console.Write("Press any key to continue . . . "); //Console.ReadKey(true); } #endregion Private Methods #region Protected Methods /// /// Effettua decodifica aree memoria alla bitmap usata x MAPO/GWMS /// - per lo scopo specifico IN REALTA' non conta lo stato macchina.... ma lo inviamo lo stesso /// protected override void decodeToBaseBitmap() { // init a zero... B_input = 0; /* ----------------------------------------------------- * bitmap MAPO STANDARD * B0: POWER_ON * B1: RUN * B2: pzCount * B3: allarme * ----------------------------------------------------- */ var MemInt = new byte[2]; int byteSignals = 0; // bit 0 (poweron) imposto a 1 SE connected... if (currPLC.Connected) { byteSignals += (1 << 0); } // processo dagli stati + gravi... if (hasAlarms) { byteSignals += (1 << 3); } else { byteSignals += (1 << 1); } // salvo! B_input = byteSignals; } /// /// effettua il setup dei memblock da gestire (NON leggo intera memoria ma tanti blocchi...) /// protected override void setupMemBlocks() { // da calcolare... ora setup cablato... memSetR.Add(1, 34); } #endregion Protected Methods #region Public Methods /// /// 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 } }