diff --git a/IOB-WIN/AdapterForm.cs b/IOB-WIN/AdapterForm.cs index 96043859..f6744ecf 100644 --- a/IOB-WIN/AdapterForm.cs +++ b/IOB-WIN/AdapterForm.cs @@ -632,7 +632,7 @@ namespace IOB_WIN case tipoAdapter.SIEMENS: iobObj = new IobSiemens(this, IOBConf); start.Enabled = true; - break; + break; case tipoAdapter.SIEMENS_TORRI: iobObj = new IobSiemensTorri(this, IOBConf); start.Enabled = true; diff --git a/IOB-WIN/DATA/CONF/MAIN.ini b/IOB-WIN/DATA/CONF/MAIN.ini index f0e7d072..e39e0706 100644 --- a/IOB-WIN/DATA/CONF/MAIN.ini +++ b/IOB-WIN/DATA/CONF/MAIN.ini @@ -4,20 +4,21 @@ NAME=develop [SERVER] -MPIP=192.168.2.252 -;MPIP=10.74.82.219 +;MPIP=192.168.2.252 +MPIP=10.74.82.219 ;MPIP=192.168.1.7 MPURL=/MP/IO CMDREBO=/IOB/sendRebootGateway?GWIP= CMDIOB2CALL=/IOB/getIob2call?GWIP= [IOB] -; OSAI -STARTLIST=OSAI -; KAWASAKI +;--- OSAI --- +;STARTLIST=OSAI +;--- KAWASAKI --- ;STARTLIST=4000 - -; SIEMENS TORRI +;--- PUNZ SIEMENS --- +STARTLIST=SIEMENS +;--- SIEMENS TORRI --- ;STARTLIST=3013 MAXCNC=4 diff --git a/IOB-WIN/DATA/CONF/SIEMENS.ini b/IOB-WIN/DATA/CONF/SIEMENS.ini new file mode 100644 index 00000000..53b917d8 --- /dev/null +++ b/IOB-WIN/DATA/CONF/SIEMENS.ini @@ -0,0 +1,63 @@ +;Configurazione IOB-WIN +[IOB] +CNCTYPE=SIEMENS +PING_MS_TIMEOUT=500 + +[MACHINE] +VENDOR=Tecnomeccanica +MODEL=Punzonatrice 140.000 + +[CNC] +; Siemens (Tecnomeccanica) +IP=192.168.1.55 +CPUTYPE=S71200 +RACK=0 +SLOT=2 + +[SERVER] +MPIP=http://192.168.1.7 +MPURL=/MP/IO +CMDBASE=/IOB/input/ +CMDFLOG=/IOB/flog/ +CMDALIVE=/IOB +CMDENABLED=/IOB/enabled/ +CMDADV1=?valore= +CMDREBO=/sendReboot.aspx?idxMacchina= + +[MEMORY] +ADDR_READ=DB15.DBB0 +ADDR_WRITE=DB16.DBB0 +SIZE_READ=50 +SIZE_WRITE=50 +;BIT0=CONN +BIT1=DB15.DBB1 +;BIT2=PZCOUNT.STD.DB700.DBW22 +BIT3=DB15.DBB3 +BIT4=DB15.DBB4 + + +[BLINK] +;MAX_COUNTER_BLINK = 30 +MAX_COUNTER_BLINK = 15 +;bit0 = 0 +;bit1 = 0 +;bit2 = 1 +;bit3 = 1 +;bit4 = 1 +;bit5 = 0 +;bit6 = 0 +;bit7 = 0 +BLINK_FILT=0 +;BLINK_FILT=28 + +[OPTPAR] +;PZCOUNT_MODE=STD.[PAR/MEM].info|BIT.indice +; attenzione memoria sempre base BYTE (1604 DW --> 6416...) +PZCOUNT_MODE=STD.DB15.DBW22 +;PZ_CAD_MADDR=1602 +;PZ_REQ_MADDR=1603 +;PZ_DONE_MADDR=1604 +;PZ_GTOT_MADDR=1605 + +[BRANCH] +NAME=develop \ No newline at end of file diff --git a/IOB-WIN/IOB-WIN.csproj b/IOB-WIN/IOB-WIN.csproj index 35e01fca..b832e019 100644 --- a/IOB-WIN/IOB-WIN.csproj +++ b/IOB-WIN/IOB-WIN.csproj @@ -201,6 +201,9 @@ Always + + Always + Always diff --git a/IOB-WIN/IobSiemens.cs b/IOB-WIN/IobSiemens.cs index 0a37cb8e..6f481039 100644 --- a/IOB-WIN/IobSiemens.cs +++ b/IOB-WIN/IobSiemens.cs @@ -1,21 +1,1194 @@ -using System; +using IOB_UT; +using S7.Net; +using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; -using System.Text; -using System.Threading.Tasks; -using IOB_UT; +using System.Net; +using System.Net.NetworkInformation; namespace IOB_WIN { public class IobSiemens : IobGeneric { + #region area componenti base + /// - /// estende l'init della classe base con i metodi x Siemens + /// Configurazione valori da LEGGERE dal PLC + /// + public otherData[] memMapR; + /// + /// Configurazione valori da SCRIVERE nel PLC + /// + public otherData[] memMapW; + /// + /// Byte dimensione buffer dati memoria (da file map) + /// + public int numByte = 0; + /// + /// Lungh massima stringhe + /// + protected int maxStrChar = 20; + /// + /// Oggetto PLC da ri-utilizzare... + /// + protected Plc currPLC; + /// + /// indica se serva refresh parametri e quindi PLC... + /// + bool needRefresh = true; + /// + /// Oggetto cronometro x test vari... + /// + protected Stopwatch sw = new Stopwatch(); + /// + /// parametri di connessione + /// + protected connParamS7 parametri; + /// + /// Variabile x salvataggio iobConf locale + /// + protected IobConfiguration _IOBConf; + + #endregion + + #region area metodi lettura/Scrittura + + + /// + /// wrapper chiamata LETTURA in blocco MULTI BYTE... + /// + /// + /// + public bool S7ReadBB(ref byte[] Value) + { + bool answ = false; + sw.Restart(); + parentForm.commPlcActive = true; + if (testCncConn()) + { + // decodifico memoria... + memAreaSiemens memoria = new memAreaSiemens(parametri.memAddrRead); + int numByte = parametri.memSizeRead; + 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(string.Format("Mismatch dimensione array memoria: passato array di {0} byte, letti da S7 {1} byte", Value.Length, memByteRead.Length)); + } + string titolo = string.Format("READ BLOCK MEM BYTE: {0} --> {1} byte", parametri.memAddrRead, numByte); + if (verboseLog) + { + lgInfo(titolo); + } + + string contenuto = string.Format("Contenuto area memoria aquisita{0}", 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; + } + parentForm.commPlcActive = false; + sw.Stop(); + if (utils.CRB("recTime")) + { + TimingData.addResult(currIobConf.codIOB, string.Format("{0}|{1}", parametri.memAddrRead, numByte), sw.ElapsedTicks); + } + + return answ; + } + /// + /// wrapper chiamata SCRITTURA in blocco MULTI BYTE... + /// + /// + /// + public bool S7WriteBB(ref byte[] Value) + { + bool answ = false; + +#if false + sw.Restart(); + if (testCncConn()) + { + // decodifico memoria... + memAddress memoria = new memAddress(txtMemArea.Text); + int numByte = 1; + int.TryParse(txtMemSize.Text, out numByte); + Byte[] memByteRead = currPLC.ReadBytes(DataType.DataBlock, memoria.DbNum, memoria.indiceMem, numByte); + titolo = string.Format("READ BLOCK MEM BYTE: {0} --> {1} byte", txtMemArea.Text, numByte); + contenuto = ""; + 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); + } + showOut(titolo, contenuto); + } + sw.Stop(); + tslRTime.Text = string.Format("{0}", sw.Elapsed); +#endif + + +#if false + if (FANUC_ref.Connected) + { + try + { + parentForm.commPlcActive = true; + answ = FANUC_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); + } + catch + { } + } + parentForm.commPlcActive = false; +#endif + return answ; + } + + + #endregion + + /// + /// estende l'init della classe base con i metodi x Siemens specifici x Torri /// /// /// public IobSiemens(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { + // gestione invio ritardato contapezzi + pzCountDelay = utils.CRI("pzCountDelay"); + lastPzCountSend = DateTime.Now; + lastWarnODL = DateTime.Now; + // init conf + _IOBConf = IOBConf; + // inizializzo parametri... + parametri = new connParamS7() + { + ipAdrr = "127.0.0.1", + tipoCpu = CpuType.S7200, + slot = 0, + rack = 0, + pingMsTimeout = IOBConf.pingMsTimeout, + memAddrRead = "DB1.DBB0", + memAddrWrite = "DB2.DBB0", + memSizeRead = 0, + memSizeWrite = 0 + }; + setParamPlc(); } + /// + /// Test connessione CNC + /// + /// + private bool testCncConn() + { + bool answ = false; + IPStatus pingStatus = testPing(); + // se passa il ping faccio il resto... + if (pingStatus != IPStatus.Success) + { + lgError(string.Format("Errore in testCncConn: reply Status per {0}: {1}", parametri.ipAdrr, pingStatus)); + } + else + { + if (!currPLC.IsConnected) + { + currPLC.Open(); + } + + if (!currPLC.IsAvailable) + { + lgError(string.Format("PLC Siemens NON disponibile:{0} | {1}", currPLC.LastErrorCode, currPLC.LastErrorString)); + currPLC.ClearLastError(); + } + else + { + if (!currPLC.IsConnected) + { + lgError(string.Format("PLC Siemens NON connesso:{0} | {1}", currPLC.LastErrorCode, currPLC.LastErrorString)); + currPLC.ClearLastError(); + parentForm.updateComStats("NO connection"); + } + else + { + parentForm.updateComStats("Connection OK"); + answ = true; + } + } + } + return answ; + } + /// + /// test ping all'indirizzo impostato nei parametri + /// + /// + private IPStatus testPing() + { + IPStatus answ = IPStatus.Unknown; ; + IPAddress address; + PingReply reply; + Ping pingSender = new Ping(); + address = IPAddress.Loopback; + IPAddress.TryParse(parametri.ipAdrr, out address); + int pingMsTimeout = parametri.pingMsTimeout; + reply = pingSender.Send(address, pingMsTimeout); + answ = reply.Status; + return answ; + } + /// + /// Imposto parametri PLC + /// + private void setParamPlc() + { + // Creo oggetto connessione NC + parentForm.commPlcActive = true; + lgInfo("Start init Adapter SIEMENS TORRI all'IP {0} | CPU: {1} | R/S: {2}/{3} | --> IOB {4}", _IOBConf.cncIpAddr, _IOBConf.cpuType, _IOBConf.rack, _IOBConf.slot, _IOBConf.codIOB); + // SE è necessario refresh... + if (needRefresh) + { + lgInfo("Refreshing connection..."); + try + { + parametri.slot = _IOBConf.slot; + parametri.rack = _IOBConf.rack; + parametri.tipoCpu = (CpuType)Enum.Parse(typeof(CpuType), _IOBConf.cpuType); + parametri.ipAdrr = _IOBConf.cncIpAddr; + // leggo file init... + IniFile fIni = new IniFile(_IOBConf.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... + 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... + if (testPing() == IPStatus.Success) + { + try + { + currPLC = new Plc(parametri.tipoCpu, parametri.ipAdrr, parametri.rack, parametri.slot); + // disconnetto e connetto... + if (utils.CRB("verbose")) + { + lgInfo("SIEMENS-TORRI: tryDisconnect"); + } + + tryDisconnect(); + lgInfo("SIEMENS-TORRI: tryConnect"); + tryConnect(); + lgInfo("End init Adapter SIEMENS-TORRI"); + if (utils.CRB("verbose")) + { + lgInfo("S7+ CONNESSIONE AVVENUTA"); + } + } + catch (Exception exc) + { + lgError(exc, "Errore in INIT PLC S7+"); + } + needRefresh = false; + } + parentForm.commPlcActive = false; + // carico conf vettore memoria... + loadMemConf(); + if (utils.CRB("enableContapezzi")) + { + lgInfo("TORRI-SIEMENS: inizio gestione contapezzi"); + try + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + if (currIobConf.optPar.Count > 0 && currIobConf.optPar["PZCOUNT_MODE"] != "") + { + if (currIobConf.optPar["PZCOUNT_MODE"].StartsWith("STD")) + { + pzCntReload(); + // refresh associazione Macchina - IOB + sendM2IOB(); + // per adesso imposto lettura fanuc == contapezzi (poi farà vera lettura...) + lastCountCNC = contapezzi; + } + else + { + contapezzi = 0; + lgInfo("Contapezzi STD disabilitato: modalità {0}", currIobConf.optPar["PZCOUNT_MODE"]); + } + } + else + { + contapezzi = 0; + lgInfo("Parametro mancante PZCOUNT_MODE"); + } + } + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi TORRI-SIEMENS"); + } + } + } + } + /// + /// Override disconnessione + /// + public override void tryDisconnect() + { + if (connectionOk) + { + string szStatusConnection = ""; + try + { + currPLC.Close(); + connectionOk = false; + lgInfo(szStatusConnection); + lgInfo("Effettuata disconnessione adapter SIEMENS-TORRI!"); + } + catch (Exception exc) + { + lgFatal(exc, "Errore nella disconnessione dall'adapter SIEMENS-TORRI"); + } + } + else + { + lgError("IMPOSSIBILE effettuare disconnessione SIEMENS-TORRI: Connessione non disponibile..."); + } + } + /// + /// Override connessione + /// + public override void tryConnect() + { + if (!connectionOk) + { + // controllo che il ping sia stato tentato almeno pingTestSec fa... + if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec")) + { + if (verboseLog || periodicLog) + { + lgInfo("ConnKO - tryConnect"); + } + // in primis salvo data ping... + lastPING = DateTime.Now; + // se passa il ping faccio il resto... + if (testPing() == IPStatus.Success) + { + string szStatusConnection = ""; + try + { + // ora provo connessione... + parentForm.commPlcActive = true; + currPLC.Open(); + parentForm.commPlcActive = false; + lgInfo("szStatusConnection: " + szStatusConnection); + connectionOk = true; + // refresh stato allarmi!!! + if (connectionOk) + { + if (adpRunning) + { + // carico status allarmi (completo) + lgInfo("Inizio refresh completo stato allarmi..."); + forceAlarmCheck(); + lgInfo("Completato refresh completo stato allarmi!"); + } + else + { + lgInfo("Connessione OK"); + } + } + else + { + lgError("Impossibile procedere, connessione mancante..."); + } + } + catch (Exception exc) + { + lgFatal(string.Format("Errore nella connessione all'adapter SIEMENS-TORRI: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc)); + connectionOk = false; + lgInfo(string.Format("Eccezione in TryConnect, Adapter SIEMENS-TORRI NON running, pausa di {0} msec prima di ulteriori tentativi di riconnessione", utils.CRI("waitRecMSec"))); + } + } + else + { + // loggo no risposta ping ... + connectionOk = false; + if (verboseLog || periodicLog) + { + lgInfo(string.Format("Attenzione: SIEMENS-TORRI controllo PING fallito per IP {0}", currIobConf.cncIpAddr)); + } + } + } + } + // se non è ancora connesso faccio procesisng memoria caso disconnesso... + if (!connectionOk) + { + // processo semafori ed invio... + processMemoryDiscon(); + } + } + /// + /// Caricamento conf memoria DB del SIEMENS + /// + private void loadMemConf() + { + // carico conf memoria + loadConfFile(ref memMapR, filePath("MMapR"), 1, ref numByte); + loadConfFile(ref memMapW, filePath("MMapW"), 1, ref numByte); + } + /// + /// Restituisce path completo file da chaive configurazione + /// + /// chaive conf x file richiesto + /// + protected string filePath(string keyFile) + { + string answ = ""; + try + { + answ = string.Format(@"{0}\{1}", utils.confDir, utils.CRS(keyFile)); + } + catch (Exception exc) + { + lgError(exc, "Eccezione in recupero filePath"); + } + return answ; + } + + /// + /// Effettua vero processing contapezzi + /// + public override void processContapezzi() + { + if (utils.CRB("enableContapezzi")) + { + try + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + if (currIobConf.optPar.Count > 0 && currIobConf.optPar["PZCOUNT_MODE"] != "") + { + string memAddr = currIobConf.optPar["PZCOUNT_MODE"]; + if (memAddr.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddr = memAddr.Replace("STD.", ""); + object outputVal = new object(); + // verifico se si tratta di lettura area DB... formato tipo STD.DB700.DBB22.W + if (memAddr.StartsWith("DB")) + { + memAreaSiemens areaCounter = new memAreaSiemens(memAddr); + + if (utils.CRB("verbose")) + { + lgInfo("[0] area memoria: {1}.{2}.{3}", memAddr, areaCounter.DbNum, areaCounter.indiceMem, areaCounter.tipoMem); + } + // copio da blocco già letto... con switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato + switch (areaCounter.tipoMem) + { + case "B": + byte valB = RawInput[areaCounter.indiceMem]; + outputVal = valB; + break; + case "W": + ushort valW = S7.Net.Types.Word.FromByteArray(RawInput.Skip(areaCounter.indiceMem).Take(2).ToArray()); + outputVal = valW; + break; + case "DW": + uint valDW = S7.Net.Types.Word.FromByteArray(RawInput.Skip(areaCounter.indiceMem).Take(4).ToArray()); + outputVal = valDW; + if (utils.CRB("verbose")) + { + lgInfo("[2] outputVal contapezzi: {0}", outputVal); + } + + break; + default: + break; + } + // salvo... + Int32.TryParse(outputVal.ToString(), out lastCountCNC); + if (utils.CRB("verbose")) + { + lgInfo("[3] lastCountCNC contapezzi: {0}", lastCountCNC); + } + } + stopwatch.Stop(); + } + } + } + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi SIEMENS-TORRI"); + } + } + } + + #region da completare + + /// + /// Recupero dati override in formato dictionary + /// + /// + public override Dictionary getOverrides() + { + Dictionary outVal = new Dictionary(); + uint valDW = 0; + // !!!FARE!!! recuperare da conf memoria, ora HARD CODED + outVal.Add("FEED_OVER", RawInput[19].ToString()); + outVal.Add("RAPID_OVER", RawInput[20].ToString()); + outVal.Add("CURR_MODE", decodeCurrMode(RawInput[21])); + // recupero RPM pezzo/mola !!!FARE!!! cambio nome da config, qui sono 01:conduttrice e 02:operatrice (3013), mentre sono pezzo/mola nella V100 + valDW = S7.Net.Types.DWord.FromByteArray(RawInput.Skip(24).Take(4).ToArray()); + outVal.Add("RPM_01", valDW.ToString()); + valDW = S7.Net.Types.DWord.FromByteArray(RawInput.Skip(28).Take(4).ToArray()); + outVal.Add("RPM_02", valDW.ToString()); + return outVal; + } + + /// + /// lettura bit semafori + /// + public override void readSemafori() + { + base.readSemafori(); + if (verboseLog) + { + lgInfo("inizio read semafori"); + } + + parentForm.sIN = Semaforo.SV; + // 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(); + } + + /// + /// decodifica da bitmap il CURRENT MODE del controllo + /// + /// + /// + protected string decodeCurrMode(byte currModeBitmap) + { + string answ = ""; + if (verboseLog) + { + lgInfo(string.Format("CURR_MODE raw data: {0}", utils.binaryForm(currModeBitmap))); + } + // decodifica del MODO... B21 + /* + * CURR MODE diviso in BIT: + * B0 (01) = AUTO + * B1 (02) = MDI + * B2 (04) = JOG + * B3 (08) = TeachIN (associato a MDI --> 10) + * B4 (16) = Repos (associato a JOG --> 20) + * B5 (32) = RefPoint (associato a Jog --> 36) + * B6 (64) = Incr1 (associato a Jog --> 68) + * B7 (128) = Incr10 (associato a Jog --> -124 / 132 se UInt) + * */ + + // modi principali + if (currModeBitmap.SelectBit(0)) + { + answ = "AUTO"; + } + else if (currModeBitmap.SelectBit(1)) + { + answ = "MDI"; + } + else if (currModeBitmap.SelectBit(2)) + { + answ = "JOG"; + } + // modi accessori + if (currModeBitmap.SelectBit(3)) + { + answ += " | TEACH-IN"; + } + if (currModeBitmap.SelectBit(4)) + { + answ += " | REPOS"; + } + if (currModeBitmap.SelectBit(5)) + { + answ += " | REF-POINT"; + } + if (currModeBitmap.SelectBit(6)) + { + answ += " | INCR-1"; + } + if (currModeBitmap.SelectBit(7)) + { + answ += " | INCR-10"; + } + return answ; + } + /// + /// Decodifica il resto dell'area TORRI x i dati accessori (allarmi, ...) + /// + private void decodeOtherData() + { + if (verboseLog) + { + + } + } + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + private void decodeToBaseBitmap() + { + // init a zero... + B_input = 0; + // TORRI: leggo i primi 8 bit hard coded... + int byteSem = RawInput[0]; + // azzero i bit NON gestiti (2-5-6-7) + byteSem &= ~(1 << 2); + byteSem &= ~(1 << 5); + byteSem &= ~(1 << 6); + byteSem &= ~(1 << 7); + // salvo infine variabile bit x invio + B_input = byteSem; + + + string currODL = ""; + try + { + currODL = utils.callUrl(urlGetCurrODL); + lgInfo(string.Format("Lettura ODL, {0} --> {1}", currIdxODL, currODL)); + // provo a salvare nuovo ODL + int.TryParse(currODL, out currIdxODL); + } + catch (Exception exc) + { + if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) + { + lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL); + lastWarnODL = DateTime.Now; + } + } + if (currODL != null && currODL != "" && currODL != "0") + { + // ora processo il contapezzi... + // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + // verifico se variato contapezzi... e se passato ritardo minimo... + if (lastCountCNC > contapezzi) + { + // salvo nuovo contapezzi (incremento di 1...) + contapezzi++; + // salvo in semaforo! + B_input += 1 << 2; + } + // registro contapezzi + lgInfo(string.Format("Contapezzi SIEMENST-TORRI: {0} | Contapezzi interno {1}", lastCountCNC, contapezzi)); + + // 2018.06.26 NON resetto perché si deve resettare da solo da conteggio TC POST cambio ODL... +#if false + else if (contapezzi > lastCountCNC) // in questo caso resetto + { + contapezzi = lastCountCNC; + } +#endif + // invio a server contapezzi (aggiornato) + string retVal = utils.callUrl(urlSetPzCount + contapezzi.ToString()); + // verifica se tutto OK + if (retVal != "OK") + { + // errore salvataggio contapezzi + lgInfo(string.Format("Errore salvataggio Contapezzi SIEMENST-TORRI: {0} | Contapezzi interno {1} | Errore salvataggio: {2}", lastCountCNC, contapezzi, retVal)); + } + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + else + { + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + lgInfo(string.Format("Attenzione: mancanza ODL non procedo con gestione contapezzi. Contapezzi SIEMENST-TORRI: {0} | Contapezzi interno {1}", lastCountCNC, contapezzi)); + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + +#if false + // SE SI E' CONNESSO al PLC allora è 1=powerON... + if (connectionOk) + { + B_input += 1 << 0; + } + + // decodifico impiegando dictionary... cercando il TIPO di memoria & co... + string bKey = ""; + string bVal = ""; + char area; + // valore INVERTED (default è false) + bool invSignal = false; + string memArea = ""; + string[] memIdx; + int bitNum = 0; + int byteNum = 0; + int byte2check = 0; + for (int i = 0; i < 8; i++) + { + bKey = string.Format("BIT{0}", i); + // cerco se ci sia in LUT + if (signLUT.ContainsKey(bKey)) + { + // recupero nome variabile... + bVal = signLUT[bKey]; + // se l'area è PZCOUNT... processo PUNTUALMENTE il CONTAPEZZI... + if (bVal.StartsWith("PZCOUNT")) + { + // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + // verifico se variato contapezzi in area STD PAR6711... e se passato ritardo minimo... + if (lastCountCNC > contapezzi) + { + // salvo nuovo contapezzi (incremento di 1...) + contapezzi++; + // salvo in semaforo! + B_input += 1 << 2; + // registro contapezzi + lgInfo(string.Format("Contapezzi FANUC: {0} | Contapezzi interno {1}", lastCountCNC, contapezzi)); + } + else if (contapezzi > lastCountCNC) // in questo caso resetto + { + contapezzi = lastCountCNC; + } + // invio a server contapezzi (aggiornato) + utils.callUrl(urlSetPzCount + contapezzi.ToString()); + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + else // area "normale" byte.bit + { + // di norma è segnale normale => 1, altrimenti inverse => 0... + invSignal = false; + // cerco se sia inverse (ultimo char "!") --> registro e elimino char... + invSignal = bVal.StartsWith("!"); + // tolgo comunque inversione... + bVal = bVal.Replace("!", ""); + // recupero area... + area = bVal[0]; + // altrimenti decodifico area... + memArea = bVal.Substring(1, bVal.Length - 1); + memIdx = memArea.Split('.'); + // calcolo bit e byte number... + int.TryParse(memIdx[0], out byteNum); + if (memIdx.Length > 1) + { + int.TryParse(memIdx[1], out bitNum); + } + // in base al nome cerco in una delle aree.. e prendo solo solo quel bit di quel byte... + switch (area) + { + case 'G': + byte2check = MemBlockG[byteNum]; + break; + case 'R': + byte2check = MemBlockR[byteNum]; + break; + case 'X': + byte2check = MemBlockX[byteNum]; + break; + case 'Y': + byte2check = MemBlockY[byteNum]; + break; + default: + break; + } + // a secondo che sia segnale normale o inverso... + if (invSignal) + { + // controllo se il bit sia NON attivo (basso)... == 0... + if ((byte2check & (1 << bitNum)) == 0) + { + B_input += 1 << i; + } + } + else + { + // controllo se il bit sia attivo (alto)... != 0 + if ((byte2check & (1 << bitNum)) != 0) + { + B_input += 1 << i; + } + } + } + + } + } + // log opzionale! + if (verboseLog) lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); +#endif + + // log opzionale! + if (verboseLog) + { + lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); + } + } + /// + /// Recupero programma in lavorazione + /// + /// + public override string getPrgName() + { + string prgName = ""; +#if false + // recupero NUOVO prgName... + try + { + // recupero nome programma MAIN + prgName = utils.purgedChar2String(FANUC_ref.getPrgNameMain()); + // trimmo path del programma, ovvero "CNCMEMUSERPATH1" + prgName = prgName.Replace(utils.CRS("basePrgMemPath"), ""); + } + catch (Exception exc) + { + lgError(string.Format("Eccezione in recupero PRG NAME MAIN:{0}{1}", Environment.NewLine, exc)); + } +#endif + return prgName; + } + + /// + /// Recupero programma in lavorazione come Dictionary FANUC... + /// - SYSINFO: (prima KEY globale) TUTTI i valori separati da # (x fare check modifica) + /// - altre stringhe: ogni singolo parametro / valore + /// + /// + public override Dictionary getSysInfo() + { + Dictionary outVal = new Dictionary(); +#if false + inizio = DateTime.Now; + CncLib.Focas1.ODBSYS answ = FANUC_ref.getSysInfo(); + if (utils.CRB("recTime")) TimingData.addResult(string.Format("SYS-INFO"), DateTime.Now.Subtract(inizio).Ticks); + try + { + string cnc_type = new string(answ.cnc_type); + string mt_type = new string(answ.mt_type); + string series = new string(answ.series); + string version = new string(answ.version); + string axes = new string(answ.axes); + //short addInfo = answ.addinfo; + short max_axis = answ.max_axis; + // preparo i singoli valori dell'array... + outVal.Add("SYSINFO", string.Format("{0}#{1}#{2}#{3}#{4}#{5}", cnc_type, mt_type, series, version, axes, max_axis)); + outVal.Add("CNC", cnc_type); + outVal.Add("MTT", mt_type); + outVal.Add("SER", series); + outVal.Add("VER", version); + outVal.Add("AXS", string.Format("{0}|{1}", axes, max_axis)); + } + catch (Exception exc) + { + lgError(exc, "Errore in getSysInfo"); + } +#endif + return outVal; + } + /// + /// Esegue processing MODE (e nel contempo recupera altri dati dell'area G) + /// + public override void processMode() + { + if (utils.CRB("enableMode")) + { +#if false + try + { + inizio = DateTime.Now; + // leggo tutto da 0 a 43... + int memIndex = 0; + FanucMemRW(R, FANUC.MemType.G, memIndex, ref MemBlockG); + if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-G-AREA", MemBlockG.Length), DateTime.Now.Subtract(inizio).Ticks); + // verifico modo con valore corrente, se cambia aggiorno... + CNC_MODE newMode = decodeG43(MemBlockG[43]); + if (newMode != currMode) + { + // aggiorno! + currMode = newMode; + // conversione NUM MODE in descrizione da ENUM + string descrMode = Enum.GetName(typeof(CNC_MODE), currMode); + // accodo x invio + string sVal = string.Format("[CNC_MODE]{0}", descrMode); + // chiamo accodamento... + accodaFLog(sVal, qEncodeFLog("CNC_MODE", descrMode)); + } + } + catch (Exception exc) + { + lgError(exc, "Errore in process Mode G43"); + } +#endif + } + } +#if false + /// + /// decodifica il modo dai valori del byte G43 + /// + /// + /// + protected CNC_MODE decodeG43(byte currVal) + { + // hard coded da valori tabellari a MODI definiti in CNC_MODE... + CNC_MODE answ = CNC_MODE.ND; + switch (currVal) + { + case 0: + answ = CNC_MODE.MDI; + break; + case 1: + answ = CNC_MODE.MEN; + break; + case 3: + answ = CNC_MODE.EDIT; + break; + case 4: + answ = CNC_MODE.HANDLE_INC; + break; + case 5: + answ = CNC_MODE.JOG; + break; + case 6: + answ = CNC_MODE.TJOG; + break; + case 7: + answ = CNC_MODE.THND; + break; + case 33: + answ = CNC_MODE.RMT; + break; + case 133: + answ = CNC_MODE.REF; + break; + default: + answ = CNC_MODE.ND; + break; + } + return answ; + } +#endif + /// + /// Recupero dati dinamici... + /// + public override Dictionary getDynData() + { + Dictionary outVal = new Dictionary(); +#if false + inizio = DateTime.Now; + CncLib.Focas1.ODBDY2_1 answ = FANUC_ref.getAllDynData(); + if (utils.CRB("recTime")) TimingData.addResult(string.Format("PROC-DYN-DATA"), DateTime.Now.Subtract(inizio).Ticks); + try + { + string actf = answ.actf.ToString(); + string acts = answ.acts.ToString(); + //string numAlarm = answ.alarm.ToString(); + // preparo i singoli valori dell'array... + //outVal.Add("DYNDATA", string.Format("{0}#{1}#{2}", actf, acts, numAlarm)); + outVal.Add("DYNDATA", string.Format("FEED {0}#SPEED_RPM {1}", actf, acts)); + if (utils.CRB("SendFeedSpeed")) + { + outVal.Add("FEED", actf); + outVal.Add("SPEED_RPM", acts); + //outVal.Add("NUM_ALARM", numAlarm); + } + if (utils.CRB("SendAxPos")) + { + // salvo le posizioni... + CncLib.Focas1.FAXIS posAx = answ.pos; + int[] currPosAbs = posAx.absolute; + int i = 0; + foreach (var item in currPosAbs) + { + i++; + outVal.Add(string.Format("POS_{0:00}", i), item.ToString()); + } + } + } + catch (Exception exc) + { + lgError(exc, "Errore in getDynData"); + } +#endif + return outVal; + } + + /// + /// Override salvataggio valori in memoria... + /// + /// tipo di DUMP + public override void saveMemDump(dumpType tipo) + { +#if false + dump_MemAreaD(); + dump_MemAreaY(); +#endif + } + /// + /// Dump PERIODICO area D della memoria + /// + /// area memoria di partenza + /// + private void dump_MemAreaD(int memIndex, int memSyzeByte) + { + // leggo TUTTI i 9999 byte della memoria D... + byte[] MemBlockD = new byte[memSyzeByte]; + stopwatch.Restart(); + if (verboseLog) + { + lgInfo("START MemDump AreaD"); + } +#if false + FanucMemRW(R, FANUC.MemType.D, memIndex, ref MemBlockD); + if (verboseLog) lgInfo("END MemDump AreaD"); + if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-MemDumpD", MemBlockD.Length), DateTime.Now.Subtract(inizio).Ticks); + // file out! + string nomeFile = ""; + Dictionary mappaValori = new Dictionary(); + // salvo in file i dati letti come DWord (4byte) + nomeFile = string.Format(@"{0}\SAMPLES\MemDump_D_DW_{1:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, DateTime.Now); + for (int i = 0; i < MemBlockD.Length / 4; i++) + { + mappaValori.Add(i.ToString("0000"), BitConverter.ToUInt32(MemBlockD, i * 4).ToString()); + } + utils.WritePlain(mappaValori, nomeFile); +#endif + } + /// + /// Dump area D della memoria + /// + private void dump_MemAreaD() + { + // faccio chaimate e salvo in file dump... + int memIndex = 0; + // leggo TUTTI i 9999 byte della memoria D... + byte[] MemBlockD = new byte[9999]; + stopwatch.Restart(); + if (verboseLog) + { + lgInfo("START MemDump AreaD"); + } +#if false + FanucMemRW(R, FANUC.MemType.D, memIndex, ref MemBlockD); + if (verboseLog) lgInfo("END MemDump AreaD"); + if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-MemDumpD", MemBlockD.Length), DateTime.Now.Subtract(inizio).Ticks); + // + string nomeFile = ""; + // salvo in file i dati letti come BYTE + nomeFile = string.Format(@"{0}\MemDump_D_Byte.dat", utils.dataDatDir); + Dictionary mappaValori = new Dictionary(); + for (int i = 0; i < MemBlockD.Length; i++) + { + mappaValori.Add(i.ToString("0000"), MemBlockD[i].ToString()); + } + utils.WritePlain(mappaValori, nomeFile); + + // salvo in file i dati letti come DWord (4byte) + nomeFile = string.Format(@"{0}\MemDump_D_DW.dat", utils.dataDatDir); + mappaValori = new Dictionary(); + for (int i = 0; i < MemBlockD.Length / 4; i++) + { + mappaValori.Add(i.ToString("0000"), BitConverter.ToUInt32(MemBlockD, i * 4).ToString()); + } + utils.WritePlain(mappaValori, nomeFile); + + // salvo in file i dati letti come DWord (4byte) + nomeFile = string.Format(@"{0}\MemDump_D_W.dat", utils.dataDatDir); + mappaValori = new Dictionary(); + for (int i = 0; i < MemBlockD.Length / 2; i++) + { + mappaValori.Add(i.ToString("0000"), BitConverter.ToUInt16(MemBlockD, i * 2).ToString()); + } + utils.WritePlain(mappaValori, nomeFile); +#endif + } + /// + /// Dump area Y della memoria + /// + private void dump_MemAreaY() + { + // faccio chaimate e salvo in file dump... + int memIndex = 0; + // leggo TUTTI i 9999 byte della memoria Y... + byte[] MemBlockY = new byte[10]; + stopwatch.Restart(); + if (verboseLog) + { + lgInfo("START MemDump AreaY"); + } +#if false + FanucMemRW(R, FANUC.MemType.Y, memIndex, ref MemBlockY); + if (verboseLog) lgInfo("END MemDump AreaY"); + if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-MemDumpY", MemBlockY.Length), DateTime.Now.Subtract(inizio).Ticks); + // + string nomeFile = ""; + // salvo in file i dati letti come BYTE + nomeFile = string.Format(@"{0}\MemDump_Y_Byte.dat", utils.dataDatDir); + Dictionary mappaValori = new Dictionary(); + for (int i = 0; i < MemBlockY.Length; i++) + { + mappaValori.Add(i.ToString("0000"), MemBlockY[i].ToString()); + } + utils.WritePlain(mappaValori, nomeFile); + + // salvo in file i dati letti come DWord (4byte) + nomeFile = string.Format(@"{0}\MemDump_Y_DW.dat", utils.dataDatDir); + mappaValori = new Dictionary(); + for (int i = 0; i < MemBlockY.Length / 4; i++) + { + mappaValori.Add(i.ToString("0000"), BitConverter.ToUInt32(MemBlockY, i * 4).ToString()); + } + utils.WritePlain(mappaValori, nomeFile); + + // salvo in file i dati letti come DWord (4byte) + nomeFile = string.Format(@"{0}\MemDump_Y_W.dat", utils.dataDatDir); + mappaValori = new Dictionary(); + for (int i = 0; i < MemBlockY.Length / 2; i++) + { + mappaValori.Add(i.ToString("0000"), BitConverter.ToUInt16(MemBlockY, i * 2).ToString()); + } + utils.WritePlain(mappaValori, nomeFile); +#endif + } + #endregion } } diff --git a/IOB-WIN/IobSiemensTorri.cs b/IOB-WIN/IobSiemensTorri.cs index 01dc522f..bbecdcb0 100644 --- a/IOB-WIN/IobSiemensTorri.cs +++ b/IOB-WIN/IobSiemensTorri.cs @@ -44,7 +44,7 @@ namespace IOB_WIN /// /// parametri di connessione /// - protected connParamS7Torri parametri; + protected connParamS7 parametri; /// /// Variabile x salvataggio iobConf locale /// @@ -178,7 +178,7 @@ namespace IOB_WIN // init conf _IOBConf = IOBConf; // inizializzo parametri... - parametri = new connParamS7Torri() + parametri = new connParamS7() { ipAdrr = "127.0.0.1", tipoCpu = CpuType.S7200, diff --git a/IOB-WIN/specialConfig.cs b/IOB-WIN/specialConfig.cs index de013531..43a1d416 100644 --- a/IOB-WIN/specialConfig.cs +++ b/IOB-WIN/specialConfig.cs @@ -3,25 +3,46 @@ namespace IOB_WIN { /// - /// Implementazione classe connessione SIEMENS con S7.net + /// Implementazione classe connessione SIEMENS con S7.net, + /// comprensiva dei parametri delle aree di memoria /// public class connParamS7 { + /// + /// Indirizzo IP del PLC + /// public string ipAdrr = ""; - + /// + /// Tipo CPU Siemens + /// public CpuType tipoCpu = CpuType.S7300; + /// + /// Slot comunicazione + /// public short slot = 0; + /// + /// Rack comunicazione + /// public short rack = 0; + /// + /// Timeout ping + /// public int pingMsTimeout = 250; - } - /// - /// Configurazione specifiche memoria x S7 Torri - /// - public class connParamS7Torri : connParamS7 - { + /// + /// 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; } }