diff --git a/IOB-WIN/IobFanuc.cs b/IOB-WIN/IobFanuc.cs index dfd80ea8..ffff3cfb 100644 --- a/IOB-WIN/IobFanuc.cs +++ b/IOB-WIN/IobFanuc.cs @@ -10,106 +10,70 @@ namespace IOB_WIN { public class IobFanuc : IobGeneric { - /// - /// Area memoria G (copia) - /// - protected byte[] MemBlockG = new byte[2]; - /// - /// Area memoria R (copia) - /// - protected byte[] MemBlockR = new byte[2]; - /// - /// Area memoria X (copia) - /// - protected byte[] MemBlockX = new byte[2]; - /// - /// Area memoria Y (copia) - /// - protected byte[] MemBlockY = new byte[2]; + #region Private Fields + /// /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO /// - Dictionary signLUT = new Dictionary(); + private Dictionary signLUT = new Dictionary(); + + #endregion Private Fields + + #region Protected Fields /// - /// wrapper chiamata lettura/scrittura SINGOLO BYTE... + /// Dati dell'area D /// - /// - /// - /// - /// - /// - public bool FanucMemRW(bool bWrite, FANUC.MemType MemType, Int32 memIndex, ref byte Value) - { - bool answ = false; - if (connectionOk) - { - if (FANUC_ref.Connected) - { - try - { - parentForm.commPlcActive = true; - answ = FANUC_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); - } - catch - { } - } - } - parentForm.commPlcActive = false; - return answ; - } + protected memAreaFanuc areaD; + /// - /// wrapper chiamata lettura/scrittura MULTI BYTE... + /// Dati dell'area PARameters /// - /// - /// - /// - /// - /// - public bool FanucMemRW(bool bWrite, FANUC.MemType MemType, Int32 memIndex, ref byte[] Value) - { - bool answ = false; - if (connectionOk) - { - if (FANUC_ref.Connected) - { - try - { - parentForm.commPlcActive = true; - answ = FANUC_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); - } - catch - { } - } - } - parentForm.commPlcActive = false; - return answ; - } + protected memAreaFanuc areaPAR; + + /// + /// Dati dell'area R + /// + protected memAreaFanuc areaR; + + /// + /// Dati dell'area X + /// + protected memAreaFanuc areaX; + + /// + /// Dati dell'area Y + /// + protected memAreaFanuc areaY; + /// /// Oggetto MAIN x connessione FANUC /// protected FANUC FANUC_ref; /// - /// Dati dell'area D + /// Area memoria G (copia) /// - protected memAreaFanuc areaD; + protected byte[] MemBlockG = new byte[2]; + /// - /// Dati dell'area PARameters + /// Area memoria R (copia) /// - protected memAreaFanuc areaPAR; + protected byte[] MemBlockR = new byte[2]; + /// - /// Dati dell'area R + /// Area memoria X (copia) /// - protected memAreaFanuc areaR; + protected byte[] MemBlockX = new byte[2]; + /// - /// Dati dell'area X + /// Area memoria Y (copia) /// - protected memAreaFanuc areaX; - /// - /// Dati dell'area Y - /// - protected memAreaFanuc areaY; + protected byte[] MemBlockY = new byte[2]; + + #endregion Protected Fields + + #region Public Constructors /// /// estende l'init della classe base... @@ -255,340 +219,10 @@ namespace IOB_WIN lgInfo("End init Adapter FANUC"); } + #endregion Public Constructors - /// - /// Processo i task richiesti e li elimino dalla coda 1:1 - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti... - Dictionary taskDone = new Dictionary(); - bool taskOk = false; - string taskVal = ""; - // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4 - foreach (var item in task2exe) - { - taskOk = false; - taskVal = ""; - // converto richiesta in enum... - taskType tName = taskType.nihil; - Enum.TryParse(item.Key, out tName); - switch (tName) - { - case taskType.nihil: - case taskType.fixStopSetup: - case taskType.forceResetPzCount: - case taskType.forceSetPzCount: - case taskType.setArt: - case taskType.setComm: - case taskType.setProg: - case taskType.sendWatchDogMes2Plc: - taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; - lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); - break; - case taskType.startSetup: - // reset contapezzi inizio setup - taskOk = resetcontapezziPLC(); - taskVal = taskOk ? "RESET: SETUP START" : "PZ RESET DISABLED | NO EXEC"; - lgInfo($"Chiamata startSetup: taskOk: {taskOk} | taskVal: {taskVal}"); - break; - case taskType.stopSetup: - // reset contapezzi fine setup SE ESPLICITAMENTE IMPOSTATO - if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET_stopSetup") == "TRUE") - { - taskOk = resetcontapezziPLC(); - } - taskVal = taskOk ? "RESET: SETUP END" : "PZ RESET DISABLED | NO EXEC"; - lgInfo($"Chiamata stopSetup: taskOk: {taskOk} | taskVal: {taskVal}"); - break; - default: - taskVal = "SKIPPED | NO EXEC"; - lgInfo($"Chiamata default senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); - break; - } - // aggiungo task! - taskDone.Add(item.Key, taskVal); - } - return taskDone; - } - /// - /// Effettua reset del contapezzi - /// - /// - public override bool resetcontapezziPLC() - { - bool answ = false; - // ...SE abilitato da conf IOB - if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET") == "TRUE") - { - // scrivo valore 0 x il contapezzi - try - { - // contapezzi ATTUALE - if (!string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) - { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) - string memAddr = getOptPar("PZCOUNT_MODE"); - if (memAddr.StartsWith("STD")) - { - // inizio verifica area memoria/parametro levando prima parte codice - memAddr = memAddr.Replace("STD.", ""); - // var di appoggio - int cntAddr = 0; - // var contapezzi a zero.... - object newVal = new object(); - newVal = 0; - // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 - if (memAddr.StartsWith("PAR.")) - { - // recupero parametro... - int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); - if (cntAddr == 0) - { - cntAddr = 6711; - } + #region Private Methods - // processo RESET contapezzi (lavorati) - stopwatch.Restart(); - FANUC_ref.F_RW_Param_Integer(true, cntAddr, 3, ref newVal); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("W{0}-PAR", 4), stopwatch.ElapsedTicks); - } - } - // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW - else - { - memAddressFanuc areaCounter = new memAddressFanuc(memAddr); - - if (isVerboseLog) - { - lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); - } - // leggo! - stopwatch.Restart(); - // switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato - switch (areaCounter.vType) - { - case "B": - byte valB = 0; - FANUC_ref.F_RW_Byte(true, areaCounter.mType, areaCounter.mPos, ref valB); - newVal = valB; - break; - case "D": - ushort valW = 0; - FANUC_ref.F_RW_Word(true, areaCounter.mType, areaCounter.mPos, ref valW); - newVal = valW; - break; - case "DW": - uint valDW = 0; - FANUC_ref.F_RW_DWord(true, areaCounter.mType, areaCounter.mPos, ref valDW); - break; - default: - break; - } - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("W-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); - } - } - stopwatch.Stop(); - } - } - } - catch (Exception exc) - { - lgError(exc, "Errore in RESET contapezzi FANUC"); - connectionOk = false; - } - answ = true; - } - return answ; - } - - /// - /// Override disconnessione - /// - public override void tryDisconnect() - { - if (connectionOk) - { - string szStatusConnection = ""; - try - { - FANUC_ref.Disconnect(ref szStatusConnection); - connectionOk = false; - // resetto timing! - TimingData.resetData(); - lgInfo(szStatusConnection); - lgInfo("Effettuata disconnessione adapter FANUC!"); - } - catch (Exception exc) - { - lgFatal(exc, "Errore nella disconnessione dall'adapter FANUC"); - } - } - else - { - lgError("IMPOSSIBILE effettuare disconnessione: 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("FANUC: ConnKO - tryConnect"); - } - // in primis salvo data ping... - lastPING = DateTime.Now; - // ora PING!!! - Ping pingSender = new Ping(); - IPAddress address = IPAddress.Loopback; - IPAddress.TryParse(cIobConf.cncIpAddr, out address); - PingReply reply = pingSender.Send(address, 100); - // se passa il ping faccio il resto... - if (reply.Status == IPStatus.Success) - { - string szStatusConnection = ""; - try - { - // ora provo connessione... - parentForm.commPlcActive = true; - FANUC_ref.Connect(ref szStatusConnection); - parentForm.commPlcActive = false; - lgInfo("szStatusConnection: " + szStatusConnection); - connectionOk = true; - // refresh stato allarmi!!! - if (connectionOk) - { - dtAvvioAdp = DateTime.Now; - if (adpRunning) - { - lgInfo("Connessione OK"); - } - } - else - { - lgError("Impossibile procedere, connessione mancante..."); - } - } - catch (Exception exc) - { - lgFatal(string.Format("Errore nella connessione all'adapter FANUC: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc)); - connectionOk = false; - lgInfo(string.Format("Eccezione in TryConnect, Adapter 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: controllo PING fallito per IP {0} - {1}", cIobConf.cncIpAddr, reply.Status)); - } - } - } - } - // se non è ancora connesso faccio procesisng memoria caso disconnesso... - if (!connectionOk) - { - // processo semafori ed invio... - processMemoryDiscon(); - } - } - /// - /// Effettua lettura semafori principale - /// Parametri da aggiornare x display in form - /// - public override void readSemafori(ref newDisplayData currDispData) - { - base.readSemafori(ref currDispData); - try - { - if (verboseLog) - { - lgInfo("inizio read semafori"); - } - - currDispData.semIn = Semaforo.SV; - // inizio letture, SEMPRE DA ZERO (possibile ottimizzazione...) - int memIndex = 0; - // controllo area R: se ha dati (> 0 byte) --> leggo! - if (MemBlockR.Length > 0) - { - stopwatch.Restart(); - FanucMemRW(R, FANUC.MemType.R, memIndex, ref MemBlockR); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-R", MemBlockR.Length), stopwatch.ElapsedTicks); - } - // log - if (verboseLog) - { - for (int i = 0; i < MemBlockR.Length; i++) - { - lgInfo(string.Format("MemBlockR{0}: {1}", i, utils.binaryForm(MemBlockR[i]))); - } - } - } - // controllo area X: se ha dati (> 0 byte) --> leggo! - if (MemBlockX.Length > 0) - { - stopwatch.Restart(); - FanucMemRW(R, FANUC.MemType.X, memIndex, ref MemBlockX); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-X", MemBlockX.Length), stopwatch.ElapsedTicks); - } - // log - if (verboseLog) - { - for (int i = 0; i < MemBlockX.Length; i++) - { - lgInfo(string.Format("MemBlockX{0}: {1}", i, utils.binaryForm(MemBlockX[i]))); - } - } - } - // controllo area Y: se ha dati (> 0 byte) --> leggo! - if (MemBlockY.Length > 0) - { - stopwatch.Restart(); - FanucMemRW(R, FANUC.MemType.Y, memIndex, ref MemBlockY); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-Y", MemBlockY.Length), stopwatch.ElapsedTicks); - } - // log - if (verboseLog) - { - for (int i = 0; i < MemBlockY.Length; i++) - { - lgInfo(string.Format("MemBlockY{0}: {1}", i, utils.binaryForm(MemBlockY[i]))); - } - } - } - stopwatch.Stop(); - // salvo il solo BYTE dell'input decifrando il semaforo... - decodeToBitmap(); - reportRawInput(ref currDispData); - } - catch (Exception exc) - { - lgError(string.Format("Eccezione in readSemafori:{0}{1}", Environment.NewLine, exc)); - connectionOk = false; - currDispData.semIn = Semaforo.SR; - } - } /// /// Effettua decodifica aree memoria alla bitmap usata x MAPO /// @@ -626,35 +260,47 @@ namespace IOB_WIN // se l'area è PZCOUNT... processo PUNTUALMENTE il CONTAPEZZI... if (bVal.StartsWith("PZCOUNT")) { - string currODL = ""; - try + // procedo SOLO SE è enabled IOB + if (IobOnline) { - currODL = utils.callUrl(urlGetCurrODL); - // solo SE HO un ODL... - if (string.IsNullOrEmpty(currODL) || currODL == "0") + try { - if (periodicLog) + currODL = utils.callUrl(urlGetCurrODL); + // solo SE HO un ODL... + if (string.IsNullOrEmpty(currODL) || currODL == "0") { - lgInfo(string.Format("Fanuc | Lettura ODL andata a vuoto: currODL: {0}", currODL)); + if (periodicLog) + { + lgInfo(string.Format("Fanuc | Lettura ODL andata a vuoto: currODL: {0}", currODL)); + } + } + else + { + // se variato o scaduto timeout log... + if (periodicLog || ($"{currIdxODL}" != currODL)) + { + lgInfo(string.Format("Fanuc | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); + } + // provo a salvare nuovo ODL + int.TryParse(currODL, out currIdxODL); } } - else + catch (Exception exc) { - // se variato o scaduto timeout log... - if (periodicLog || (currIdxODL.ToString() != currODL)) + if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) { - lgInfo(string.Format("Fanuc | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); + lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL); + lastWarnODL = DateTime.Now; } - // provo a salvare nuovo ODL - int.TryParse(currODL, out currIdxODL); } } - catch (Exception exc) + else { - if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) + // imposto currODL a vuoto! + currODL = ""; + if (periodicLog) { - lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL); - lastWarnODL = DateTime.Now; + lgInfo($"Fanuc | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); } } if (!string.IsNullOrEmpty(currODL) && currODL != "0") @@ -665,9 +311,8 @@ namespace IOB_WIN // se sono differenti MOSTRO... if (contapezziPLC != contapezziIOB) { - // registro contapezzi + // registro contapezzi lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - } // verifico se variato contapezzi... if (contapezziPLC > contapezziIOB) @@ -682,10 +327,10 @@ namespace IOB_WIN } // invio a server contapezzi (aggiornato) string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); - // verifica se tutto OK + // verifica se tutto OK if (retVal != contapezziIOB.ToString()) { - // errore salvataggio contapezzi + // errore salvataggio contapezzi lgInfo($"Errore salvataggio Contapezzi FANUC: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); // rileggo il counter pezzi da server pzCntReload(true); @@ -729,15 +374,19 @@ namespace IOB_WIN 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; } @@ -768,535 +417,9 @@ namespace IOB_WIN lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); } } - /// - /// Recupero programma in lavorazione - /// - /// - public override string getPrgName() - { - string prgName = ""; - // 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"), ""); - lgInfo("Current PROG: {0}", prgName); - } - catch (Exception exc) - { - lgError(string.Format("Eccezione in recupero PRG NAME MAIN:{0}{1}", Environment.NewLine, exc)); - connectionOk = false; - } - 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(); - stopwatch.Restart(); - CncLib.Focas1.ODBSYS answ = FANUC_ref.getSysInfo(); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("SYS-INFO"), stopwatch.ElapsedTicks); - } - - 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"); - connectionOk = false; - } - return outVal; - } - /// - /// Effettua vero processing contapezzi: - /// 6711: pezzi lavorati - /// 6712: pezzi lavorati totali - /// 6713: pezzi richiesti - /// - public override void processContapezzi() - { - if (utils.CRB("enableContapezzi")) - { - // procedo SOLO SE ho connessione... - if (connectionOk) - { - try - { - // controllo di AVERE parametri opzionali x conteggi vari - if (cIobConf.optPar.Count > 0) - { - // contapezzi ATTUALE - if (!string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) - { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) - string memAddr = getOptPar("PZCOUNT_MODE"); - if (memAddr.StartsWith("STD")) - { - // inizio verifica area memoria/parametro levando prima parte codice - memAddr = memAddr.Replace("STD.", ""); - // var di appoggio - int cntAddr = 0; - object outputVal = new object(); - // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 - if (memAddr.StartsWith("PAR.")) - { - // recupero parametro... - int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); - if (cntAddr == 0) - { - cntAddr = 6711; - } - - // processo parametro contapezzi (lavorati) - stopwatch.Restart(); - FANUC_ref.F_RW_Param_Integer(false, cntAddr, 3, ref outputVal); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-PAR", 4), stopwatch.ElapsedTicks); - } - - // salvo ultimo conteggio rilevato - int newVal = -1; - Int32.TryParse(outputVal.ToString(), out newVal); - contapezziPLC = newVal > -1 ? newVal : contapezziPLC; - } - // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW - else - { - memAddressFanuc areaCounter = new memAddressFanuc(memAddr); - - if (isVerboseLog) - { - lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); - } - - // leggo! - stopwatch.Restart(); - // switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato - switch (areaCounter.vType) - { - case "B": - byte valB = 0; - FANUC_ref.F_RW_Byte(false, areaCounter.mType, areaCounter.mPos, ref valB); - outputVal = valB; - break; - case "D": - ushort valW = 0; - FANUC_ref.F_RW_Word(false, areaCounter.mType, areaCounter.mPos, ref valW); - outputVal = valW; - break; - case "DW": - uint valDW = 0; - FANUC_ref.F_RW_DWord(false, areaCounter.mType, areaCounter.mPos, ref valDW); - if (isVerboseLog) - { - lgInfo("[1] valDW contapezzi: {0}", valDW); - } - - outputVal = valDW; - if (isVerboseLog) - { - lgInfo("[2] outputVal contapezzi: {0}", outputVal); - } - - break; - default: - break; - } - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); - } - - // salvo... - int newVal = -1; - Int32.TryParse(outputVal.ToString(), out newVal); - contapezziPLC = newVal > -1 ? newVal : contapezziPLC; - if (isVerboseLog) - { - lgInfo("[3] contapezziPLC contapezzi: {0}", contapezziPLC); - } - } - stopwatch.Stop(); - } - } - - } - } - catch (Exception exc) - { - lgError(exc, "Errore in contapezzi FANUC"); - connectionOk = false; - } - } - else - { - lgError("Errore: manca connessione in contapezzi FANUC"); - } - } - } - /// - /// Recupero altri counters se ci sono - /// - public override void processOtherCounters() - { - try - { - // controllo di AVERE parametri opzionali x conteggi vari - if (cIobConf.optPar.Count > 0) - { - string newVal = ""; -#if false - // controllo SE salvare contapezzo - if (getOptPar("PZCOUNT_MODE") != "") - { - sendOptVal("PZ_COUNT", contapezziPLC); - } -#endif - // controllo SE devo gestire contatore pezzi REQUESTED (lanciati) - if (!string.IsNullOrEmpty(getOptPar("PZREQ_MODE"))) - { - newVal = getValByParam("PZREQ_MODE"); - sendOptVal("PZ_REQ", newVal); - } - // controllo SE devo gestire contatore PEZZI TOTALI - if (!string.IsNullOrEmpty(getOptPar("PZGTOT_MODE"))) - { - newVal = getValByParam("PZGTOT_MODE"); - sendOptVal("PZ_GTOT", newVal); - } - // controllo SE devo gestire contatore CADENZA (secondi ciclo rilevati) - if (!string.IsNullOrEmpty(getOptPar("PZCAD_MODE"))) - { - newVal = getValByParam("PZCAD_MODE"); - sendOptVal("CICLE_CAD", newVal); - } - } - } - catch (Exception exc) - { - lgError(exc, "Eccezione in processOtherCounters"); - } - } - /// - /// Recupera il valore INT dal nome del parametro per successivo processing - /// - /// - /// - private string getValByParam(string varName) - { - string answ = ""; - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) - string memAddr = getOptPar(varName); - if (memAddr.StartsWith("STD")) - { - // inizio verifica area memoria/parametro levando prima parte codice - memAddr = memAddr.Replace("STD.", ""); - // var di appoggio - int cntAddr = 0; - object outputVal = new object(); - // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 - if (memAddr.StartsWith("PAR.")) - { - // recupero parametro... - int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); - // processo parametro - stopwatch.Restart(); - FANUC_ref.F_RW_Param_Integer(false, cntAddr, 3, ref outputVal); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-PAR", 4), stopwatch.ElapsedTicks); - } - // salvo valore - answ = outputVal.ToString(); - } - // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW - else - { - memAddressFanuc areaCounter = new memAddressFanuc(memAddr); - - if (isVerboseLog) - { - lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); - } - - // leggo! - stopwatch.Restart(); - // switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato - switch (areaCounter.vType) - { - case "B": - byte valB = 0; - FANUC_ref.F_RW_Byte(false, areaCounter.mType, areaCounter.mPos, ref valB); - outputVal = valB; - break; - case "D": - ushort valW = 0; - FANUC_ref.F_RW_Word(false, areaCounter.mType, areaCounter.mPos, ref valW); - outputVal = valW; - break; - case "DW": - uint valDW = 0; - FANUC_ref.F_RW_DWord(false, areaCounter.mType, areaCounter.mPos, ref valDW); - if (isVerboseLog) - { - lgInfo("[1] valDW PAR: {0}", valDW); - } - - outputVal = valDW; - if (isVerboseLog) - { - lgInfo("[2] outputVal PAR: {0}", outputVal); - } - - break; - default: - break; - } - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); - } - - // salvo... - answ = outputVal.ToString(); - if (isVerboseLog) - { - lgInfo("[3] PAR letto: {0} | {1}", varName, answ); - } - } - stopwatch.Stop(); - } - return answ; - } - /// - /// Esegue processing MODE (e nel contempo recupera altri dati dell'area G) - /// - public override void processMode() - { - // processo SOLO SE connected... - if (connectionOk) - { - if (FANUC_ref.Connected) - { - if (utils.CRB("enableMode") && MemBlockG != null && MemBlockG.Length > 0) - { - try - { - // leggo tutto da 0 a 43... - int memIndex = 0; - // controllo modalità lettura memoria - stopwatch.Restart(); - FanucMemRW(R, FANUC.MemType.G, memIndex, ref MemBlockG); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-G-AREA", MemBlockG.Length), stopwatch.ElapsedTicks); - } - - stopwatch.Stop(); - // 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, string.Format("Errore in process Mode G43: {0}{1}", Environment.NewLine, exc)); - connectionOk = false; - stopwatch.Stop(); - } - } - } - } - } - /// - /// decodifica il modo dai valori del byte G43 - /// - /// - /// - protected static 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; - } - /// - /// Recupero dati dinamici... - /// - public override Dictionary getDynData() - { - Dictionary outVal = new Dictionary(); - // processo SOLO SE connected... - if (connectionOk) - { - if (FANUC_ref.Connected) - { - stopwatch.Restart(); - CncLib.Focas1.ODBDY2_1 answ = FANUC_ref.getAllDynData(); - if (utils.CRB("recTime")) - { - TimingData.addResult(cIobConf.codIOB, string.Format("PROC-DYN-DATA"), stopwatch.ElapsedTicks); - } - - 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"); - } - stopwatch.Stop(); - } - } - return outVal; - } - /// - /// Recupero dati override (da area G che è già stata letta...) - /// - /// - public override Dictionary getOverrides() - { - Dictionary outVal = new Dictionary(); - // processo SOLO SE connected... - if (connectionOk) - { - if (FANUC_ref.Connected) - { - if (utils.CRB("enableMode") && MemBlockG != null && MemBlockG.Length > 0) - { - outVal.Add("FEED_OVER", MemBlockG[30].ToString()); - outVal.Add("RAPID_OVER", MemBlockG[12].ToString()); - } - } - } - return outVal; - } - - /// - /// Override salvataggio valori in memoria... - /// - /// tipo di DUMP - public override void saveMemDump(dumpType tipo) - { - // se l'area ha una size > 0... - if (areaD.arraySize > 0) - { - dump_MemArea(tipo, FANUC.MemType.D, areaD.startIdx, areaD.arraySize); - } - // se l'area ha una size > 0... - if (areaR.arraySize > 0) - { - dump_MemArea(tipo, FANUC.MemType.R, areaR.startIdx, areaR.arraySize); - } - // se l'area ha una size > 0... - if (areaX.arraySize > 0) - { - dump_MemArea(tipo, FANUC.MemType.X, areaX.startIdx, areaX.arraySize); - } - // se l'area ha una size > 0... - if (areaY.arraySize > 0) - { - dump_MemArea(tipo, FANUC.MemType.Y, areaY.startIdx, areaY.arraySize); - } - // se l'area ha una size > 0... - if (areaPAR.arraySize > 0) - { - dump_ParArea(tipo, areaPAR.startIdx, areaPAR.arraySize); - } - } - /// - /// Dump area D della memoria + /// Dump area D della memoria /// /// tipo di DUMP: START (sovrascrivendo) / SAMPLE (salva tanti campionamenti) /// tipo memoria @@ -1372,6 +495,7 @@ namespace IOB_WIN } utils.WritePlain(mappaValori, nomeFileDW); } + /// /// Dump area PARAMETRI /// @@ -1430,5 +554,963 @@ namespace IOB_WIN } utils.WritePlain(mappaValori, nomeFile); } + + /// + /// Recupera il valore INT dal nome del parametro per successivo processing + /// + /// + /// + private string getValByParam(string varName) + { + string answ = ""; + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + string memAddr = getOptPar(varName); + if (memAddr.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddr = memAddr.Replace("STD.", ""); + // var di appoggio + int cntAddr = 0; + object outputVal = new object(); + // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 + if (memAddr.StartsWith("PAR.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); + // processo parametro + stopwatch.Restart(); + FANUC_ref.F_RW_Param_Integer(false, cntAddr, 3, ref outputVal); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-PAR", 4), stopwatch.ElapsedTicks); + } + // salvo valore + answ = outputVal.ToString(); + } + // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW + else + { + memAddressFanuc areaCounter = new memAddressFanuc(memAddr); + + if (isVerboseLog) + { + lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); + } + + // leggo! + stopwatch.Restart(); + // switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato + switch (areaCounter.vType) + { + case "B": + byte valB = 0; + FANUC_ref.F_RW_Byte(false, areaCounter.mType, areaCounter.mPos, ref valB); + outputVal = valB; + break; + + case "D": + ushort valW = 0; + FANUC_ref.F_RW_Word(false, areaCounter.mType, areaCounter.mPos, ref valW); + outputVal = valW; + break; + + case "DW": + uint valDW = 0; + FANUC_ref.F_RW_DWord(false, areaCounter.mType, areaCounter.mPos, ref valDW); + if (isVerboseLog) + { + lgInfo("[1] valDW PAR: {0}", valDW); + } + + outputVal = valDW; + if (isVerboseLog) + { + lgInfo("[2] outputVal PAR: {0}", outputVal); + } + + break; + + default: + break; + } + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); + } + + // salvo... + answ = outputVal.ToString(); + if (isVerboseLog) + { + lgInfo("[3] PAR letto: {0} | {1}", varName, answ); + } + } + stopwatch.Stop(); + } + return answ; + } + + #endregion Private Methods + + #region Protected Methods + + /// + /// decodifica il modo dai valori del byte G43 + /// + /// + /// + protected static 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; + } + + #endregion Protected Methods + + #region Public Methods + + /// + /// Processo i task richiesti e li elimino dalla coda 1:1 + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti... + Dictionary taskDone = new Dictionary(); + bool taskOk = false; + string taskVal = ""; + // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4 + foreach (var item in task2exe) + { + taskOk = false; + taskVal = ""; + // converto richiesta in enum... + taskType tName = taskType.nihil; + Enum.TryParse(item.Key, out tName); + switch (tName) + { + case taskType.nihil: + case taskType.fixStopSetup: + case taskType.forceResetPzCount: + case taskType.forceSetPzCount: + case taskType.setArt: + case taskType.setComm: + case taskType.setProg: + case taskType.sendWatchDogMes2Plc: + taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; + lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + + case taskType.startSetup: + // reset contapezzi inizio setup + taskOk = resetcontapezziPLC(); + taskVal = taskOk ? "RESET: SETUP START" : "PZ RESET DISABLED | NO EXEC"; + lgInfo($"Chiamata startSetup: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + + case taskType.stopSetup: + // reset contapezzi fine setup SE ESPLICITAMENTE IMPOSTATO + if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET_stopSetup") == "TRUE") + { + taskOk = resetcontapezziPLC(); + } + taskVal = taskOk ? "RESET: SETUP END" : "PZ RESET DISABLED | NO EXEC"; + lgInfo($"Chiamata stopSetup: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + + default: + taskVal = "SKIPPED | NO EXEC"; + lgInfo($"Chiamata default senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + } + // aggiungo task! + taskDone.Add(item.Key, taskVal); + } + return taskDone; + } + + /// + /// wrapper chiamata lettura/scrittura SINGOLO BYTE... + /// + /// + /// + /// + /// + /// + public bool FanucMemRW(bool bWrite, FANUC.MemType MemType, Int32 memIndex, ref byte Value) + { + bool answ = false; + if (connectionOk) + { + if (FANUC_ref.Connected) + { + try + { + parentForm.commPlcActive = true; + answ = FANUC_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); + } + catch + { } + } + } + parentForm.commPlcActive = false; + return answ; + } + + /// + /// wrapper chiamata lettura/scrittura MULTI BYTE... + /// + /// + /// + /// + /// + /// + public bool FanucMemRW(bool bWrite, FANUC.MemType MemType, Int32 memIndex, ref byte[] Value) + { + bool answ = false; + if (connectionOk) + { + if (FANUC_ref.Connected) + { + try + { + parentForm.commPlcActive = true; + answ = FANUC_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); + } + catch + { } + } + } + parentForm.commPlcActive = false; + return answ; + } + + /// + /// Recupero dati dinamici... + /// + public override Dictionary getDynData() + { + Dictionary outVal = new Dictionary(); + // processo SOLO SE connected... + if (connectionOk) + { + if (FANUC_ref.Connected) + { + stopwatch.Restart(); + CncLib.Focas1.ODBDY2_1 answ = FANUC_ref.getAllDynData(); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("PROC-DYN-DATA"), stopwatch.ElapsedTicks); + } + + 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"); + } + stopwatch.Stop(); + } + } + return outVal; + } + + /// + /// Recupero dati override (da area G che è già stata letta...) + /// + /// + public override Dictionary getOverrides() + { + Dictionary outVal = new Dictionary(); + // processo SOLO SE connected... + if (connectionOk) + { + if (FANUC_ref.Connected) + { + if (utils.CRB("enableMode") && MemBlockG != null && MemBlockG.Length > 0) + { + outVal.Add("FEED_OVER", MemBlockG[30].ToString()); + outVal.Add("RAPID_OVER", MemBlockG[12].ToString()); + } + } + } + return outVal; + } + + /// + /// Recupero programma in lavorazione + /// + /// + public override string getPrgName() + { + string prgName = ""; + // 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"), ""); + lgInfo("Current PROG: {0}", prgName); + } + catch (Exception exc) + { + lgError(string.Format("Eccezione in recupero PRG NAME MAIN:{0}{1}", Environment.NewLine, exc)); + connectionOk = false; + } + 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(); + stopwatch.Restart(); + CncLib.Focas1.ODBSYS answ = FANUC_ref.getSysInfo(); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("SYS-INFO"), stopwatch.ElapsedTicks); + } + + 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"); + connectionOk = false; + } + return outVal; + } + + /// + /// Effettua vero processing contapezzi: + /// 6711: pezzi lavorati + /// 6712: pezzi lavorati totali + /// 6713: pezzi richiesti + /// + public override void processContapezzi() + { + if (utils.CRB("enableContapezzi")) + { + // procedo SOLO SE ho connessione... + if (connectionOk) + { + try + { + // controllo di AVERE parametri opzionali x conteggi vari + if (cIobConf.optPar.Count > 0) + { + // contapezzi ATTUALE + if (!string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + string memAddr = getOptPar("PZCOUNT_MODE"); + if (memAddr.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddr = memAddr.Replace("STD.", ""); + // var di appoggio + int cntAddr = 0; + object outputVal = new object(); + // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 + if (memAddr.StartsWith("PAR.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); + if (cntAddr == 0) + { + cntAddr = 6711; + } + + // processo parametro contapezzi (lavorati) + stopwatch.Restart(); + FANUC_ref.F_RW_Param_Integer(false, cntAddr, 3, ref outputVal); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-PAR", 4), stopwatch.ElapsedTicks); + } + + // salvo ultimo conteggio rilevato + int newVal = -1; + Int32.TryParse(outputVal.ToString(), out newVal); + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + } + // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW + else + { + memAddressFanuc areaCounter = new memAddressFanuc(memAddr); + + if (isVerboseLog) + { + lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); + } + + // leggo! + stopwatch.Restart(); + // switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato + switch (areaCounter.vType) + { + case "B": + byte valB = 0; + FANUC_ref.F_RW_Byte(false, areaCounter.mType, areaCounter.mPos, ref valB); + outputVal = valB; + break; + + case "D": + ushort valW = 0; + FANUC_ref.F_RW_Word(false, areaCounter.mType, areaCounter.mPos, ref valW); + outputVal = valW; + break; + + case "DW": + uint valDW = 0; + FANUC_ref.F_RW_DWord(false, areaCounter.mType, areaCounter.mPos, ref valDW); + if (isVerboseLog) + { + lgInfo("[1] valDW contapezzi: {0}", valDW); + } + + outputVal = valDW; + if (isVerboseLog) + { + lgInfo("[2] outputVal contapezzi: {0}", outputVal); + } + + break; + + default: + break; + } + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); + } + + // salvo... + int newVal = -1; + Int32.TryParse(outputVal.ToString(), out newVal); + contapezziPLC = newVal > -1 ? newVal : contapezziPLC; + if (isVerboseLog) + { + lgInfo("[3] contapezziPLC contapezzi: {0}", contapezziPLC); + } + } + stopwatch.Stop(); + } + } + } + } + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi FANUC"); + connectionOk = false; + } + } + else + { + lgError("Errore: manca connessione in contapezzi FANUC"); + } + } + } + + /// + /// Esegue processing MODE (e nel contempo recupera altri dati dell'area G) + /// + public override void processMode() + { + // processo SOLO SE connected... + if (connectionOk) + { + if (FANUC_ref.Connected) + { + if (utils.CRB("enableMode") && MemBlockG != null && MemBlockG.Length > 0) + { + try + { + // leggo tutto da 0 a 43... + int memIndex = 0; + // controllo modalità lettura memoria + stopwatch.Restart(); + FanucMemRW(R, FANUC.MemType.G, memIndex, ref MemBlockG); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-G-AREA", MemBlockG.Length), stopwatch.ElapsedTicks); + } + + stopwatch.Stop(); + // 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, string.Format("Errore in process Mode G43: {0}{1}", Environment.NewLine, exc)); + connectionOk = false; + stopwatch.Stop(); + } + } + } + } + } + + /// + /// Recupero altri counters se ci sono + /// + public override void processOtherCounters() + { + try + { + // controllo di AVERE parametri opzionali x conteggi vari + if (cIobConf.optPar.Count > 0) + { + string newVal = ""; +#if false + // controllo SE salvare contapezzo + if (getOptPar("PZCOUNT_MODE") != "") + { + sendOptVal("PZ_COUNT", contapezziPLC); + } +#endif + // controllo SE devo gestire contatore pezzi REQUESTED (lanciati) + if (!string.IsNullOrEmpty(getOptPar("PZREQ_MODE"))) + { + newVal = getValByParam("PZREQ_MODE"); + sendOptVal("PZ_REQ", newVal); + } + // controllo SE devo gestire contatore PEZZI TOTALI + if (!string.IsNullOrEmpty(getOptPar("PZGTOT_MODE"))) + { + newVal = getValByParam("PZGTOT_MODE"); + sendOptVal("PZ_GTOT", newVal); + } + // controllo SE devo gestire contatore CADENZA (secondi ciclo rilevati) + if (!string.IsNullOrEmpty(getOptPar("PZCAD_MODE"))) + { + newVal = getValByParam("PZCAD_MODE"); + sendOptVal("CICLE_CAD", newVal); + } + } + } + catch (Exception exc) + { + lgError(exc, "Eccezione in processOtherCounters"); + } + } + + /// + /// Effettua lettura semafori principale + /// Parametri da aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) + { + base.readSemafori(ref currDispData); + try + { + if (verboseLog) + { + lgInfo("inizio read semafori"); + } + + currDispData.semIn = Semaforo.SV; + // inizio letture, SEMPRE DA ZERO (possibile ottimizzazione...) + int memIndex = 0; + // controllo area R: se ha dati (> 0 byte) --> leggo! + if (MemBlockR.Length > 0) + { + stopwatch.Restart(); + FanucMemRW(R, FANUC.MemType.R, memIndex, ref MemBlockR); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-R", MemBlockR.Length), stopwatch.ElapsedTicks); + } + // log + if (verboseLog) + { + for (int i = 0; i < MemBlockR.Length; i++) + { + lgInfo(string.Format("MemBlockR{0}: {1}", i, utils.binaryForm(MemBlockR[i]))); + } + } + } + // controllo area X: se ha dati (> 0 byte) --> leggo! + if (MemBlockX.Length > 0) + { + stopwatch.Restart(); + FanucMemRW(R, FANUC.MemType.X, memIndex, ref MemBlockX); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-X", MemBlockX.Length), stopwatch.ElapsedTicks); + } + // log + if (verboseLog) + { + for (int i = 0; i < MemBlockX.Length; i++) + { + lgInfo(string.Format("MemBlockX{0}: {1}", i, utils.binaryForm(MemBlockX[i]))); + } + } + } + // controllo area Y: se ha dati (> 0 byte) --> leggo! + if (MemBlockY.Length > 0) + { + stopwatch.Restart(); + FanucMemRW(R, FANUC.MemType.Y, memIndex, ref MemBlockY); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-Y", MemBlockY.Length), stopwatch.ElapsedTicks); + } + // log + if (verboseLog) + { + for (int i = 0; i < MemBlockY.Length; i++) + { + lgInfo(string.Format("MemBlockY{0}: {1}", i, utils.binaryForm(MemBlockY[i]))); + } + } + } + stopwatch.Stop(); + // salvo il solo BYTE dell'input decifrando il semaforo... + decodeToBitmap(); + reportRawInput(ref currDispData); + } + catch (Exception exc) + { + lgError(string.Format("Eccezione in readSemafori:{0}{1}", Environment.NewLine, exc)); + connectionOk = false; + currDispData.semIn = Semaforo.SR; + } + } + + /// + /// Effettua reset del contapezzi + /// + /// + public override bool resetcontapezziPLC() + { + bool answ = false; + // ...SE abilitato da conf IOB + if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET") == "TRUE") + { + // scrivo valore 0 x il contapezzi + try + { + // contapezzi ATTUALE + if (!string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + string memAddr = getOptPar("PZCOUNT_MODE"); + if (memAddr.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddr = memAddr.Replace("STD.", ""); + // var di appoggio + int cntAddr = 0; + // var contapezzi a zero.... + object newVal = new object(); + newVal = 0; + // verifico se si tratta di lettura parametro... formato tipo STD.PAR.6711 + if (memAddr.StartsWith("PAR.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("PAR.", ""), out cntAddr); + if (cntAddr == 0) + { + cntAddr = 6711; + } + + // processo RESET contapezzi (lavorati) + stopwatch.Restart(); + FANUC_ref.F_RW_Param_Integer(true, cntAddr, 3, ref newVal); + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("W{0}-PAR", 4), stopwatch.ElapsedTicks); + } + } + // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW + else + { + memAddressFanuc areaCounter = new memAddressFanuc(memAddr); + + if (isVerboseLog) + { + lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType); + } + // leggo! + stopwatch.Restart(); + // switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato + switch (areaCounter.vType) + { + case "B": + byte valB = 0; + FANUC_ref.F_RW_Byte(true, areaCounter.mType, areaCounter.mPos, ref valB); + newVal = valB; + break; + + case "D": + ushort valW = 0; + FANUC_ref.F_RW_Word(true, areaCounter.mType, areaCounter.mPos, ref valW); + newVal = valW; + break; + + case "DW": + uint valDW = 0; + FANUC_ref.F_RW_DWord(true, areaCounter.mType, areaCounter.mPos, ref valDW); + break; + + default: + break; + } + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("W-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); + } + } + stopwatch.Stop(); + } + } + } + catch (Exception exc) + { + lgError(exc, "Errore in RESET contapezzi FANUC"); + connectionOk = false; + } + answ = true; + } + return answ; + } + + /// + /// Override salvataggio valori in memoria... + /// + /// tipo di DUMP + public override void saveMemDump(dumpType tipo) + { + // se l'area ha una size > 0... + if (areaD.arraySize > 0) + { + dump_MemArea(tipo, FANUC.MemType.D, areaD.startIdx, areaD.arraySize); + } + // se l'area ha una size > 0... + if (areaR.arraySize > 0) + { + dump_MemArea(tipo, FANUC.MemType.R, areaR.startIdx, areaR.arraySize); + } + // se l'area ha una size > 0... + if (areaX.arraySize > 0) + { + dump_MemArea(tipo, FANUC.MemType.X, areaX.startIdx, areaX.arraySize); + } + // se l'area ha una size > 0... + if (areaY.arraySize > 0) + { + dump_MemArea(tipo, FANUC.MemType.Y, areaY.startIdx, areaY.arraySize); + } + // se l'area ha una size > 0... + if (areaPAR.arraySize > 0) + { + dump_ParArea(tipo, areaPAR.startIdx, areaPAR.arraySize); + } + } + + /// + /// 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("FANUC: ConnKO - tryConnect"); + } + // in primis salvo data ping... + lastPING = DateTime.Now; + // ora PING!!! + Ping pingSender = new Ping(); + IPAddress address = IPAddress.Loopback; + IPAddress.TryParse(cIobConf.cncIpAddr, out address); + PingReply reply = pingSender.Send(address, 100); + // se passa il ping faccio il resto... + if (reply.Status == IPStatus.Success) + { + string szStatusConnection = ""; + try + { + // ora provo connessione... + parentForm.commPlcActive = true; + FANUC_ref.Connect(ref szStatusConnection); + parentForm.commPlcActive = false; + lgInfo("szStatusConnection: " + szStatusConnection); + connectionOk = true; + // refresh stato allarmi!!! + if (connectionOk) + { + dtAvvioAdp = DateTime.Now; + if (adpRunning) + { + lgInfo("Connessione OK"); + } + } + else + { + lgError("Impossibile procedere, connessione mancante..."); + } + } + catch (Exception exc) + { + lgFatal(string.Format("Errore nella connessione all'adapter FANUC: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc)); + connectionOk = false; + lgInfo(string.Format("Eccezione in TryConnect, Adapter 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: controllo PING fallito per IP {0} - {1}", cIobConf.cncIpAddr, reply.Status)); + } + } + } + } + // 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 + { + FANUC_ref.Disconnect(ref szStatusConnection); + connectionOk = false; + // resetto timing! + TimingData.resetData(); + lgInfo(szStatusConnection); + lgInfo("Effettuata disconnessione adapter FANUC!"); + } + catch (Exception exc) + { + lgFatal(exc, "Errore nella disconnessione dall'adapter FANUC"); + } + } + else + { + lgError("IMPOSSIBILE effettuare disconnessione: Connessione non disponibile..."); + } + } + + #endregion Public Methods } -} +} \ No newline at end of file diff --git a/IOB-WIN/IobGeneric.cs b/IOB-WIN/IobGeneric.cs index 3c70db86..a72f7792 100644 --- a/IOB-WIN/IobGeneric.cs +++ b/IOB-WIN/IobGeneric.cs @@ -167,13 +167,18 @@ namespace IOB_WIN /// /// ODL attualmente sulla macchina /// - public Int32 currIdxODL; + public Int32 currIdxODL = 0; /// /// Modo corrente (da classe ENUM) /// public CNC_MODE currMode; + /// + /// ODL corrente caricato sulla macchina (stringa, da chiamata MP/IO) + /// + public string currODL = ""; + /// /// Indica se sia richiesto campionamento memoria PERIODICO /// @@ -908,7 +913,7 @@ namespace IOB_WIN } /// - /// stato Online/Offline della IOB + /// Indica lo stato Online/Offline della IOB /// public bool IobOnline { diff --git a/IOB-WIN/IobKawasaki.cs b/IOB-WIN/IobKawasaki.cs index 3c062701..98d64fc7 100644 --- a/IOB-WIN/IobKawasaki.cs +++ b/IOB-WIN/IobKawasaki.cs @@ -6,139 +6,510 @@ using System.Net.NetworkInformation; namespace IOB_WIN { - public class IobKawasaki : IobGeneric - { - - /// - /// Enum segnali status macchina (ByteStatus) come flag - /// - [Flags] - public enum bitStatus + public class IobKawasaki : IobGeneric { - NONE = 0, - POWER_ON = 1 << 0, - AUTO = 1 << 1, - RUN = 1 << 2, - ERROR = 1 << 3, - ALARM = 1 << 4, - EMERG_OK = 1 << 5, - DOOR_CLOSED = 1 << 6, - READY_LOAD = 1 << 7 - } - /// - /// Enum segnali macchina ulteriori (ByteSignals) - /// - [Flags] - public enum bitSignals - { - NONE = 0, - TRANSF_AUTO = 1 << 0, - PUNZ_AUTO = 1 << 1, - BARR_TAV_RIPR = 1 << 2, - ARIA_OK = 1 << 3, - CONS_TRANS_OK = 1 << 4, - TAV_A = 1 << 5, - TAV_B = 1 << 6, - RICH_ACCESSO = 1 << 7 - } + #region Private Fields - /// - /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO - /// - Dictionary signLUT = new Dictionary(); - /// - /// Oggetto MAIN x connessione KAWASAKI - /// - protected KRcc.Commu KAWASAKI_ref; - /// - /// Array delle risposte dal controllo KAWASAKI - /// - protected System.Collections.ArrayList resDataArray; - /// - /// Comando inviato al robot - /// - protected string comando; - /// - /// Variabile verifica thread comunicazione - /// - protected bool threadOk = false; - /// - /// Nome e seriale macchina - /// - protected string macName = ""; - /// - /// Variabile STATUS corrente (8bit INT) - /// - protected string cStatus; - /// - /// Variabile SIGNALS corrente (8bit INT) - /// - protected string cSignals; - /// - /// Num pezzi prelevati - /// - protected int numPzPrel; - /// - /// Ultimo TC registrato da robot - /// - protected decimal lastRecTC; - /// - /// Ultima missione svolta da robot - /// - protected string lastMissRobot; + /// + /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO + /// + private Dictionary signLUT = new Dictionary(); - /// - /// estende l'init della classe base... - /// - /// - /// - public IobKawasaki(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) - { - // gestione invio ritardato contapezzi - pzCountDelay = utils.CRI("pzCountDelay"); - lastPzCountSend = DateTime.Now; - lastWarnODL = DateTime.Now; - // init connessione - setConnection(); + #endregion Private Fields - // test completo funzionalità kawasaki, da TOGLIERE in prod... -#if DEBUG - kawasakiFullTest(); -#endif - } - /// - /// Test completo funzioni kawasaki - /// - private void kawasakiFullTest() - { - // faccio un try-catch di test vari... - try - { - //string connPar = string.Format("TCP {0}", cIobConf.cncIpAddr); - //KAWASAKI_ref = new KRcc.Commu(connPar); - //KAWASAKI_ref = new KRcc.Commu("TCP 192.168.0.92"); - if (KAWASAKI_ref.IsConnected) + #region Protected Fields + + /// + /// Comando inviato al robot + /// + protected string comando; + + /// + /// Variabile SIGNALS corrente (8bit INT) + /// + protected string cSignals; + + /// + /// Variabile STATUS corrente (8bit INT) + /// + protected string cStatus; + + /// + /// Oggetto MAIN x connessione KAWASAKI + /// + protected KRcc.Commu KAWASAKI_ref; + + /// + /// Ultima missione svolta da robot + /// + protected string lastMissRobot; + + /// + /// Ultimo TC registrato da robot + /// + protected decimal lastRecTC; + + /// + /// Nome e seriale macchina + /// + protected string macName = ""; + + /// + /// Num pezzi prelevati + /// + protected int numPzPrel; + + /// + /// Array delle risposte dal controllo KAWASAKI + /// + protected System.Collections.ArrayList resDataArray; + + /// + /// Variabile verifica thread comunicazione + /// + protected bool threadOk = false; + + #endregion Protected Fields + + #region Public Constructors + + /// + /// estende l'init della classe base... + /// + /// + /// + public IobKawasaki(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { - // connect ok - resDataArray = KAWASAKI_ref.command("where", 3000); - // WHERE [RET] - // Console.WriteLine(resDataArray[1]); - // [0] = 0 - // [1] = JT1 JT2 JT3 JT4 JT5 JT6 - // -23.205 - 39.967 - 13.176 95.663 71.402 - 21.512 - // X[mm] Y[mm] Z[mm] O[deg] A[deg] T[deg] - // - 489.620 693.940 1564.733 92.612 131.285 7.482 + // gestione invio ritardato contapezzi + pzCountDelay = utils.CRI("pzCountDelay"); + lastPzCountSend = DateTime.Now; + lastWarnODL = DateTime.Now; + // init connessione + setConnection(); - threadOk = commThreadOk; - macName = machineName; - cStatus = currBitmapStatus; - cSignals = currBitmapSignals; - contapezziPLC = pzCounter; - numPzPrel = pzPrelevati; - lastRecTC = lastTC; - lastMissRobot = lastMission; + // test completo funzionalità kawasaki, da TOGLIERE in prod... +#if DEBUG + kawasakiFullTest(); +#endif } - // test contapezzi + + #endregion Public Constructors + + #region Public Enums + + /// + /// Enum segnali macchina ulteriori (ByteSignals) + /// + [Flags] + public enum bitSignals + { + NONE = 0, + TRANSF_AUTO = 1 << 0, + PUNZ_AUTO = 1 << 1, + BARR_TAV_RIPR = 1 << 2, + ARIA_OK = 1 << 3, + CONS_TRANS_OK = 1 << 4, + TAV_A = 1 << 5, + TAV_B = 1 << 6, + RICH_ACCESSO = 1 << 7 + } + + /// + /// Enum segnali status macchina (ByteStatus) come flag + /// + [Flags] + public enum bitStatus + { + NONE = 0, + POWER_ON = 1 << 0, + AUTO = 1 << 1, + RUN = 1 << 2, + ERROR = 1 << 3, + ALARM = 1 << 4, + EMERG_OK = 1 << 5, + DOOR_CLOSED = 1 << 6, + READY_LOAD = 1 << 7 + } + + #endregion Public Enums + + #region Protected Properties + + /// + /// Verifica se il thread 4 di comm sia attivo + /// + protected bool commThreadOk + { + get + { + bool answ = false; + if (KAWASAKI_ref.IsConnected) + { + int retVal = 0; + resDataArray = KAWASAKI_ref.command("TYPE TASK (1004)", 3000); // thread 4 ok --> " 1\r\n" + int.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""), out retVal); + answ = (retVal == 1); + } + return answ; + } + } + + /// + /// Restituisce SEGNALI macchina nel formato: + /// B0: Transfer in auto + /// B1: Punzonatrice in AUTO + /// B2: Barriera tavola ripristinata + /// B3: Aria in linea OK + /// B4: Console Transfer in fuori ingombro + /// B5: TAV A + /// B6: TAV B + /// B7: Richiesta accesso attiva + /// + protected string currBitmapSignals + { + get + { + string answ = ""; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE $signal", 3000); // segnali --> "1|0|1|1|1|0|0|0\r\n" + answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", "").Replace("|", ""); +#if false + // reverse stringa (B0 portato a sx) + szBitmap = utils.reverseStr(szBitmap); + // ora converto bitmap string in INT + answ = Convert.ToInt32(szBitmap, 2); +#endif + } + return answ; + } + } + + /// + /// Restituisce stato macchina nel formato (da sx a dx): + /// B0: POWER_ON + /// B1: AUTO + /// B2: RUN + /// B3: ERROR + /// B4: ALLARME + /// B5: EMERGENZA OK + /// B6: PORTA CHIUSA + /// B7: PRONTO AL LOAD + /// + protected string currBitmapStatus + { + get + { + string answ = ""; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE $status", 3000); // status --> "0|0|1|0|0|1|0|0\r\n" + answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", "").Replace("|", ""); +#if false + // reverse stringa (B0 portato a sx) + szBitmap = utils.reverseStr(szBitmap); + // ora converto bitmap string in INT + answ = Convert.ToInt32(szBitmap, 2); +#endif + } + return answ; + } + } + + /// + /// Recupera ultima missione svolta + /// + protected string lastMission + { + get + { + string answ = ""; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE $exe", 3000); // missione --> "\r\n" (vuoto, no missione) + answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""); + } + return answ; + } + } + + /// + /// Oggetto per lettura ULTIMO TC rilevato + /// + protected decimal lastTC + { + get + { + decimal answ = 0; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE r_tempo", 3000); // ultimo TCiclo rilevato --> " 349.19\r\n" + decimal.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", "").Replace(".", ","), out answ); + } + return answ; + } + } + + /// + /// Recupera nome e seriale macchina + /// + protected string machineName + { + get + { + string answ = ""; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE $id_true", 3000); // id macchina --> "BX100N-B001 Sn. 2366\r\n" + answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""); + } + return answ; + } + } + + /// + /// Oggetto per lettura/scrittura counter pezzi robot + /// + protected int pzCounter + { + get + { + int answ = 0; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE i_cicli", 3000); // num cicli depositati/fatti --> " 0\r\n" + int.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""), out answ); + } + return answ; + } + set + { + if (KAWASAKI_ref.IsConnected) + { + comando = string.Format("i_cicli={0}", value); + // scrivo valore cicli + resDataArray = KAWASAKI_ref.command(comando, 3000); // imposto cicli depositati/fatti --> " 0\r\n" + } + } + } + + /// + /// Oggetto per lettura counter pezzi PRELEVATI + /// + protected int pzPrelevati + { + get + { + int answ = 0; + if (KAWASAKI_ref.IsConnected) + { + resDataArray = KAWASAKI_ref.command("TYPE i_prelevati", 3000); // num pz prelevati --> "0\r\n" + int.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""), out answ); + } + return answ; + } + } + + #endregion Protected Properties + + #region Private Methods + + /// + /// Decodifica il resto dell'area 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; + /* ----------------------------------------------------- + * bitmap MAPO + * B0: POWER_ON + * B1: RUN + * B2: pzCount + * B3: allarme + * B4: manuale + * B5: emergenza + * B6: error prog + * B7: auto mode + ----------------------------------------------------- */ + // bit 0 (poweron) imposto a 1 SE connected... + B_input = KAWASAKI_ref.IsConnected ? 1 : 0; + // RUN + if (cStatus[2] == '1') + { + B_input += (1 << 1); + } + // ERROR prog/macchina + if (cStatus[3] == '1') + { + B_input += (1 << 6); + } + // allarme + if (cStatus[4] == '1') + { + B_input += (1 << 3); + } + // Automatico (porta chiusa) + if (cStatus[6] == '1' || cStatus[1] == '1') + { + B_input += (1 << 4); + } + // NON EMERGENZA (1=armed, 0=triggered) + if (cStatus[5] == '0') + { + B_input += (1 << 5); + } + // procedo SOLO SE è enabled IOB + if (IobOnline) + { + try + { + currODL = utils.callUrl(urlGetCurrODL); + // solo SE HO un ODL... + if (string.IsNullOrEmpty(currODL) || currODL == "0") + { + if (periodicLog) + { + lgInfo(string.Format("Kawasaki | Lettura ODL andata a vuoto: currODL: {0}", currODL)); + } + } + else + { // se variato o scaduto timeout log... + if (periodicLog || (currIdxODL.ToString() != currODL)) + { + lgInfo(string.Format("Kawasaki | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); + } + // 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; + } + } + } + else + { + // imposto currODL a vuoto! + currODL = ""; + if (periodicLog) + { + lgInfo($"Kawasaki | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); + } + } + if (!string.IsNullOrEmpty(currODL)) + { + if (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)) + { + // se sono differenti MOSTRO... + if (contapezziPLC != contapezziIOB) + { + // registro contapezzi + lgInfo($"Differenza Contapezzi CNC/IOB: contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); + } + // verifico se variato contapezzi... e se passato ritardo minimo... + if (contapezziPLC > contapezziIOB) + { + // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio + contapezziIOB++; + needRefreshPzCount = true; + // salvo in semaforo! + B_input += (1 << 2); + // registro contapezzi + lgInfo($"contapezziPLC KAWASAKI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + } + else if (contapezziIOB > contapezziPLC) + { + lgInfo($"Contapezzi IOB > CNC --> NON INVIO (contapezziPLC: {contapezziPLC} < contapezziIOB: {contapezziIOB})"); + } + + // invio a server contapezzi (aggiornato) + string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); + // verifica se tutto OK + if (retVal != contapezziIOB.ToString()) + { + // errore salvataggio contapezzi + lgInfo($"Errore salvataggio Contapezzi KAWASAKI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); + // rileggo il counter pezzi da server + pzCntReload(true); + } + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + else + { + lgError("Attenzione non trovato ODL --> currODL = 0"); + } + } + else + { + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + lgError($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC KAWASAKI {contapezziPLC} | contapezziIOB {contapezziIOB}"); + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + + // log opzionale! + if (verboseLog) + { + lgInfo($"Trasformazione B_input: {B_input}"); + } + } + + /// + /// Test completo funzioni kawasaki + /// + private void kawasakiFullTest() + { + // faccio un try-catch di test vari... + try + { + //string connPar = string.Format("TCP {0}", cIobConf.cncIpAddr); + //KAWASAKI_ref = new KRcc.Commu(connPar); + //KAWASAKI_ref = new KRcc.Commu("TCP 192.168.0.92"); + if (KAWASAKI_ref.IsConnected) + { + // connect ok + resDataArray = KAWASAKI_ref.command("where", 3000); + // WHERE [RET] + // Console.WriteLine(resDataArray[1]); + // [0] = 0 + // [1] = JT1 JT2 JT3 JT4 JT5 JT6 + // -23.205 - 39.967 - 13.176 95.663 71.402 - 21.512 + // X[mm] Y[mm] Z[mm] O[deg] A[deg] T[deg] + // - 489.620 693.940 1564.733 92.612 131.285 7.482 + + threadOk = commThreadOk; + macName = machineName; + cStatus = currBitmapStatus; + cSignals = currBitmapSignals; + contapezziPLC = pzCounter; + numPzPrel = pzPrelevati; + lastRecTC = lastTC; + lastMissRobot = lastMission; + } + // test contapezzi #if false // leggo i pezzi int currCount = pzCounter; @@ -149,582 +520,310 @@ namespace IOB_WIN // reimposto corretti pzCounter = currCount; #endif - // test gest programmi + // test gest programmi #if true - //saveProgram("prog", "default"); - sendProgram("prog", "default2"); + //saveProgram("prog", "default"); + sendProgram("prog", "default2"); #endif - } - catch (Exception e) - { // e.Message = "can't connect TCP/IP" or // "can't login" - Console.WriteLine(e.Message); - } - } - - - /// - /// Processo i task richiesti e li elimino dalla coda 1:1 - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti... - Dictionary taskDone = new Dictionary(); - bool taskOk = false; - string taskVal = ""; - - // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4 - 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.setArt: - case taskType.setComm: - case taskType.setProg: - case taskType.sendWatchDogMes2Plc: - taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; - break; - case taskType.forceResetPzCount: - // reset contapezzi inizio setup - taskOk = resetcontapezziPLC(); - taskVal = taskOk ? "FORCE RESET PZ COUNT" : "FORCE RESET DISABLED | NO EXEC"; - break; - case taskType.forceSetPzCount: - // reset contapezzi inizio setup - int newPzCount = 0; - int.TryParse(item.Value, out newPzCount); - if (newPzCount >= 0) - { - taskOk = setcontapezziPLC(newPzCount); - taskVal = taskOk ? $"FORCE SET PZ COUNT TO {newPzCount}" : $"FORCE SET PZ COUNT TO {newPzCount} | NO EXEC"; } - else - { - taskVal = $"ERROR IN FORCE SET PZ COUNT TO {newPzCount}"; + catch (Exception e) + { // e.Message = "can't connect TCP/IP" or // "can't login" + Console.WriteLine(e.Message); } - break; - case taskType.startSetup: - // reset contapezzi inizio setup - taskOk = resetcontapezziPLC(); - taskVal = taskOk ? "RESET: SETUP START" : "PZ RESET DISABLED | NO EXEC"; - break; - case taskType.stopSetup: - // reset contapezzi fine setup // reset contapezzi fine setup SE ESPLICITAMENTE IMPOSTATO - if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET_stopSetup") == "TRUE") - { - resetcontapezziPLC(); - } - taskVal = taskOk ? "RESET: SETUP END" : "PZ RESET DISABLED | NO EXEC"; - break; - default: - taskVal = "SKIPPED | NO EXEC"; - break; } - taskDone.Add(item.Key, taskVal); - } - return taskDone; - } - /// - /// Effettua reset del contapezzi - /// - /// - public override bool resetcontapezziPLC() - { - bool answ = false; - // ...SE abilitato da conf IOB - if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET") == "TRUE") - { - // scrivo valore 0 x il contapezzi - try + /// + /// Effettua salvataggio del programma corrente + /// + /// Dir di riferimento + /// Nome Programma (se mancasse *.as lo aggiunge) + private void saveProgram(string progDir = "prog", string progName = "current.as") { - pzCounter = 0; - } - catch (Exception exc) - { - lgError(exc, "Errore in RESET contapezzi KAWASAKI"); - connectionOk = false; - } - answ = true; - } - else - { - lgError("Impossibile effettuare RESET contapezzi KAWASAKI, mancanza parametro OPT:ENABLE_PZ_RESET"); - } - return answ; - } - /// - /// Effettua IMPOSTAZIONE FORZATA del contapezzi - /// - /// - public override bool setcontapezziPLC(int newPzCount) - { - bool answ = false; - // ...SE abilitato da conf IOB - if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET") == "TRUE") - { - // scrivo valore 0 x il contapezzi - try - { - pzCounter = newPzCount; - } - catch (Exception exc) - { - lgError(exc, "Errore in SET contapezzi KAWASAKI"); - connectionOk = false; - } - answ = true; - } - else - { - lgError("Impossibile effettuare SET contapezzi KAWASAKI, mancanza parametro OPT:ENABLE_PZ_RESET"); - } - return answ; - } + // path completo + progName = progName.EndsWith(".as") ? progName : progName + ".as"; + string prgPath = progName;// string.Format("{0}/{1}", progDir, progName); + if (KAWASAKI_ref.IsConnected) + { + // comandi x setup programma... + resDataArray = KAWASAKI_ref.command("ferma", 3000); // ferma processi (all) --> "" + resDataArray = KAWASAKI_ref.command("togli", 3000); // toglie processi da pronta esecuzione --> "" - /// - /// Imposto connessione - /// - protected virtual void setConnection() - { - // Creo oggetto connessione NC - parentForm.commPlcActive = true; - lgInfo("Start init Adapter KAWASAKI all'IP {0} | --> IOB {1}", cIobConf.cncIpAddr, cIobConf.codIOB); + //resp = com.command("SAVE nome_del_file", 3000); // salvataggio file... FORSE --> "\u0005\u0002Bnome_del_file.as\u0017" --> verificare DOVE salva... - // inizializzo correttamente aree memoria secondo CONF - iniFileName - IniFile fIni = new IniFile(cIobConf.iniFileName); - // fix enable prgName - enablePrgName = fIni.ReadBoolean("CNC", "GETPRGNAME", true); - - // SE è necessario refresh... - if (needRefresh) - { - lgInfo("Refreshing connection..."); - // ora tento avvio PLC... SE PING OK... - if (testPingMachine == IPStatus.Success) - { - try - { - string connPar = string.Format("TCP {0}", cIobConf.cncIpAddr); - KAWASAKI_ref = new KRcc.Commu(connPar); - // disconnetto e connetto... - if (isVerboseLog) - { - lgInfo("KAWASAKI: tryDisconnect"); - } - - lgInfo("End init Adapter KAWASAKI"); - if (isVerboseLog) - { - lgInfo("KAWASAKI CONNESSIONE AVVENUTA"); - } - } - catch (Exception exc) - { - lgError(exc, "Errore in INIT KAWASAKI Commu"); - } - needRefresh = false; - } - parentForm.commPlcActive = false; - // gestione pzCounter - if (utils.CRB("enableContapezzi")) - { - lgInfo("KAWASAKI: inizio gestione contapezzi"); - try - { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) - if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) - { - if (getOptPar("PZCOUNT_MODE").StartsWith("STD")) - { - lgInfo("Init contapezzi KAWASAKI: pzCntReload(true)"); - pzCntReload(true); - // refresh associazione Macchina - IOB - sendM2IOB(); - // per adesso imposto lettura fanuc == 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 KAWASAKI"); - } - } - } - } - /// - /// Override disconnessione - /// - public override void tryDisconnect() - { - if (connectionOk) - { - connectionOk = false; - string szStatusConnection = ""; - try - { - KAWASAKI_ref.disconnect(); - lgInfo(szStatusConnection); - lgInfo("Effettuata disconnessione adapter KAWASAKI!"); - } - catch (Exception exc) - { - lgFatal(exc, "Errore nella disconnessione dall'adapter KAWASAKI"); - } - } - else - { - lgError("IMPOSSIBILE effettuare disconnessione KAWASAKI: Connessione non disponibile..."); - } - needRefresh = true; - } - /// - /// 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("KAWASAKI: ConnKO - tryConnect"); - } - // in primis salvo data ping... - lastPING = DateTime.Now; - // se passa il ping faccio il resto... - if (testPingMachine == IPStatus.Success) - { - string szStatusConnection = ""; - try - { - // ora provo connessione... - parentForm.commPlcActive = true; - string connPar = string.Format("TCP {0}", cIobConf.cncIpAddr); - KAWASAKI_ref.connect(connPar); - parentForm.commPlcActive = false; - lgInfo("szStatusConnection: " + KAWASAKI_ref.IsConnected); - connectionOk = true; - // verifico se sta girando - if (connectionOk) - { - if (adpRunning) + int ret = KAWASAKI_ref.save(prgPath); // SAVE current.as[RET] + if (ret == 0) { - lgInfo("Connessione OK"); + // Success + } + if (ret == -1) + { + // Communication error + } + if (ret == -2) + { + // Robot Controller error + } + if (ret == -3) + { + // Internal error } - } - else - { - lgError("Impossibile procedere, connessione mancante..."); - } } - catch (Exception exc) + } + + /// + /// Effettua invio del programma di alvorazione al ROBOT + /// Dir di riferimento + /// Nome Programma (se mancasse *.as lo aggiunge) + /// + private void sendProgram(string progDir = "prog", string progName = "default.as") + { + // path completo + progName = progName.EndsWith(".as") ? progName : progName + ".as"; + string prgPath = progName;// string.Format("{0}/{1}", progDir, progName); + + // comandi x setup programma... + resDataArray = KAWASAKI_ref.command("ferma", 3000); // ferma processi (all) --> "" + resDataArray = KAWASAKI_ref.command("togli", 3000); // toglie processi da pronta esecuzione --> "" + + if (KAWASAKI_ref.IsConnected) { - lgFatal(string.Format("Errore nella connessione all'adapter KAWASAKI: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc)); - connectionOk = false; - lgInfo(string.Format("Eccezione in TryConnect, Adapter KAWASAKI NON running, pausa di {0} msec prima di ulteriori tentativi di riconnessione", utils.CRI("waitRecMSec"))); + // carico... + KAWASAKI_ref.asInquiry = delegate (string as_msg) + { + Console.WriteLine(as_msg); if (as_msg.StartsWith("Are you sure ?")) + { + return "0\n"; // 0 [RET] + } + + if (as_msg.StartsWith("Load data?")) + { + return "1\n"; // 1 [RET] + } + + return null; + }; + int retLoad = KAWASAKI_ref.load(prgPath, "/Q"); // LOAD/Q default.as[RET] } - } - else - { - // loggo no risposta ping ... - connectionOk = false; - needRefresh = true; - if (verboseLog || periodicLog) + } + + #endregion Private Methods + + #region Protected Methods + + /// + /// Imposto connessione + /// + protected virtual void setConnection() + { + // Creo oggetto connessione NC + parentForm.commPlcActive = true; + lgInfo("Start init Adapter KAWASAKI all'IP {0} | --> IOB {1}", cIobConf.cncIpAddr, cIobConf.codIOB); + + // inizializzo correttamente aree memoria secondo CONF - iniFileName + IniFile fIni = new IniFile(cIobConf.iniFileName); + // fix enable prgName + enablePrgName = fIni.ReadBoolean("CNC", "GETPRGNAME", true); + + // SE è necessario refresh... + if (needRefresh) { - lgInfo(string.Format("Attenzione: KAWASAKI controllo PING fallito per IP {0}", cIobConf.cncIpAddr)); + lgInfo("Refreshing connection..."); + // ora tento avvio PLC... SE PING OK... + if (testPingMachine == IPStatus.Success) + { + try + { + string connPar = string.Format("TCP {0}", cIobConf.cncIpAddr); + KAWASAKI_ref = new KRcc.Commu(connPar); + // disconnetto e connetto... + if (isVerboseLog) + { + lgInfo("KAWASAKI: tryDisconnect"); + } + + lgInfo("End init Adapter KAWASAKI"); + if (isVerboseLog) + { + lgInfo("KAWASAKI CONNESSIONE AVVENUTA"); + } + } + catch (Exception exc) + { + lgError(exc, "Errore in INIT KAWASAKI Commu"); + } + needRefresh = false; + } + parentForm.commPlcActive = false; + // gestione pzCounter + if (utils.CRB("enableContapezzi")) + { + lgInfo("KAWASAKI: inizio gestione contapezzi"); + try + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) + { + if (getOptPar("PZCOUNT_MODE").StartsWith("STD")) + { + lgInfo("Init contapezzi KAWASAKI: pzCntReload(true)"); + pzCntReload(true); + // refresh associazione Macchina - IOB + sendM2IOB(); + // per adesso imposto lettura fanuc == 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 KAWASAKI"); + } + } } - } } - } - // se non è ancora connesso faccio processing memoria caso disconnesso... - if (!connectionOk) - { - // processo semafori ed invio... - processMemoryDiscon(); - } - } - /// - /// Oggetto per lettura counter pezzi PRELEVATI - /// - protected int pzPrelevati - { - get - { - int answ = 0; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE i_prelevati", 3000); // num pz prelevati --> "0\r\n" - int.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""), out answ); - } - return answ; - } - } - /// - /// Oggetto per lettura ULTIMO TC rilevato - /// - protected decimal lastTC - { - get - { - decimal answ = 0; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE r_tempo", 3000); // ultimo TCiclo rilevato --> " 349.19\r\n" - decimal.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", "").Replace(".", ","), out answ); - } - return answ; - } - } - /// - /// Oggetto per lettura/scrittura counter pezzi robot - /// - protected int pzCounter - { - get - { - int answ = 0; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE i_cicli", 3000); // num cicli depositati/fatti --> " 0\r\n" - int.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""), out answ); - } - return answ; - } - set - { - if (KAWASAKI_ref.IsConnected) - { - comando = string.Format("i_cicli={0}", value); - // scrivo valore cicli - resDataArray = KAWASAKI_ref.command(comando, 3000); // imposto cicli depositati/fatti --> " 0\r\n" - } - } - } - /// - /// Verifica se il thread 4 di comm sia attivo - /// - protected bool commThreadOk - { - get - { - bool answ = false; - if (KAWASAKI_ref.IsConnected) - { - int retVal = 0; - resDataArray = KAWASAKI_ref.command("TYPE TASK (1004)", 3000); // thread 4 ok --> " 1\r\n" - int.TryParse(resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""), out retVal); - answ = (retVal == 1); - } - return answ; - } - } - /// - /// Recupera nome e seriale macchina - /// - protected string machineName - { - get - { - string answ = ""; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE $id_true", 3000); // id macchina --> "BX100N-B001 Sn. 2366\r\n" - answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""); - } - return answ; - } - } - /// - /// Recupera ultima missione svolta - /// - protected string lastMission - { - get - { - string answ = ""; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE $exe", 3000); // missione --> "\r\n" (vuoto, no missione) - answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", ""); - } - return answ; - } - } - /// - /// Restituisce stato macchina nel formato (da sx a dx): - /// B0: POWER_ON - /// B1: AUTO - /// B2: RUN - /// B3: ERROR - /// B4: ALLARME - /// B5: EMERGENZA OK - /// B6: PORTA CHIUSA - /// B7: PRONTO AL LOAD - /// - protected string currBitmapStatus - { - get - { - string answ = ""; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE $status", 3000); // status --> "0|0|1|0|0|1|0|0\r\n" - answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", "").Replace("|", ""); -#if false - // reverse stringa (B0 portato a sx) - szBitmap = utils.reverseStr(szBitmap); - // ora converto bitmap string in INT - answ = Convert.ToInt32(szBitmap, 2); -#endif - } - return answ; - } - } - /// - /// Restituisce SEGNALI macchina nel formato: - /// B0: Transfer in auto - /// B1: Punzonatrice in AUTO - /// B2: Barriera tavola ripristinata - /// B3: Aria in linea OK - /// B4: Console Transfer in fuori ingombro - /// B5: TAV A - /// B6: TAV B - /// B7: Richiesta accesso attiva - /// - protected string currBitmapSignals - { - get - { - string answ = ""; - if (KAWASAKI_ref.IsConnected) - { - resDataArray = KAWASAKI_ref.command("TYPE $signal", 3000); // segnali --> "1|0|1|1|1|0|0|0\r\n" - answ = resDataArray[1].ToString().Replace("\n", "").Replace("\r", "").Replace("|", ""); -#if false - // reverse stringa (B0 portato a sx) - szBitmap = utils.reverseStr(szBitmap); - // ora converto bitmap string in INT - answ = Convert.ToInt32(szBitmap, 2); -#endif - } - return answ; - } - } + #endregion Protected Methods - /// - /// Effettua salvataggio del programma corrente - /// - /// Dir di riferimento - /// Nome Programma (se mancasse *.as lo aggiunge) - private void saveProgram(string progDir = "prog", string progName = "current.as") - { - // path completo - progName = progName.EndsWith(".as") ? progName : progName + ".as"; - string prgPath = progName;// string.Format("{0}/{1}", progDir, progName); - if (KAWASAKI_ref.IsConnected) - { - // comandi x setup programma... - resDataArray = KAWASAKI_ref.command("ferma", 3000); // ferma processi (all) --> "" - resDataArray = KAWASAKI_ref.command("togli", 3000); // toglie processi da pronta esecuzione --> "" + #region Public Methods - //resp = com.command("SAVE nome_del_file", 3000); // salvataggio file... FORSE --> "\u0005\u0002Bnome_del_file.as\u0017" --> verificare DOVE salva... - - int ret = KAWASAKI_ref.save(prgPath); // SAVE current.as[RET] - if (ret == 0) + /// + /// Processo i task richiesti e li elimino dalla coda 1:1 + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) { - // Success + // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti... + Dictionary taskDone = new Dictionary(); + bool taskOk = false; + string taskVal = ""; + + // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4 + 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.setArt: + case taskType.setComm: + case taskType.setProg: + case taskType.sendWatchDogMes2Plc: + taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; + break; + + case taskType.forceResetPzCount: + // reset contapezzi inizio setup + taskOk = resetcontapezziPLC(); + taskVal = taskOk ? "FORCE RESET PZ COUNT" : "FORCE RESET DISABLED | NO EXEC"; + break; + + case taskType.forceSetPzCount: + // reset contapezzi inizio setup + int newPzCount = 0; + int.TryParse(item.Value, out newPzCount); + if (newPzCount >= 0) + { + taskOk = setcontapezziPLC(newPzCount); + taskVal = taskOk ? $"FORCE SET PZ COUNT TO {newPzCount}" : $"FORCE SET PZ COUNT TO {newPzCount} | NO EXEC"; + } + else + { + taskVal = $"ERROR IN FORCE SET PZ COUNT TO {newPzCount}"; + } + break; + + case taskType.startSetup: + // reset contapezzi inizio setup + taskOk = resetcontapezziPLC(); + taskVal = taskOk ? "RESET: SETUP START" : "PZ RESET DISABLED | NO EXEC"; + break; + + case taskType.stopSetup: + // reset contapezzi fine setup // reset contapezzi fine setup SE ESPLICITAMENTE IMPOSTATO + if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET_stopSetup") == "TRUE") + { + resetcontapezziPLC(); + } + taskVal = taskOk ? "RESET: SETUP END" : "PZ RESET DISABLED | NO EXEC"; + break; + + default: + taskVal = "SKIPPED | NO EXEC"; + break; + } + taskDone.Add(item.Key, taskVal); + } + + return taskDone; } - if (ret == -1) + + /// + /// Recupero dati dinamici... + /// + public override Dictionary getDynData() { - // Communication error + // valore non presente in vers default... se gestito fare override + Dictionary outVal = new Dictionary(); + outVal.Add("LAST_MISS", lastMissRobot); + outVal.Add("LAST_TC", lastTC.ToString()); + outVal.Add("NUM_PZ_PREL", pzPrelevati.ToString()); + outVal.Add("NUM_PZ_LAV", pzCounter.ToString()); + outVal.Add("CURR_SIGNALS", currBitmapSignals.ToString()); + return outVal; } - if (ret == -2) + + /// + /// Recupero programma in lavorazione + /// + /// + public override string getPrgName() { - // Robot Controller error + // valore non presente in vers default... se gestito fare override + string prgName = ""; + return prgName; } - if (ret == -3) + + /// + /// Recupero info sistema generiche + /// + public override Dictionary getSysInfo() { - // Internal error + // valore non presente in vers default... se gestito fare override + Dictionary outVal = new Dictionary(); + outVal.Add("MACHINE", machineName); + return outVal; } - } - } - /// - /// Effettua invio del programma di alvorazione al ROBOT - /// Dir di riferimento - /// Nome Programma (se mancasse *.as lo aggiunge) - /// - private void sendProgram(string progDir = "prog", string progName = "default.as") - { - // path completo - progName = progName.EndsWith(".as") ? progName : progName + ".as"; - string prgPath = progName;// string.Format("{0}/{1}", progDir, progName); - // comandi x setup programma... - resDataArray = KAWASAKI_ref.command("ferma", 3000); // ferma processi (all) --> "" - resDataArray = KAWASAKI_ref.command("togli", 3000); // toglie processi da pronta esecuzione --> "" - - if (KAWASAKI_ref.IsConnected) - { - // carico... - KAWASAKI_ref.asInquiry = delegate (string as_msg) + /// + /// Effettua vero processing contapezzi + /// + public override void processContapezzi() { - Console.WriteLine(as_msg); if (as_msg.StartsWith("Are you sure ?")) - { - return "0\n"; // 0 [RET] - } - - if (as_msg.StartsWith("Load data?")) - { - return "1\n"; // 1 [RET] - } - - return null; - }; - int retLoad = KAWASAKI_ref.load(prgPath, "/Q"); // LOAD/Q default.as[RET] - } - } - - - #region Metodi specifici (da verificare/completare in implementazione) - - - /// - /// Effettua vero processing contapezzi - /// - public override void processContapezzi() - { - if (utils.CRB("enableContapezzi")) - { - try - { - // hard coded... !!!FARE!!! rivedere megio conf - contapezziPLC = pzCounter; - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) - if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) - { + if (utils.CRB("enableContapezzi")) + { + try + { + // hard coded... !!!FARE!!! rivedere megio conf + contapezziPLC = pzCounter; + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) + { #if false string memAddr = getOptPar("PZCOUNT_MODE"); if (memAddr.StartsWith("STD")) @@ -748,15 +847,18 @@ namespace IOB_WIN 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; break; + default: break; } @@ -769,246 +871,213 @@ namespace IOB_WIN } } stopwatch.Stop(); - } + } #endif - } - } - catch (Exception exc) - { - lgError(exc, "Errore in contapezzi KAWASAKI"); - } - } - } - /// - /// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid) - /// - public override void processOverride() - { - } - /// - /// Effettua lettura semafori principale - /// Parametri da aggiornare x display in form - /// - public override void readSemafori(ref newDisplayData currDispData) - { - try - { - if (verboseLog) - { - lgInfo("inizio read semafori"); - } - currDispData.semIn = Semaforo.SV; - - // effettuo TUTTE le letture - threadOk = commThreadOk; - cStatus = currBitmapStatus; - cSignals = currBitmapSignals; - contapezziPLC = pzCounter; - // decodifica e gestione - decodeToBaseBitmap(); - decodeOtherData(); - reportRawInput(ref currDispData); - // se trova ok thread --> aggiorno ultima lettura - if (threadOk) - { - lastReadPLC = DateTime.Now; - } - } - catch - { - currDispData.semIn = Semaforo.SR; - } - } - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - private void decodeToBaseBitmap() - { - // init a zero... - B_input = 0; - /* ----------------------------------------------------- - * bitmap MAPO - * B0: POWER_ON - * B1: RUN - * B2: pzCount - * B3: allarme - * B4: manuale - * B5: emergenza - * B6: error prog - * B7: auto mode - ----------------------------------------------------- */ - // bit 0 (poweron) imposto a 1 SE connected... - B_input = KAWASAKI_ref.IsConnected ? 1 : 0; - // RUN - if (cStatus[2] == '1') - { - B_input += (1 << 1); - } - // ERROR prog/macchina - if (cStatus[3] == '1') - { - B_input += (1 << 6); - } - // allarme - if (cStatus[4] == '1') - { - B_input += (1 << 3); - } - // Automatico (porta chiusa) - if (cStatus[6] == '1' || cStatus[1] == '1') - { - B_input += (1 << 4); - } - // NON EMERGENZA (1=armed, 0=triggered) - if (cStatus[5] == '0') - { - B_input += (1 << 5); - } - - // process ODL e contapezzi - string currODL = ""; - try - { - currODL = utils.callUrl(urlGetCurrODL); - // solo SE HO un ODL... - if (string.IsNullOrEmpty(currODL) || currODL == "0") - { - if (periodicLog) - { - lgInfo(string.Format("Kawasaki | Lettura ODL andata a vuoto: currODL: {0}", currODL)); - } - } - else - { // se variato o scaduto timeout log... - if (periodicLog || (currIdxODL.ToString() != currODL)) - { - lgInfo(string.Format("Kawasaki | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); - } - // 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 (!string.IsNullOrEmpty(currODL)) - { - if (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)) - { - // se sono differenti MOSTRO... - if (contapezziPLC != contapezziIOB) - { - // registro contapezzi - lgInfo($"Differenza Contapezzi CNC/IOB: contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); + } + } + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi KAWASAKI"); + } } - // verifico se variato contapezzi... e se passato ritardo minimo... - if (contapezziPLC > contapezziIOB) - { - // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio - contapezziIOB++; - needRefreshPzCount = true; - // salvo in semaforo! - B_input += (1 << 2); - // registro contapezzi - lgInfo($"contapezziPLC KAWASAKI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - } - else if (contapezziIOB > contapezziPLC) - { - lgInfo($"Contapezzi IOB > CNC --> NON INVIO (contapezziPLC: {contapezziPLC} < contapezziIOB: {contapezziIOB})"); - } - - // invio a server contapezzi (aggiornato) - string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); - // verifica se tutto OK - if (retVal != contapezziIOB.ToString()) - { - // errore salvataggio contapezzi - lgInfo($"Errore salvataggio Contapezzi KAWASAKI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); - // rileggo il counter pezzi da server - pzCntReload(true); - } - // resetto timer... - lastPzCountSend = DateTime.Now; - } } - else + + /// + /// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid) + /// + public override void processOverride() { - lgError("Attenzione non trovato ODL --> currODL = 0"); } - } - else - { - if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + + /// + /// Effettua lettura semafori principale + /// Parametri da aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) { - lgError($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC KAWASAKI {contapezziPLC} | contapezziIOB {contapezziIOB}"); - // resetto timer... - lastPzCountSend = DateTime.Now; + try + { + if (verboseLog) + { + lgInfo("inizio read semafori"); + } + currDispData.semIn = Semaforo.SV; + + // effettuo TUTTE le letture + threadOk = commThreadOk; + cStatus = currBitmapStatus; + cSignals = currBitmapSignals; + contapezziPLC = pzCounter; + // decodifica e gestione + decodeToBaseBitmap(); + decodeOtherData(); + reportRawInput(ref currDispData); + // se trova ok thread --> aggiorno ultima lettura + if (threadOk) + { + lastReadPLC = DateTime.Now; + } + } + catch + { + currDispData.semIn = Semaforo.SR; + } } - } - // log opzionale! - if (verboseLog) - { - lgInfo($"Trasformazione B_input: {B_input}"); - } - } + /// + /// Effettua reset del contapezzi + /// + /// + public override bool resetcontapezziPLC() + { + bool answ = false; + // ...SE abilitato da conf IOB + if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET") == "TRUE") + { + // scrivo valore 0 x il contapezzi + try + { + pzCounter = 0; + } + catch (Exception exc) + { + lgError(exc, "Errore in RESET contapezzi KAWASAKI"); + connectionOk = false; + } + answ = true; + } + else + { + lgError("Impossibile effettuare RESET contapezzi KAWASAKI, mancanza parametro OPT:ENABLE_PZ_RESET"); + } + return answ; + } - /// - /// Decodifica il resto dell'area x i dati accessori (allarmi, ...) - /// - private void decodeOtherData() - { - if (verboseLog) - { + /// + /// Effettua IMPOSTAZIONE FORZATA del contapezzi + /// + /// + public override bool setcontapezziPLC(int newPzCount) + { + bool answ = false; + // ...SE abilitato da conf IOB + if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET") == "TRUE") + { + // scrivo valore 0 x il contapezzi + try + { + pzCounter = newPzCount; + } + catch (Exception exc) + { + lgError(exc, "Errore in SET contapezzi KAWASAKI"); + connectionOk = false; + } + answ = true; + } + else + { + lgError("Impossibile effettuare SET contapezzi KAWASAKI, mancanza parametro OPT:ENABLE_PZ_RESET"); + } + return answ; + } - } - } + /// + /// 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("KAWASAKI: ConnKO - tryConnect"); + } + // in primis salvo data ping... + lastPING = DateTime.Now; + // se passa il ping faccio il resto... + if (testPingMachine == IPStatus.Success) + { + string szStatusConnection = ""; + try + { + // ora provo connessione... + parentForm.commPlcActive = true; + string connPar = string.Format("TCP {0}", cIobConf.cncIpAddr); + KAWASAKI_ref.connect(connPar); + parentForm.commPlcActive = false; + lgInfo("szStatusConnection: " + KAWASAKI_ref.IsConnected); + connectionOk = true; + // verifico se sta girando + if (connectionOk) + { + if (adpRunning) + { + lgInfo("Connessione OK"); + } + } + else + { + lgError("Impossibile procedere, connessione mancante..."); + } + } + catch (Exception exc) + { + lgFatal(string.Format("Errore nella connessione all'adapter KAWASAKI: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc)); + connectionOk = false; + lgInfo(string.Format("Eccezione in TryConnect, Adapter KAWASAKI NON running, pausa di {0} msec prima di ulteriori tentativi di riconnessione", utils.CRI("waitRecMSec"))); + } + } + else + { + // loggo no risposta ping ... + connectionOk = false; + needRefresh = true; + if (verboseLog || periodicLog) + { + lgInfo(string.Format("Attenzione: KAWASAKI controllo PING fallito per IP {0}", cIobConf.cncIpAddr)); + } + } + } + } + // se non è ancora connesso faccio processing memoria caso disconnesso... + if (!connectionOk) + { + // processo semafori ed invio... + processMemoryDiscon(); + } + } - /// - /// Recupero programma in lavorazione - /// - /// - public override string getPrgName() - { - // valore non presente in vers default... se gestito fare override - string prgName = ""; - return prgName; - } - /// - /// Recupero info sistema generiche - /// - public override Dictionary getSysInfo() - { - // valore non presente in vers default... se gestito fare override - Dictionary outVal = new Dictionary(); - outVal.Add("MACHINE", machineName); - return outVal; - } - /// - /// Recupero dati dinamici... - /// - public override Dictionary getDynData() - { - // valore non presente in vers default... se gestito fare override - Dictionary outVal = new Dictionary(); - outVal.Add("LAST_MISS", lastMissRobot); - outVal.Add("LAST_TC", lastTC.ToString()); - outVal.Add("NUM_PZ_PREL", pzPrelevati.ToString()); - outVal.Add("NUM_PZ_LAV", pzCounter.ToString()); - outVal.Add("CURR_SIGNALS", currBitmapSignals.ToString()); - return outVal; - } + /// + /// Override disconnessione + /// + public override void tryDisconnect() + { + if (connectionOk) + { + connectionOk = false; + string szStatusConnection = ""; + try + { + KAWASAKI_ref.disconnect(); + lgInfo(szStatusConnection); + lgInfo("Effettuata disconnessione adapter KAWASAKI!"); + } + catch (Exception exc) + { + lgFatal(exc, "Errore nella disconnessione dall'adapter KAWASAKI"); + } + } + else + { + lgError("IMPOSSIBILE effettuare disconnessione KAWASAKI: Connessione non disponibile..."); + } + needRefresh = true; + } - #endregion - } -} + #endregion Public Methods + } +} \ No newline at end of file diff --git a/IOB-WIN/IobOSAI.cs b/IOB-WIN/IobOSAI.cs index 3ee01344..4e3fe929 100644 --- a/IOB-WIN/IobOSAI.cs +++ b/IOB-WIN/IobOSAI.cs @@ -9,678 +9,739 @@ using CVCncLib; namespace IOB_WIN { - public class IobOSAI : IobGeneric - { - - /// - /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO - /// - Dictionary signLUT = new Dictionary(); - /// - /// Struttura dati principale in continuo update... - /// - protected Cndex.GETINFO1DATA oData; - /// - /// Vettore degli allarmi CNC attivi - /// - public Dictionary allarmiCNC = new Dictionary(); - /// - /// Stato corrente (da classe ENUM) - /// - public CNC_STATUS_OSAI currStatus; - /// - /// Oggetto MAIN x connessione OSAI - /// - protected ComCNOsai OSAI_ref; - /// - /// estende l'init della classe base... - /// - /// - /// - public IobOSAI(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) + public class IobOSAI : IobGeneric { - // gestione invio ritardato contapezzi - pzCountDelay = utils.CRI("pzCountDelay"); - lastPzCountSend = DateTime.Now; - lastWarnODL = DateTime.Now; - if (IOBConf != null) - { - // inizializzo correttamente aree memoria secondo CONF - iniFileName - if (!string.IsNullOrEmpty(IOBConf.iniFileName)) + #region Private Fields + + /// + /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO + /// + private Dictionary signLUT = new Dictionary(); + + #endregion Private Fields + + #region Protected Fields + + /// + /// Struttura dati principale in continuo update... + /// + protected Cndex.GETINFO1DATA oData; + + /// + /// Oggetto MAIN x connessione OSAI + /// + protected ComCNOsai OSAI_ref; + + #endregion Protected Fields + + #region Public Fields + + /// + /// Vettore degli allarmi CNC attivi + /// + public Dictionary allarmiCNC = new Dictionary(); + + /// + /// Stato corrente (da classe ENUM) + /// + public CNC_STATUS_OSAI currStatus; + + #endregion Public Fields + + #region Public Constructors + + /// + /// estende l'init della classe base... + /// + /// + /// + public IobOSAI(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { - IniFile fIni = new IniFile(IOBConf.iniFileName); - - // fix enable prgName - enablePrgName = fIni.ReadBoolean("CNC", "GETPRGNAME", true); - - // effettuo lettura della conf sigLUT... cercando 1:1 i bit... - string currBit = ""; - string memArea = ""; - for (int i = 0; i < 8; i++) - { - currBit = string.Format("BIT{0}", i); - memArea = fIni.ReadString("MEMORY", currBit, ""); - // se trovo un valore... - if (!string.IsNullOrEmpty(memArea)) + // gestione invio ritardato contapezzi + pzCountDelay = utils.CRI("pzCountDelay"); + lastPzCountSend = DateTime.Now; + lastWarnODL = DateTime.Now; + if (IOBConf != null) { - signLUT.Add(currBit, memArea); + // inizializzo correttamente aree memoria secondo CONF - iniFileName + if (!string.IsNullOrEmpty(IOBConf.iniFileName)) + { + IniFile fIni = new IniFile(IOBConf.iniFileName); + + // fix enable prgName + enablePrgName = fIni.ReadBoolean("CNC", "GETPRGNAME", true); + + // effettuo lettura della conf sigLUT... cercando 1:1 i bit... + string currBit = ""; + string memArea = ""; + for (int i = 0; i < 8; i++) + { + currBit = string.Format("BIT{0}", i); + memArea = fIni.ReadString("MEMORY", currBit, ""); + // se trovo un valore... + if (!string.IsNullOrEmpty(memArea)) + { + signLUT.Add(currBit, memArea); + } + } + } } - } - } - } - // è little endian (NON serve conversione) - hasBigEndian = false; - lgInfo("Start init Adapter OSAI, tipo all'IP/NOME {0}, variante {1} per IOB {2}", IOBConf.cncIpAddr, IOBConf.tipoIob, IOBConf.codIOB); + // è little endian (NON serve conversione) + hasBigEndian = false; + lgInfo("Start init Adapter OSAI, tipo all'IP/NOME {0}, variante {1} per IOB {2}", IOBConf.cncIpAddr, IOBConf.tipoIob, IOBConf.codIOB); - // Creo oggetto x gestione connessione/comunicazione NC: secondo il tipo creo CNDEX o OPEN - parentForm.commPlcActive = true; - if (IOBConf.tipoIob == tipoAdapter.OSAI_OPEN) - { - OSAI_ref = new Open_Series(IOBConf.cncIpAddr, false); - } - else if (IOBConf.tipoIob == tipoAdapter.OSAI_VB6) - { - OSAI_ref = new ComCNOSAIVB6(IOBConf.cncIpAddr, false); - } - else - { - OSAI_ref = new ComCNOsai(IOBConf.cncIpAddr, false); - } - parentForm.commPlcActive = false; - - if (isVerboseLog) - { - lgInfo(string.Format("INIT OSAI_ref da CncLib come {0}", IOBConf.tipoIob)); - } - - // disconnetto e connetto... - if (isVerboseLog) - { - lgInfo("OSAI: tryDisconnect"); - } - - tryDisconnect(); - lgInfo("OSAI: tryConnect"); - tryConnect(); - - - // recupero machine status e mode da cui decodificare info sul PLC... - byte machineStatus = OSAI_ref.GetMachineStatus(); - byte modeSelected = OSAI_ref.GetModeSelected(); - lgInfo(string.Format("Lettura preliminare: machineStatus={0} | modeSelected={1}", machineStatus, modeSelected)); - - // possiamo leggere tutto da qui che contiene status, mode e last_nc_error - oData = new Cndex.GETINFO1DATA(); - var ncInfo = OSAI_ref.NcInfo1(ref oData); - - lgInfo(string.Format("Lettura START completa NCINFO1DATA{0} lastNcError={1}{0}status={2}{0}substatus={9}{0}mode_select={3}{0}main_progr_name={4}{0}speed_ov={5}{0}progr_speed={6}{0}real_speed={7}{0}real_feed={8}{0}", Environment.NewLine, oData.last_nc_error, oData.status, oData.mode_select, oData.main_progr_name, oData.speed_ov, oData.progr_speed, oData.real_speed, oData.real_feed, oData.substatus)); - - // inizio il calcolo dello status semaforico - short bitStatus = 0; - if (OSAI_ref.Connected) - { - bitStatus += 1; - } - - if (utils.CRB("enableContapezzi")) - { - lgInfo("OSAI: inizio gestione contapezzi"); - try - { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) - if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) - { - if (getOptPar("PZCOUNT_MODE").StartsWith("OVAR")) + // Creo oggetto x gestione connessione/comunicazione NC: secondo il tipo creo CNDEX o OPEN + parentForm.commPlcActive = true; + if (IOBConf.tipoIob == tipoAdapter.OSAI_OPEN) { - lgInfo("Init contapezzi OSAI: pzCntReload(true)"); - pzCntReload(true); - // refresh associazione Macchina - IOB - sendM2IOB(); - // per adesso imposto lettura dal CNC == contapezzi (poi farà vera lettura...) - contapezziPLC = contapezziIOB; + OSAI_ref = new Open_Series(IOBConf.cncIpAddr, false); + } + else if (IOBConf.tipoIob == tipoAdapter.OSAI_VB6) + { + OSAI_ref = new ComCNOSAIVB6(IOBConf.cncIpAddr, false); } else { - contapezziIOB = 0; - lgInfo("Contapezzi STD disabilitato: modalità {0}", getOptPar("PZCOUNT_MODE")); + OSAI_ref = new ComCNOsai(IOBConf.cncIpAddr, false); } - } - else - { - contapezziIOB = 0; - lgInfo("Parametro mancante PZCOUNT_MODE"); - } + parentForm.commPlcActive = false; + + if (isVerboseLog) + { + lgInfo(string.Format("INIT OSAI_ref da CncLib come {0}", IOBConf.tipoIob)); + } + + // disconnetto e connetto... + if (isVerboseLog) + { + lgInfo("OSAI: tryDisconnect"); + } + + tryDisconnect(); + lgInfo("OSAI: tryConnect"); + tryConnect(); + + // recupero machine status e mode da cui decodificare info sul PLC... + byte machineStatus = OSAI_ref.GetMachineStatus(); + byte modeSelected = OSAI_ref.GetModeSelected(); + lgInfo(string.Format("Lettura preliminare: machineStatus={0} | modeSelected={1}", machineStatus, modeSelected)); + + // possiamo leggere tutto da qui che contiene status, mode e last_nc_error + oData = new Cndex.GETINFO1DATA(); + var ncInfo = OSAI_ref.NcInfo1(ref oData); + + lgInfo(string.Format("Lettura START completa NCINFO1DATA{0} lastNcError={1}{0}status={2}{0}substatus={9}{0}mode_select={3}{0}main_progr_name={4}{0}speed_ov={5}{0}progr_speed={6}{0}real_speed={7}{0}real_feed={8}{0}", Environment.NewLine, oData.last_nc_error, oData.status, oData.mode_select, oData.main_progr_name, oData.speed_ov, oData.progr_speed, oData.real_speed, oData.real_feed, oData.substatus)); + + // inizio il calcolo dello status semaforico + short bitStatus = 0; + if (OSAI_ref.Connected) + { + bitStatus += 1; + } + + if (utils.CRB("enableContapezzi")) + { + lgInfo("OSAI: inizio gestione contapezzi"); + try + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) + { + if (getOptPar("PZCOUNT_MODE").StartsWith("OVAR")) + { + lgInfo("Init contapezzi OSAI: pzCntReload(true)"); + pzCntReload(true); + // refresh associazione Macchina - IOB + sendM2IOB(); + // per adesso imposto lettura dal CNC == 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 OSAI"); + } + } + // finisco INIT ADAPTER + lgInfo("End init Adapter OSAI"); } - catch (Exception exc) + + #endregion Public Constructors + + #region Private Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + private void decodeToBitmap() { - lgError(exc, "Errore in contapezzi OSAI"); + // init a zero... + B_input = 0; + // SE SI E' CONNESSO al CNC allora è 1=powerON... + if (OSAI_ref.Connected) + { + B_input += 1 << 0; + } + + // decodifico impiegando dictionary... cercando il TIPO di memoria & co... + string bKey = ""; + string bVal = ""; + 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")) + { + // procedo SOLO SE è enabled IOB + if (IobOnline) + { + try + { + currODL = utils.callUrl(urlGetCurrODL); + // solo SE HO un ODL... + if (string.IsNullOrEmpty(currODL) || currODL == "0") + { + if (periodicLog) + { + lgInfo(string.Format("Osai | Lettura ODL andata a vuoto: currODL: {0}", currODL)); + } + } + else + { + lgInfo(string.Format("Osai | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); + // 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; + } + } + } + else + { + // imposto currODL a vuoto! + currODL = ""; + if (periodicLog) + { + lgInfo($"OSAI | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); + } + } + if (!string.IsNullOrEmpty(currODL) && currODL != "0") + { + // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + // se sono differenti MOSTRO... + if (contapezziPLC != contapezziIOB) + { + // registro contapezzi + lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + } + // verifico se variato contapezzi in area STD PAR6711... e se passato ritardo minimo... + if (contapezziPLC > contapezziIOB) + { + // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio + contapezziIOB++; + needRefreshPzCount = true; + // salvo in semaforo! + B_input += 1 << 2; + // registro contapezzi + lgInfo($"contapezziPLC OSAI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + } + + // invio a server contapezzi (aggiornato) + string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); + // verifica se tutto OK + if (retVal != contapezziIOB.ToString()) + { + // errore salvataggio contapezzi + lgInfo($"Errore salvataggio Contapezzi OSAI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); + // rileggo il counter pezzi da server + pzCntReload(true); + } + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + else + { + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC OSAI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + } + // controllo le condizioni x costruire il bit1 RUN! + if (oData.mode_select == 2 && oData.status == 2) + { + B_input += 1 << 1; + } + // errore su bit3 + if (oData.mode_select == 6) + { + B_input += 1 << 3; + } + // auto su bit4 + if (oData.mode_select != 2) + { + B_input += 1 << 4; + } + // emergenza su bit5 + if (oData.mode_select == 9) + { + B_input += 1 << 5; + } + } + } + // log opzionale! + if (verboseLog) + { + lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); + } } - } - // finisco INIT ADAPTER - lgInfo("End init Adapter OSAI"); - } - /// - /// Override disconnessione - /// - public override void tryDisconnect() - { - if (connectionOk) - { - string szStatusConnection = ""; - try + + #endregion Private Methods + + #region Protected Methods + + /// + /// Decodifica del MODE selezionato + /// + /// + /// + protected static CNC_MODE decodeModeOsai(int mode) { - OSAI_ref.CloseSession(); - connectionOk = false; - // resetto timing! - TimingData.resetData(); - lgInfo(szStatusConnection); - lgInfo("Effettuata disconnessione adapter OSAI!"); + CNC_MODE answ = CNC_MODE.ND; + switch (mode) + { + case 1: + answ = CNC_MODE.MDI; + break; + + case 2: + answ = CNC_MODE.AUTO; + break; + + case 3: + answ = CNC_MODE.SEMI; + break; + + case 4: + answ = CNC_MODE.JOG_MAN; + break; + + case 5: + answ = CNC_MODE.JOG_INC; + break; + + case 6: + answ = CNC_MODE.PROFILE; + break; + + case 7: + answ = CNC_MODE.HOME; + break; + + case 8: + answ = CNC_MODE.HANDLE_INC; + break; + + default: + break; + } + return answ; } - catch (Exception exc) + + #endregion Protected Methods + + #region Public Methods + + /// + /// Recupera e processa allarmi CNC... + /// + public override Dictionary getCncAlarms() { - lgFatal(exc, "Errore nella disconnessione dall'adapter OSAI"); + Dictionary outVal = new Dictionary(); + // se ho allarmi li accodo... + if (oData.last_nc_error != 0) + { + try + { + outVal.Add("CNC_ALARM", (oData.last_nc_error).ToString()); + } + catch (Exception exc) + { + lg.Error(exc, "Eccezione in getCncAlarms"); + } + } + return outVal; } - } - else - { - lgError("IMPOSSIBILE effettuare disconnessione: 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")) + + /// + /// Recupero dati dinamici... + /// + public override Dictionary getDynData() { - if (verboseLog || periodicLog) - { - lgInfo("OSAI: ConnKO - tryConnect"); - } - // PING SOLO x OPEN!!! - bool needPing = (cIobConf.tipoIob == tipoAdapter.OSAI_OPEN); - bool pingOk = false; - Ping pingSender = new Ping(); - PingReply reply = pingSender.Send("127.0.0.1", 100); - // se serve PING... - if (needPing) - { - // in primis salvo data ping... - lastPING = DateTime.Now; - // ora PING!!! - IPAddress address = IPAddress.Loopback; - IPAddress.TryParse(cIobConf.cncIpAddr, out address); - reply = pingSender.Send(address, 100); - pingOk = reply.Status == IPStatus.Success; - } - // se passa il ping faccio il resto... - if (pingOk || !needPing) - { - string szStatusConnection = ""; + Dictionary outVal = new Dictionary(); + stopwatch.Restart(); try { - // ora provo connessione... - parentForm.commPlcActive = true; - bool fatto = OSAI_ref.OpenSession(); - if (!fatto) - { - // log errore! - lgInfo("Impossibile effettuare apertura sessione: " + OSAI_ref.ErrMsg); - } - parentForm.commPlcActive = false; - lgInfo("szStatusConnection: " + szStatusConnection); - connectionOk = true; - // refresh stato allarmi!!! - if (connectionOk) - { - dtAvvioAdp = DateTime.Now; - if (adpRunning) + string actf = oData.real_feed.ToString(); + string acts = oData.real_speed.ToString(); + outVal.Add("DYNDATA", string.Format("FEED {0}#SPEED_RPM {1}", actf, acts)); + + if (utils.CRB("SendFeedSpeed")) { - lgInfo("Connessione OK"); + outVal.Add("FEED", actf); + outVal.Add("SPEED_RPM", acts); + //outVal.Add("NUM_ALARM", numAlarm); + outVal.Add("ACT_TOOL", oData.actual_tool.ToString()); + } + if (utils.CRB("SendAxPos")) + { + // salvo info assi... + outVal.Add("AX_SEL", oData.ax_sel.ToString()); + outVal.Add("NUM_AX_SEL", oData.num_ax_sel.ToString()); } - } - else - { - lgError("Impossibile procedere, connessione mancante..."); - } } catch (Exception exc) { - lgFatal(string.Format("Errore nella connessione all'adapter OSAI: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc)); - connectionOk = false; - lgInfo(string.Format("Eccezione in TryConnect, Adapter NON running, pausa di {0} msec prima di ulteriori tentativi di riconnessione", utils.CRI("waitRecMSec"))); + lgError(exc, "Errore in getDynData"); } - } - else - { - // loggo no risposta ping ... - connectionOk = false; - if (needPing) - { - if (verboseLog || periodicLog) - { - lgInfo(string.Format("Attenzione: controllo PING fallito per IP {0} - {1}", cIobConf.cncIpAddr, reply.Status)); - } - } - } - } - } - // se non è ancora connesso faccio procesisng memoria caso disconnesso... - if (!connectionOk) - { - // processo semafori ed invio... - processMemoryDiscon(); - } - } - /// - /// Effettua lettura semafori principale - /// Parametri da aggiornare x display in form - /// - public override void readSemafori(ref newDisplayData currDispData) - { - base.readSemafori(ref currDispData); - try - { - if (verboseLog) - { - lgInfo("inizio read semafori"); + stopwatch.Stop(); + return outVal; } - currDispData.semIn = Semaforo.SV; - - stopwatch.Restart(); - // possiamo leggere tutto da qui che contiene tutto: status, mode, last_nc_error - var ncInfo = OSAI_ref.NcInfo1(ref oData); - // time rec - if (utils.CRB("recTime")) + /// + /// Recupero dati override (da area G che è già stata letta...) + /// + /// + public override Dictionary getOverrides() { - TimingData.addResult(cIobConf.codIOB, "GETINFO1DATA", stopwatch.ElapsedTicks); + Dictionary outVal = new Dictionary(); + outVal.Add("FEED_OVER", (oData.feed_ov).ToString()); + outVal.Add("RAPID_OVER", (oData.rapid_override).ToString()); + return outVal; } - stopwatch.Stop(); - // salvo il solo BYTE dell'input decifrando il semaforo... - decodeToBitmap(); - } - catch (Exception exc) - { - lgError(string.Format("Eccezione in readSemafori:{0}{1}", Environment.NewLine, exc)); - connectionOk = false; - currDispData.semIn = Semaforo.SR; - } - } - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - private void decodeToBitmap() - { - // init a zero... - B_input = 0; - // SE SI E' CONNESSO al CNC allora è 1=powerON... - if (OSAI_ref.Connected) - { - B_input += 1 << 0; - } - - // decodifico impiegando dictionary... cercando il TIPO di memoria & co... - string bKey = ""; - string bVal = ""; - for (int i = 0; i < 8; i++) - { - bKey = string.Format("BIT{0}", i); - // cerco se ci sia in LUT - if (signLUT.ContainsKey(bKey)) + /// + /// Recupero programma in lavorazione + /// + /// + public override string getPrgName() { - // recupero nome variabile... - bVal = signLUT[bKey]; - // se l'area è PZCOUNT... processo PUNTUALMENTE il CONTAPEZZI... - if (bVal.StartsWith("PZCOUNT")) - { - string currODL = ""; + string prgName = ""; + // recupero NUOVO prgName... try { - currODL = utils.callUrl(urlGetCurrODL); - // solo SE HO un ODL... - if (string.IsNullOrEmpty(currODL) || currODL == "0") - { - if (periodicLog) - { - lgInfo(string.Format("Osai | Lettura ODL andata a vuoto: currODL: {0}", currODL)); - } - } - else - { - lgInfo(string.Format("Osai | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); - // provo a salvare nuovo ODL - int.TryParse(currODL, out currIdxODL); - } + // recupero nome programma MAIN + prgName = System.Text.Encoding.Default.GetString(oData.main_progr_name); + // trimmo path del programma, ovvero "CNCMEMUSERPATH1" + prgName = prgName.Replace(utils.CRS("basePrgMemPath"), ""); + lgInfo("Current PROG: {0}", prgName); } 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; - } + lgError(string.Format("Eccezione in recupero PRG NAME MAIN:{0}{1}", Environment.NewLine, exc)); + connectionOk = false; } - if (!string.IsNullOrEmpty(currODL) && currODL != "0") - { - // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture - if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) - { - - // se sono differenti MOSTRO... - if (contapezziPLC != contapezziIOB) - { - // registro contapezzi - lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - } - // verifico se variato contapezzi in area STD PAR6711... e se passato ritardo minimo... - if (contapezziPLC > contapezziIOB) - { - // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio - contapezziIOB++; - needRefreshPzCount = true; - // salvo in semaforo! - B_input += 1 << 2; - // registro contapezzi - lgInfo($"contapezziPLC OSAI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - } - - // invio a server contapezzi (aggiornato) - string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); - // verifica se tutto OK - if (retVal != contapezziIOB.ToString()) - { - // errore salvataggio contapezzi - lgInfo($"Errore salvataggio Contapezzi OSAI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); - // rileggo il counter pezzi da server - pzCntReload(true); - } - // resetto timer... - lastPzCountSend = DateTime.Now; - } - } - else - { - if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) - { - lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC OSAI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - // resetto timer... - lastPzCountSend = DateTime.Now; - } - } - } - // controllo le condizioni x costruire il bit1 RUN! - if (oData.mode_select == 2 && oData.status == 2) - { - B_input += 1 << 1; - } - // errore su bit3 - if (oData.mode_select == 6) - { - B_input += 1 << 3; - } - // auto su bit4 - if (oData.mode_select != 2) - { - B_input += 1 << 4; - } - // emergenza su bit5 - if (oData.mode_select == 9) - { - B_input += 1 << 5; - } + return prgName; } - } - // log opzionale! - if (verboseLog) - { - lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); - } - } - /// - /// Recupero programma in lavorazione - /// - /// - public override string getPrgName() - { - string prgName = ""; - // recupero NUOVO prgName... - try - { - // recupero nome programma MAIN - prgName = System.Text.Encoding.Default.GetString(oData.main_progr_name); - // trimmo path del programma, ovvero "CNCMEMUSERPATH1" - prgName = prgName.Replace(utils.CRS("basePrgMemPath"), ""); - lgInfo("Current PROG: {0}", prgName); - } - catch (Exception exc) - { - lgError(string.Format("Eccezione in recupero PRG NAME MAIN:{0}{1}", Environment.NewLine, exc)); - connectionOk = false; - } - return prgName; - } - /// - /// Effettua vero processing contapezzi appoggiato ad area specifica da CONF - /// - public override void processContapezzi() - { - if (utils.CRB("enableContapezzi")) - { - try + + /// + /// Effettua vero processing contapezzi appoggiato ad area specifica da CONF + /// + public override void processContapezzi() { - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) - if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) - { - string memAddr = getOptPar("PZCOUNT_MODE"); - if (memAddr.StartsWith("STD")) + if (utils.CRB("enableContapezzi")) { - // inizio verifica area memoria/parametro levando prima parte codice - memAddr = memAddr.Replace("STD.", ""); - // var di appoggio - int cntAddr = 0; - // verifico se si tratta di lettura MEMORIA... formato tipo STD.MEM.6711 - if (memAddr.StartsWith("MEM.")) - { - // recupero parametro... - int.TryParse(memAddr.Replace("MEM.", ""), out cntAddr); - if (cntAddr == 0) + try { - cntAddr = 29; + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE"))) + { + string memAddr = getOptPar("PZCOUNT_MODE"); + if (memAddr.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddr = memAddr.Replace("STD.", ""); + // var di appoggio + int cntAddr = 0; + // verifico se si tratta di lettura MEMORIA... formato tipo STD.MEM.6711 + if (memAddr.StartsWith("MEM.")) + { + // recupero parametro... + int.TryParse(memAddr.Replace("MEM.", ""), out cntAddr); + if (cntAddr == 0) + { + cntAddr = 29; + } + // processo parametro contapezzi (lavorati) + stopwatch.Restart(); + // vera lettura area memoria... + int resVal = 0; + // lettura variabili (es contapezzi) + resVal = (int)OSAI_ref.ReadVarSN((short)cntAddr); + + if (utils.CRB("recTime")) + { + TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-MEM", 2), stopwatch.ElapsedTicks); + } + // aggiungo in visualizzazione SE variata... + if (resVal != contapezziPLC) + { + string mCount = string.Format("MEM{0}", cntAddr); + string sVal = string.Format("[PZCOUNT]{0}|{1}", mCount, resVal); + // chiamo accodamento... + accodaFLog(sVal, qEncodeFLog(mCount, resVal.ToString())); + } + // salvo ultimo conteggio rilevato + contapezziPLC = resVal; + } + stopwatch.Stop(); + } + } } - // processo parametro contapezzi (lavorati) + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi CNC"); + connectionOk = false; + } + } + } + + /// + /// Esegue processing MODE (e nel contempo recupera altri dati dell'area G) + /// + public override void processMode() + { + if (utils.CRB("enableMode")) + { + try + { + // verifico modo con valore corrente, se cambia aggiorno... + CNC_MODE newMode = decodeModeOsai(oData.mode_select); + 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, string.Format("Errore in process Mode OSAI: {0}{1}", Environment.NewLine, exc)); + connectionOk = false; + stopwatch.Stop(); + } + } + // lo status lo processo SEMPRE + try + { + // verifico modo con valore corrente, se cambia aggiorno... + CNC_STATUS_OSAI newStatus = (CNC_STATUS_OSAI)(oData.status); + if (newStatus != currStatus) + { + // aggiorno! + currStatus = newStatus; + // accodo x invio + string sVal = string.Format("[CNC_STATUS]{0}", currStatus.ToString()); + // chiamo accodamento... + accodaFLog(sVal, qEncodeFLog("CNC_STATUS", currStatus.ToString())); + } + } + catch (Exception exc) + { + lgError(exc, string.Format("Errore in process Mode OSAI: {0}{1}", Environment.NewLine, exc)); + connectionOk = false; + stopwatch.Stop(); + } + } + + /// + /// Effettua lettura semafori principale + /// Parametri da aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) + { + base.readSemafori(ref currDispData); + try + { + if (verboseLog) + { + lgInfo("inizio read semafori"); + } + + currDispData.semIn = Semaforo.SV; + stopwatch.Restart(); - // vera lettura area memoria... - int resVal = 0; - // lettura variabili (es contapezzi) - resVal = (int)OSAI_ref.ReadVarSN((short)cntAddr); - + // possiamo leggere tutto da qui che contiene tutto: status, mode, last_nc_error + var ncInfo = OSAI_ref.NcInfo1(ref oData); + // time rec if (utils.CRB("recTime")) { - TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-MEM", 2), stopwatch.ElapsedTicks); + TimingData.addResult(cIobConf.codIOB, "GETINFO1DATA", stopwatch.ElapsedTicks); } - // aggiungo in visualizzazione SE variata... - if (resVal != contapezziPLC) - { - string mCount = string.Format("MEM{0}", cntAddr); - string sVal = string.Format("[PZCOUNT]{0}|{1}", mCount, resVal); - // chiamo accodamento... - accodaFLog(sVal, qEncodeFLog(mCount, resVal.ToString())); - } - // salvo ultimo conteggio rilevato - contapezziPLC = resVal; - } - stopwatch.Stop(); - } - } - } - catch (Exception exc) - { - lgError(exc, "Errore in contapezzi CNC"); - connectionOk = false; - } - } - } - /// - /// Esegue processing MODE (e nel contempo recupera altri dati dell'area G) - /// - public override void processMode() - { - if (utils.CRB("enableMode")) - { - try - { - // verifico modo con valore corrente, se cambia aggiorno... - CNC_MODE newMode = decodeModeOsai(oData.mode_select); - 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, string.Format("Errore in process Mode OSAI: {0}{1}", Environment.NewLine, exc)); - connectionOk = false; - stopwatch.Stop(); - } - } - // lo status lo processo SEMPRE - try - { - // verifico modo con valore corrente, se cambia aggiorno... - CNC_STATUS_OSAI newStatus = (CNC_STATUS_OSAI)(oData.status); - if (newStatus != currStatus) - { - // aggiorno! - currStatus = newStatus; - // accodo x invio - string sVal = string.Format("[CNC_STATUS]{0}", currStatus.ToString()); - // chiamo accodamento... - accodaFLog(sVal, qEncodeFLog("CNC_STATUS", currStatus.ToString())); - } - } - catch (Exception exc) - { - lgError(exc, string.Format("Errore in process Mode OSAI: {0}{1}", Environment.NewLine, exc)); - connectionOk = false; - stopwatch.Stop(); - } - } - /// - /// Decodifica del MODE selezionato - /// - /// - /// - protected static CNC_MODE decodeModeOsai(int mode) - { - CNC_MODE answ = CNC_MODE.ND; - switch (mode) - { - case 1: - answ = CNC_MODE.MDI; - break; - case 2: - answ = CNC_MODE.AUTO; - break; - case 3: - answ = CNC_MODE.SEMI; - break; - case 4: - answ = CNC_MODE.JOG_MAN; - break; - case 5: - answ = CNC_MODE.JOG_INC; - break; - case 6: - answ = CNC_MODE.PROFILE; - break; - case 7: - answ = CNC_MODE.HOME; - break; - case 8: - answ = CNC_MODE.HANDLE_INC; - break; - default: - break; - } - return answ; - } - /// - /// Recupero dati dinamici... - /// - public override Dictionary getDynData() - { - Dictionary outVal = new Dictionary(); - stopwatch.Restart(); - try - { - string actf = oData.real_feed.ToString(); - string acts = oData.real_speed.ToString(); - outVal.Add("DYNDATA", string.Format("FEED {0}#SPEED_RPM {1}", actf, acts)); + stopwatch.Stop(); - if (utils.CRB("SendFeedSpeed")) - { - outVal.Add("FEED", actf); - outVal.Add("SPEED_RPM", acts); - //outVal.Add("NUM_ALARM", numAlarm); - outVal.Add("ACT_TOOL", oData.actual_tool.ToString()); + // salvo il solo BYTE dell'input decifrando il semaforo... + decodeToBitmap(); + } + catch (Exception exc) + { + lgError(string.Format("Eccezione in readSemafori:{0}{1}", Environment.NewLine, exc)); + connectionOk = false; + currDispData.semIn = Semaforo.SR; + } } - if (utils.CRB("SendAxPos")) + + /// + /// Override connessione + /// + public override void tryConnect() { - // salvo info assi... - outVal.Add("AX_SEL", oData.ax_sel.ToString()); - outVal.Add("NUM_AX_SEL", oData.num_ax_sel.ToString()); + 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("OSAI: ConnKO - tryConnect"); + } + // PING SOLO x OPEN!!! + bool needPing = (cIobConf.tipoIob == tipoAdapter.OSAI_OPEN); + bool pingOk = false; + Ping pingSender = new Ping(); + PingReply reply = pingSender.Send("127.0.0.1", 100); + // se serve PING... + if (needPing) + { + // in primis salvo data ping... + lastPING = DateTime.Now; + // ora PING!!! + IPAddress address = IPAddress.Loopback; + IPAddress.TryParse(cIobConf.cncIpAddr, out address); + reply = pingSender.Send(address, 100); + pingOk = reply.Status == IPStatus.Success; + } + // se passa il ping faccio il resto... + if (pingOk || !needPing) + { + string szStatusConnection = ""; + try + { + // ora provo connessione... + parentForm.commPlcActive = true; + bool fatto = OSAI_ref.OpenSession(); + if (!fatto) + { + // log errore! + lgInfo("Impossibile effettuare apertura sessione: " + OSAI_ref.ErrMsg); + } + parentForm.commPlcActive = false; + lgInfo("szStatusConnection: " + szStatusConnection); + connectionOk = true; + // refresh stato allarmi!!! + if (connectionOk) + { + dtAvvioAdp = DateTime.Now; + if (adpRunning) + { + lgInfo("Connessione OK"); + } + } + else + { + lgError("Impossibile procedere, connessione mancante..."); + } + } + catch (Exception exc) + { + lgFatal(string.Format("Errore nella connessione all'adapter OSAI: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc)); + connectionOk = false; + lgInfo(string.Format("Eccezione in TryConnect, Adapter NON running, pausa di {0} msec prima di ulteriori tentativi di riconnessione", utils.CRI("waitRecMSec"))); + } + } + else + { + // loggo no risposta ping ... + connectionOk = false; + if (needPing) + { + if (verboseLog || periodicLog) + { + lgInfo(string.Format("Attenzione: controllo PING fallito per IP {0} - {1}", cIobConf.cncIpAddr, reply.Status)); + } + } + } + } + } + // se non è ancora connesso faccio procesisng memoria caso disconnesso... + if (!connectionOk) + { + // processo semafori ed invio... + processMemoryDiscon(); + } } - } - catch (Exception exc) - { - lgError(exc, "Errore in getDynData"); - } - stopwatch.Stop(); - return outVal; + + /// + /// Override disconnessione + /// + public override void tryDisconnect() + { + if (connectionOk) + { + string szStatusConnection = ""; + try + { + OSAI_ref.CloseSession(); + connectionOk = false; + // resetto timing! + TimingData.resetData(); + lgInfo(szStatusConnection); + lgInfo("Effettuata disconnessione adapter OSAI!"); + } + catch (Exception exc) + { + lgFatal(exc, "Errore nella disconnessione dall'adapter OSAI"); + } + } + else + { + lgError("IMPOSSIBILE effettuare disconnessione: Connessione non disponibile..."); + } + } + + #endregion Public Methods } - /// - /// Recupero dati override (da area G che è già stata letta...) - /// - /// - public override Dictionary getOverrides() - { - Dictionary outVal = new Dictionary(); - outVal.Add("FEED_OVER", (oData.feed_ov).ToString()); - outVal.Add("RAPID_OVER", (oData.rapid_override).ToString()); - return outVal; - } - /// - /// Recupera e processa allarmi CNC... - /// - public override Dictionary getCncAlarms() - { - Dictionary outVal = new Dictionary(); - // se ho allarmi li accodo... - if (oData.last_nc_error != 0) - { - try - { - outVal.Add("CNC_ALARM", (oData.last_nc_error).ToString()); - } - catch (Exception exc) - { - lg.Error(exc, "Eccezione in getCncAlarms"); - } - } - return outVal; - } - } -} +} \ No newline at end of file diff --git a/IOB-WIN/IobOmron.cs b/IOB-WIN/IobOmron.cs index 11085307..ec7dfff2 100644 --- a/IOB-WIN/IobOmron.cs +++ b/IOB-WIN/IobOmron.cs @@ -8,149 +8,660 @@ using System.Threading; namespace IOB_WIN { - public class IobOmron : IobGeneric - { - - /// - /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO - /// - Dictionary signLUT = new Dictionary(); - /// - /// Oggetto MAIN x connessione OMRON - /// - protected OmronFinsTCP.Net.EtherNetPLC OMRON_ref; - /// - /// Array delle risposte dal controllo OMRON - /// - protected System.Collections.ArrayList resDataArray; - - /// - /// Array valori letti da memoria CIO INGRESSI - /// - protected short[] memReadCIO_IN; - /// - /// Array valori letti da memoria CIO USCITE - /// - protected short[] memReadCIO_OUT; - /// - /// Array valori letti da memoria DM - /// - protected short[] memReadDM; - /// - /// Array valori letti da memoria WR - /// - protected short[] memReadWR; - /// - /// Array valori SCRITTI su memoria CIO - /// - protected short[] memWriteCIO; - /// - /// Array valori SCRITTI su memoria DM - /// - protected short[] memWriteDM; - /// - /// Array valori SCRITTI su memoria WR - /// - protected short[] memWriteWR; - - /// - /// Calcola la conversione da byte --> num decimale --> HEX --> conversione come stringa in INT - /// - /// - /// - protected static int convDHD(short valore) + public class IobOmron : IobGeneric { - // legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) - // esempio 12540 --> diviso in 1 | 2540 --> in HEX diventa 1 | 9472, ma il 9472 va su byte[0] e 1 su byte[1] - int answ = 0; - string hexVal = valore.ToString("x"); - int.TryParse(hexVal, out answ); - return answ; - } - /// - /// Calcola la conversione da INTERO a intero HEX x OMRON - /// - /// - /// - protected static int convHD(string hexVal) - { - int answ = 0; - if (!string.IsNullOrEmpty(hexVal)) - { + #region Private Fields + + /// + /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO + /// + private Dictionary signLUT = new Dictionary(); + + #endregion Private Fields + + #region Protected Fields + + /// + /// Array valori letti da memoria CIO INGRESSI + /// + protected short[] memReadCIO_IN; + + /// + /// Array valori letti da memoria CIO USCITE + /// + protected short[] memReadCIO_OUT; + + /// + /// Array valori letti da memoria DM + /// + protected short[] memReadDM; + + /// + /// Array valori letti da memoria WR + /// + protected short[] memReadWR; + + /// + /// Array valori SCRITTI su memoria CIO + /// + protected short[] memWriteCIO; + + /// + /// Array valori SCRITTI su memoria DM + /// + protected short[] memWriteDM; + + /// + /// Array valori SCRITTI su memoria WR + /// + protected short[] memWriteWR; + + /// + /// Oggetto MAIN x connessione OMRON + /// + protected OmronFinsTCP.Net.EtherNetPLC OMRON_ref; + + /// + /// Array delle risposte dal controllo OMRON + /// + protected System.Collections.ArrayList resDataArray; + + #endregion Protected Fields + + #region Public Constructors + + /// + /// estende l'init della classe base... + /// + /// + /// + public IobOmron(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) + { + // gestione invio ritardato contapezzi + pzCountDelay = utils.CRI("pzCountDelay"); + lastPzCountSend = DateTime.Now; + lastWarnODL = DateTime.Now; + + // imposto i parametri PLC + setParamPlc(); + } + + #endregion Public Constructors + + #region Protected Properties + + /// + /// Lettura scrittura commessa da OMRON (come array di coppie di byte) + /// + protected string commessa + { + get + { + string answ = ""; + short[] response; + byte[] byteData = new byte[20]; + try + { + // leggo + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 10, out response); + // copio come byte... + Buffer.BlockCopy(response, 0, byteData, 0, response.Length); + answ = Encoding.ASCII.GetString(byteData); + } + catch + { } + return answ; + } + set + { + // converto in byte la mia stringa + byte[] valByte = Encoding.ASCII.GetBytes(value); + // limite 20 char... imposto a 20! + int maxChar = valByte.Length < 20 ? valByte.Length : 20; + // creao un array di 10 short MAX + short[] valoriWord = new short[10]; + // copio i valori + Buffer.BlockCopy(valByte, 0, valoriWord, 0, maxChar); + // scrivo su OMRON! + OMRON_ref.WriteWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 10, valoriWord); + } + } + + /// + /// Verifico se abbia ALMENO un errore... + /// + protected bool hasError + { + get + { + bool answ = false; + if (memReadCIO_OUT != null) + { + answ = ((memReadCIO_OUT[4] & (1 << 7)) != 0); + } +#if false + bool answ = false; + // controllo primi errori, parto dal primo e poi OR + answ = answ || ((memReadCIO[0] & (1 << 7)) == 1); + answ = answ || ((memReadCIO[1] & (1 << 0)) == 1); + answ = answ || ((memReadCIO[1] & (1 << 1)) == 1); + answ = answ || ((memReadCIO[1] & (1 << 3)) == 1); + answ = answ || (memReadCIO[2] > 0); + answ = answ || ((memReadCIO[3] & (1 << 0)) == 1); + answ = answ || ((memReadCIO[3] & (1 << 1)) == 1); +#endif + return answ; + } + } + + /// + /// Oggetto get/set per lettura (DM22-23) /scrittura (DM26-27) PESO RICHIESTO + /// + protected int pesoRichiesto + { + get + { + int answ = 0; + try + { + short[] valDM; + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 22, 2, out valDM); + answ = convDHD(valDM[0]) + 10000 * convDHD(valDM[1]); + } + catch + { } + return answ; + } + set + { + short[] valDM = intToShort(value); + OMRON_ref.WriteWords(OmronFinsTCP.Net.PlcMemory.DM, 26, 2, valDM); + // ora devo "comandare scrittura" su OMRON... + + // sollevo bit 65.0 x azzeramento + OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.CIO, 65, 1); + Thread.Sleep(500); + // ora sollevo bit e 65.1 x indicare nuovo valore... + OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.CIO, 65, 2); + // ora attendo ed abbasso tutti i bit + Thread.Sleep(500); + OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.CIO, 65, 0); + } + } + + /// + /// Oggetto per lettura PESO rilevato (DM20-21) + /// + protected int pesoRilevato + { + get + { + int answ = 0; + try + { + short[] valDM; + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 20, 2, out valDM); + // legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) + // esempio 12540 --> diviso in 1 | 2540 --> in HEX diventa 1 | 9472, ma il 9472 va su byte[0] e 1 su byte[1] + answ = convDHD(valDM[0]) + 10000 * convDHD(valDM[1]); + } + catch + { } + return answ; + } + } + + /// + /// Oggetto get/set x portata + /// + protected int portata + { + get + { + int answ = 0; + try + { + short valDM; + OMRON_ref.ReadWord(OmronFinsTCP.Net.PlcMemory.DM, 50, out valDM); + answ = convDHD(valDM); + } + catch + { } + return answ; + } + set + { + // scrivo portata su memoria DM50... + short portata = (short)convHD("0x" + value.ToString("0000")); + OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.DM, 50, portata); + } + } + + /// + /// Oggetto get/set x quantità richiesta LOTTO + /// + protected int quantitaLotto + { + get + { + int answ = 0; + try + { + short[] valDM; + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 52, 2, out valDM); + answ = convDHD(valDM[0]) + 10000 * convDHD(valDM[1]); + } + catch + { } + return answ; + } + set + { + short[] valDM = intToShort(value); + OMRON_ref.WriteWords(OmronFinsTCP.Net.PlcMemory.DM, 52, 2, valDM); + } + } + + #endregion Protected Properties + + #region Private Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + private void decodeToBaseBitmap() + { + // init a zero... + B_input = 0; + + /* ----------------------------------------------------- + * bitmap MAPO + * B0: POWER_ON + * B1: RUN + * B2: pzCount + * B3: allarme + * B4: manuale + * B5: carico SILOS + * B6: carico AUTOBOTTE + ----------------------------------------------------- */ + // bit 0 (poweron) imposto a 1 SE pingo... + B_input = testPingMachine == IPStatus.Success ? 1 : 0; + + bool caricoSilos = ((memReadCIO_IN[55] & (1 << 2)) != 0); + bool caricoAutobotte = ((memReadCIO_IN[50] & (1 << 2)) != 0); + // filtro DEVE ANDARE ma VIENE RILEVATO DOPO, POTREBEB andare da solo x scaricare... + bool runFiltro = ((memReadCIO_IN[0] & (1 << 1)) != 0); + + // RUN se CIO_bit 0.01 è RUN FILTRO... + if ((caricoAutobotte || caricoSilos)) + { + // SE HO carico silos OPPURE carico autobotte --> RUN + B_input += (1 << 1); + } + // ERROR generale (CORREGGERE!) + if (hasError) + { + B_input += (1 << 3); + } + + // carico SILOS + if (caricoSilos) + { + B_input += (1 << 5); + } + // carico AUTOBOTTE + if (caricoAutobotte) + { + B_input += (1 << 6); + } + + // procedo SOLO SE è enabled IOB + if (IobOnline) + { + try + { + currODL = utils.callUrl(urlGetCurrODL); + // solo SE HO un ODL... + if (string.IsNullOrEmpty(currODL) || currODL == "0") + { + if (periodicLog) + { + lgInfo(string.Format("OMRON | Lettura ODL andata a vuoto: currODL: {0}", currODL)); + } + } + else + { + // se variato o scaduto timeout log... + if (periodicLog || (currIdxODL.ToString() != currODL)) + { + lgInfo(string.Format("OMRON | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); + } + // 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; + } + } + } + else + { + // imposto currODL a vuoto! + currODL = ""; + if (periodicLog) + { + lgInfo($"Omron | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); + } + } + // log opzionale! + if (verboseLog) + { + lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); + } + } + + /// + /// Vera connessione ad OMRON + /// + /// + private short doConnect() + { + // avvio un oggetto di comunicazione OMRON + OMRON_ref = new OmronFinsTCP.Net.EtherNetPLC(); + short port = 9600; + short.TryParse(cIobConf.cncPort, out port); + lgInfo($"Chiamata apertura OMRON FINS: {cIobConf.cncIpAddr}:{port}"); + short esitoLink = OMRON_ref.Link(cIobConf.cncIpAddr, port, 500); + return esitoLink; + } + + /// + /// Test completo funzioni OMRON + /// + private void omronWriteTest() + { + commessa = "OMRON EDF TEST"; + + // scrivo portata + portata = 444; + + // scrivo pesatura richiesta + pesoRichiesto = 22222; + + // scrivo DM 52-53 del lotto richiesto + quantitaLotto = 66666; + } + + /// + /// Lettura e log valori x debug + /// + private void readAndLog() + { + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.CIO, 0, 8, out memReadCIO_IN); + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.CIO, 100, 8, out memReadCIO_OUT); + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 0, 8, out memReadDM); + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 8, out memReadWR); + + if (isVerboseLog) + { + lgInfo("Effettuata lettura dati CIO"); + foreach (var item in memReadCIO_IN) + { + lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); + } + lgInfo("Effettuata lettura dati DM"); + foreach (var item in memReadDM) + { + lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); + } + lgInfo("Effettuata lettura dati WR"); + foreach (var item in memReadWR) + { + lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); + } + } + short[] respDM20; + short[] respDM22; + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 20, 2, out respDM20); + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 22, 2, out respDM22); + if (isVerboseLog) + { + // legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) + lgInfo("Effettuata lettura dati respDM20"); + foreach (var item in respDM20) + { + lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); + } + lgInfo("Effettuata lettura dati respDM22"); + foreach (var item in respDM22) + { + lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); + } + } + } + + #endregion Private Methods + + #region Protected Methods + + /// + /// Calcola la conversione da byte --> num decimale --> HEX --> conversione come stringa in INT + /// + /// + /// + protected static int convDHD(short valore) + { + // legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) + // esempio 12540 --> diviso in 1 | 2540 --> in HEX diventa 1 | 9472, ma il 9472 va su byte[0] e 1 su byte[1] + int answ = 0; + string hexVal = valore.ToString("x"); + int.TryParse(hexVal, out answ); + return answ; + } + + /// + /// Converte un valore di 2 short in un unico numero accostato: + /// es: legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) + /// 12540 --> diviso in 1 | 2540 --> in HEX diventa 1 | 9472, ma il 9472 va su byte[0] e 1 su byte[1] + /// + /// + /// + protected static int convFromHex(short[] valori) + { + int answ = 0; + string fullVal = $"{convDHD(valori[1]).ToString("D4")}{convDHD(valori[0]).ToString("D4")}"; + int.TryParse(fullVal, out answ); + return answ; + } + + /// + /// Calcola la conversione da INTERO a intero HEX x OMRON + /// + /// + /// + protected static int convHD(string hexVal) + { + int answ = 0; + if (!string.IsNullOrEmpty(hexVal)) + { + try + { + if (!hexVal.StartsWith("0x")) + { + hexVal = "0x" + hexVal; + } + answ = Convert.ToInt32(hexVal, 16); + } + catch + { } + } + return answ; + } + + /// + /// Converte un valore INT in un array di due SHORT valido x scrivere su OMRON + /// + /// + /// + protected static short[] intToShort(int value) + { + short[] valDM = new short[2]; + short highVal = (short)(value / 10000); + short lowVal = (short)(value - highVal * 10000); + valDM[0] = (short)convHD("0x" + lowVal.ToString("0000")); + valDM[1] = (short)convHD("0x" + highVal.ToString("0000")); + return valDM; + } + + /// + /// OVerride metodo x scrittura parametri su PLC + /// + /// + protected override void plcWriteParams(List updatedPar) + { + int valInt = 0; + if (updatedPar != null) + { + // controllo i parametri... ne gestisco 4... + foreach (var item in updatedPar) + { + lgInfo($"Richiesti processing plcWriteParams per {item.name} | valore richiesto {item.reqValue} | valore attuale {item.value}"); + string readBackVal = ""; + switch (item.uid) + { + case "kgRich": + int.TryParse(item.value, out valInt); + pesoRichiesto = valInt; + readBackVal = pesoRichiesto.ToString(); + break; + + case "kgLotto": + int.TryParse(item.value, out valInt); + quantitaLotto = valInt; + readBackVal = quantitaLotto.ToString(); + break; + + case "portata": + int.TryParse(item.value, out valInt); + portata = valInt; + readBackVal = portata.ToString(); + break; + + case "setComm": + commessa = item.value; + readBackVal = commessa; + break; + + default: + break; + } + // SE non corrispondessero LOGGO ERRORE... + if (item.value != readBackVal) + { + lgError($"Errore in plcWriteParams: uid {item.uid} | Wrote {item.value} | ReadBack {readBackVal}"); + } + } + } + } + + #endregion Protected Methods + + #region Public Methods + + /// + /// Processo i task richiesti e li elimino dalla coda 1:1 + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + // uso metodo base x ora + return base.executeTasks(task2exe); + } + + /// + /// Recupero dati dinamici... + /// + public override Dictionary getDynData() + { + // valore non presente in vers default... se gestito fare override + Dictionary outVal = new Dictionary(); + outVal.Add("kgAct", pesoRilevato.ToString()); + outVal.Add("kgImp", pesoRichiesto.ToString()); + return outVal; + } + + /// + /// Effettua vero processing contapezzi + /// + public override void processContapezzi() + { + if (utils.CRB("enableContapezzi")) + { +#if false try { - if (!hexVal.StartsWith("0x")) + // hard coded... !!!FARE!!! rivedere megio conf + contapezziPLC = pzCounter; + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + if (cIobConf.optPar.Count > 0 && getOptPar("PZCOUNT_MODE") != "") { - hexVal = "0x" + hexVal; } - answ = Convert.ToInt32(hexVal, 16); } - catch - { } - } - return answ; - } - /// - /// Converte un valore INT in un array di due SHORT valido x scrivere su OMRON - /// - /// - /// - protected static short[] intToShort(int value) - { - short[] valDM = new short[2]; - short highVal = (short)(value / 10000); - short lowVal = (short)(value - highVal * 10000); - valDM[0] = (short)convHD("0x" + lowVal.ToString("0000")); - valDM[1] = (short)convHD("0x" + highVal.ToString("0000")); - return valDM; - } - /// - /// Converte un valore di 2 short in un unico numero accostato: - /// es: legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) - /// 12540 --> diviso in 1 | 2540 --> in HEX diventa 1 | 9472, ma il 9472 va su byte[0] e 1 su byte[1] - /// - /// - /// - protected static int convFromHex(short[] valori) - { - int answ = 0; - string fullVal = $"{convDHD(valori[1]).ToString("D4")}{convDHD(valori[0]).ToString("D4")}"; - int.TryParse(fullVal, out answ); - return answ; - } - /// - /// estende l'init della classe base... - /// - /// - /// - public IobOmron(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) - { - // gestione invio ritardato contapezzi - pzCountDelay = utils.CRI("pzCountDelay"); - lastPzCountSend = DateTime.Now; - lastWarnODL = DateTime.Now; + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi OMRON"); + } +#endif + } + } - // imposto i parametri PLC - setParamPlc(); - } - /// - /// Processo i task richiesti e li elimino dalla coda 1:1 - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - // uso metodo base x ora - return base.executeTasks(task2exe); - } - /// - /// Effettua reset del contapezzi, in questo caso il conteggio dei KG - /// - /// - public override bool resetcontapezziPLC() - { - bool answ = false; + /// + /// Effettua lettura semafori principale + /// Parametri da aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) + { + base.readSemafori(ref currDispData); + try + { + if (verboseLog) + { + lgInfo("inizio read semafori"); + } + + currDispData.semIn = Semaforo.SV; + + // effettuo TUTTE le letture + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.CIO, 0, 60, out memReadCIO_IN); + OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.CIO, 100, 10, out memReadCIO_OUT); + //OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 0, 8, out memReadDM); + //OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 8, out memReadWR); + + contapezziPLC = pesoRilevato; + // decodifica e gestione + decodeToBaseBitmap(); + reportRawInput(ref currDispData); + } + catch + { + currDispData.semIn = Semaforo.SR; + } + } + + /// + /// Effettua reset del contapezzi, in questo caso il conteggio dei KG + /// + /// + public override bool resetcontapezziPLC() + { + bool answ = false; #if false - // ...SE abilitato da conf IOB + // ...SE abilitato da conf IOB if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET") == "TRUE") { // scrivo valore 0 x il contapezzi @@ -168,19 +679,20 @@ namespace IOB_WIN else { lgError("Impossibile effettuare RESET contapezzi OMRON, mancanza parametro OPT:ENABLE_PZ_RESET"); - } + } #endif - return answ; - } - /// - /// Effettua IMPOSTAZIONE FORZATA del contapezzi, in questo caso il conteggio dei KG - /// - /// - public override bool setcontapezziPLC(int newPzCount) - { - bool answ = false; + return answ; + } + + /// + /// Effettua IMPOSTAZIONE FORZATA del contapezzi, in questo caso il conteggio dei KG + /// + /// + public override bool setcontapezziPLC(int newPzCount) + { + bool answ = false; #if false - // ...SE abilitato da conf IOB + // ...SE abilitato da conf IOB if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET") == "TRUE") { // scrivo valore 0 x il contapezzi @@ -198,566 +710,110 @@ namespace IOB_WIN else { lgError("Impossibile effettuare SET contapezzi OMRON, mancanza parametro OPT:ENABLE_PZ_RESET"); - } + } #endif - return answ; - } - /// - /// Vera connessione ad OMRON - /// - /// - private short doConnect() - { - // avvio un oggetto di comunicazione OMRON - OMRON_ref = new OmronFinsTCP.Net.EtherNetPLC(); - short port = 9600; - short.TryParse(cIobConf.cncPort, out port); - lgInfo($"Chiamata apertura OMRON FINS: {cIobConf.cncIpAddr}:{port}"); - short esitoLink = OMRON_ref.Link(cIobConf.cncIpAddr, port, 500); - return esitoLink; - } - /// - /// Override disconnessione - /// - public override void tryDisconnect() - { - if (connectionOk) - { - string szStatusConnection = ""; - try - { - OMRON_ref.Close(); - connectionOk = false; - lgInfo(szStatusConnection); - lgInfo("Effettuata disconnessione adapter OMRON!"); + return answ; } - catch (Exception exc) + + /// + /// Override connessione + /// + public override void tryConnect() { - lgFatal(exc, "Errore nella disconnessione dall'adapter OMRON"); - } - } - else - { - lgError("IMPOSSIBILE effettuare disconnessione OMRON: 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("OMRON: ConnKO - tryConnect"); - } - // in primis salvo data ping... - lastPING = DateTime.Now; - // se passa il ping faccio il resto... - if (testPingMachine == IPStatus.Success) - { - string szStatusConnection = ""; - try + if (!connectionOk) { - // ora provo connessione... - parentForm.commPlcActive = true; - short esitoLink = doConnect(); - lgInfo($"szStatusConnection OMRON, esitoLink: {esitoLink}"); - parentForm.commPlcActive = false; - // imposto i parametri... - setParamPlc(); - connectionOk = true; - // refresh stato connessione!!! - if (connectionOk) - { - if (adpRunning) + // controllo che il ping sia stato tentato almeno pingTestSec fa... + if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec")) { - lgInfo("Connessione OK"); + if (verboseLog || periodicLog) + { + lgInfo("OMRON: ConnKO - tryConnect"); + } + // in primis salvo data ping... + lastPING = DateTime.Now; + // se passa il ping faccio il resto... + if (testPingMachine == IPStatus.Success) + { + string szStatusConnection = ""; + try + { + // ora provo connessione... + parentForm.commPlcActive = true; + short esitoLink = doConnect(); + lgInfo($"szStatusConnection OMRON, esitoLink: {esitoLink}"); + parentForm.commPlcActive = false; + // imposto i parametri... + setParamPlc(); + connectionOk = true; + // refresh stato connessione!!! + if (connectionOk) + { + if (adpRunning) + { + lgInfo("Connessione OK"); + } + } + else + { + lgError("Impossibile procedere, connessione mancante..."); + } + } + catch (Exception exc) + { + lgFatal($"Errore nella connessione all'adapter OMRON: {szStatusConnection}{Environment.NewLine}{exc}"); + connectionOk = false; + lgInfo($"Eccezione in TryConnect, Adapter OMRON NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione"); + } + } + else + { + // loggo no risposta ping ... + connectionOk = false; + if (verboseLog || periodicLog) + { + lgInfo($"Attenzione: OMRON controllo PING fallito per IP {cIobConf.cncIpAddr}"); + } + } } - } - else - { - lgError("Impossibile procedere, connessione mancante..."); - } } - catch (Exception exc) + else { - lgFatal($"Errore nella connessione all'adapter OMRON: {szStatusConnection}{Environment.NewLine}{exc}"); - connectionOk = false; - lgInfo($"Eccezione in TryConnect, Adapter OMRON NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione"); + needRefresh = true; } - } - else - { - // loggo no risposta ping ... - connectionOk = false; - if (verboseLog || periodicLog) + // se non è ancora connesso faccio procesisng memoria caso disconnesso... + if (!connectionOk) { - lgInfo($"Attenzione: OMRON controllo PING fallito per IP {cIobConf.cncIpAddr}"); + // processo semafori ed invio... + processMemoryDiscon(); } - } } - } - else - { - needRefresh = true; - } - // 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 + { + OMRON_ref.Close(); + connectionOk = false; + lgInfo(szStatusConnection); + lgInfo("Effettuata disconnessione adapter OMRON!"); + } + catch (Exception exc) + { + lgFatal(exc, "Errore nella disconnessione dall'adapter OMRON"); + } + } + else + { + lgError("IMPOSSIBILE effettuare disconnessione OMRON: Connessione non disponibile..."); + } + } + + #endregion Public Methods } - - #region Metodi specifici (da verificare/completare in implementazione) - - /// - /// Oggetto per lettura PESO rilevato (DM20-21) - /// - protected int pesoRilevato - { - get - { - int answ = 0; - try - { - short[] valDM; - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 20, 2, out valDM); - // legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) - // esempio 12540 --> diviso in 1 | 2540 --> in HEX diventa 1 | 9472, ma il 9472 va su byte[0] e 1 su byte[1] - answ = convDHD(valDM[0]) + 10000 * convDHD(valDM[1]); - } - catch - { } - return answ; - } - } - /// - /// Oggetto get/set per lettura (DM22-23) /scrittura (DM26-27) PESO RICHIESTO - /// - protected int pesoRichiesto - { - get - { - int answ = 0; - try - { - short[] valDM; - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 22, 2, out valDM); - answ = convDHD(valDM[0]) + 10000 * convDHD(valDM[1]); - } - catch - { } - return answ; - } - set - { - short[] valDM = intToShort(value); - OMRON_ref.WriteWords(OmronFinsTCP.Net.PlcMemory.DM, 26, 2, valDM); - // ora devo "comandare scrittura" su OMRON... - - // sollevo bit 65.0 x azzeramento - OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.CIO, 65, 1); - Thread.Sleep(500); - // ora sollevo bit e 65.1 x indicare nuovo valore... - OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.CIO, 65, 2); - // ora attendo ed abbasso tutti i bit - Thread.Sleep(500); - OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.CIO, 65, 0); - } - } - /// - /// Oggetto get/set x quantità richiesta LOTTO - /// - protected int quantitaLotto - { - get - { - int answ = 0; - try - { - short[] valDM; - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 52, 2, out valDM); - answ = convDHD(valDM[0]) + 10000 * convDHD(valDM[1]); - } - catch - { } - return answ; - } - set - { - short[] valDM = intToShort(value); - OMRON_ref.WriteWords(OmronFinsTCP.Net.PlcMemory.DM, 52, 2, valDM); - } - } - /// - /// Oggetto get/set x portata - /// - protected int portata - { - get - { - int answ = 0; - try - { - short valDM; - OMRON_ref.ReadWord(OmronFinsTCP.Net.PlcMemory.DM, 50, out valDM); - answ = convDHD(valDM); - } - catch - { } - return answ; - } - set - { - // scrivo portata su memoria DM50... - short portata = (short)convHD("0x" + value.ToString("0000")); - OMRON_ref.WriteWord(OmronFinsTCP.Net.PlcMemory.DM, 50, portata); - } - } - /// - /// Lettura scrittura commessa da OMRON (come array di coppie di byte) - /// - protected string commessa - { - get - { - string answ = ""; - short[] response; - byte[] byteData = new byte[20]; - try - { - // leggo - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 10, out response); - // copio come byte... - Buffer.BlockCopy(response, 0, byteData, 0, response.Length); - answ = Encoding.ASCII.GetString(byteData); - } - catch - { } - return answ; - } - set - { - // converto in byte la mia stringa - byte[] valByte = Encoding.ASCII.GetBytes(value); - // limite 20 char... imposto a 20! - int maxChar = valByte.Length < 20 ? valByte.Length : 20; - // creao un array di 10 short MAX - short[] valoriWord = new short[10]; - // copio i valori - Buffer.BlockCopy(valByte, 0, valoriWord, 0, maxChar); - // scrivo su OMRON! - OMRON_ref.WriteWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 10, valoriWord); - } - } - /// - /// Effettua vero processing contapezzi - /// - public override void processContapezzi() - { - if (utils.CRB("enableContapezzi")) - { -#if false - try - { - // hard coded... !!!FARE!!! rivedere megio conf - contapezziPLC = pzCounter; - // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) - if (cIobConf.optPar.Count > 0 && getOptPar("PZCOUNT_MODE") != "") - { - } - } - catch (Exception exc) - { - lgError(exc, "Errore in contapezzi OMRON"); - } -#endif - } - } - - /// - /// Effettua lettura semafori principale - /// Parametri da aggiornare x display in form - /// - public override void readSemafori(ref newDisplayData currDispData) - { - base.readSemafori(ref currDispData); - try - { - if (verboseLog) - { - lgInfo("inizio read semafori"); - } - - currDispData.semIn = Semaforo.SV; - - - // effettuo TUTTE le letture - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.CIO, 0, 60, out memReadCIO_IN); - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.CIO, 100, 10, out memReadCIO_OUT); - //OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 0, 8, out memReadDM); - //OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 8, out memReadWR); - - - contapezziPLC = pesoRilevato; - // decodifica e gestione - decodeToBaseBitmap(); - reportRawInput(ref currDispData); - } - catch - { - currDispData.semIn = Semaforo.SR; - } - } - /// - /// Verifico se abbia ALMENO un errore... - /// - protected bool hasError - { - get - { - bool answ = false; - if (memReadCIO_OUT != null) - { - answ = ((memReadCIO_OUT[4] & (1 << 7)) != 0); - } -#if false - bool answ = false; - // controllo primi errori, parto dal primo e poi OR - answ = answ || ((memReadCIO[0] & (1 << 7)) == 1); - answ = answ || ((memReadCIO[1] & (1 << 0)) == 1); - answ = answ || ((memReadCIO[1] & (1 << 1)) == 1); - answ = answ || ((memReadCIO[1] & (1 << 3)) == 1); - answ = answ || (memReadCIO[2] > 0); - answ = answ || ((memReadCIO[3] & (1 << 0)) == 1); - answ = answ || ((memReadCIO[3] & (1 << 1)) == 1); -#endif - return answ; - } - } - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - private void decodeToBaseBitmap() - { - // init a zero... - B_input = 0; - - - /* ----------------------------------------------------- - * bitmap MAPO - * B0: POWER_ON - * B1: RUN - * B2: pzCount - * B3: allarme - * B4: manuale - * B5: carico SILOS - * B6: carico AUTOBOTTE - ----------------------------------------------------- */ - // bit 0 (poweron) imposto a 1 SE pingo... - B_input = testPingMachine == IPStatus.Success ? 1 : 0; - - bool caricoSilos = ((memReadCIO_IN[55] & (1 << 2)) != 0); - bool caricoAutobotte = ((memReadCIO_IN[50] & (1 << 2)) != 0); - // filtro DEVE ANDARE ma VIENE RILEVATO DOPO, POTREBEB andare da solo x scaricare... - bool runFiltro = ((memReadCIO_IN[0] & (1 << 1)) != 0); - - // RUN se CIO_bit 0.01 è RUN FILTRO... - if ((caricoAutobotte || caricoSilos)) - { - // SE HO carico silos OPPURE carico autobotte --> RUN - B_input += (1 << 1); - } - // ERROR generale (CORREGGERE!) - if (hasError) - { - B_input += (1 << 3); - } - - // carico SILOS - if (caricoSilos) - { - B_input += (1 << 5); - } - // carico AUTOBOTTE - if (caricoAutobotte) - { - B_input += (1 << 6); - } - - // process ODL e contapezzi - string currODL = ""; - try - { - currODL = utils.callUrl(urlGetCurrODL); - // solo SE HO un ODL... - if (string.IsNullOrEmpty(currODL) || currODL == "0") - { - if (periodicLog) - { - lgInfo(string.Format("OMRON | Lettura ODL andata a vuoto: currODL: {0}", currODL)); - } - } - else - { - // se variato o scaduto timeout log... - if (periodicLog || (currIdxODL.ToString() != currODL)) - { - lgInfo(string.Format("OMRON | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); - } - // 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; - } - } - // log opzionale! - if (verboseLog) - { - lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); - } - } - /// - /// Recupero dati dinamici... - /// - public override Dictionary getDynData() - { - // valore non presente in vers default... se gestito fare override - Dictionary outVal = new Dictionary(); - outVal.Add("kgAct", pesoRilevato.ToString()); - outVal.Add("kgImp", pesoRichiesto.ToString()); - return outVal; - } - /// - /// OVerride metodo x scrittura parametri su PLC - /// - /// - protected override void plcWriteParams(List updatedPar) - { - int valInt = 0; - if (updatedPar != null) - { - // controllo i parametri... ne gestisco 4... - foreach (var item in updatedPar) - { - lgInfo($"Richiesti processing plcWriteParams per {item.name} | valore richiesto {item.reqValue} | valore attuale {item.value}"); - string readBackVal = ""; - switch (item.uid) - { - case "kgRich": - int.TryParse(item.value, out valInt); - pesoRichiesto = valInt; - readBackVal = pesoRichiesto.ToString(); - break; - case "kgLotto": - int.TryParse(item.value, out valInt); - quantitaLotto = valInt; - readBackVal = quantitaLotto.ToString(); - break; - case "portata": - int.TryParse(item.value, out valInt); - portata = valInt; - readBackVal = portata.ToString(); - break; - case "setComm": - commessa = item.value; - readBackVal = commessa; - break; - default: - break; - } - // SE non corrispondessero LOGGO ERRORE... - if (item.value != readBackVal) - { - lgError($"Errore in plcWriteParams: uid {item.uid} | Wrote {item.value} | ReadBack {readBackVal}"); - } - } - } - } - - - #endregion - - #region metodi testing *non usati( - - /// - /// Test completo funzioni OMRON - /// - private void omronWriteTest() - { - - commessa = "OMRON EDF TEST"; - - // scrivo portata - portata = 444; - - // scrivo pesatura richiesta - pesoRichiesto = 22222; - - // scrivo DM 52-53 del lotto richiesto - quantitaLotto = 66666; - - } - /// - /// Lettura e log valori x debug - /// - private void readAndLog() - { - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.CIO, 0, 8, out memReadCIO_IN); - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.CIO, 100, 8, out memReadCIO_OUT); - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 0, 8, out memReadDM); - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.WR, 0, 8, out memReadWR); - - if (isVerboseLog) - { - lgInfo("Effettuata lettura dati CIO"); - foreach (var item in memReadCIO_IN) - { - lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); - } - lgInfo("Effettuata lettura dati DM"); - foreach (var item in memReadDM) - { - lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); - } - lgInfo("Effettuata lettura dati WR"); - foreach (var item in memReadWR) - { - lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); - } - } - short[] respDM20; - short[] respDM22; - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 20, 2, out respDM20); - OMRON_ref.ReadWords(OmronFinsTCP.Net.PlcMemory.DM, 22, 2, out respDM22); - if (isVerboseLog) - { - // legge delle coppie di valori INT, vanno trasformati in HEX e POI accodati, dove il primo è x 1 e il secondo x 10000 (in pratica va in testa) - lgInfo("Effettuata lettura dati respDM20"); - foreach (var item in respDM20) - { - lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); - } - lgInfo("Effettuata lettura dati respDM22"); - foreach (var item in respDM22) - { - lgInfo($"Valori: {item} --> {baseUtils.binaryForm(item)}"); - } - } - } - - #endregion - } -} +} \ No newline at end of file diff --git a/IOB-WIN/IobSiemensFape.cs b/IOB-WIN/IobSiemensFape.cs index 95d6f534..0f918023 100644 --- a/IOB-WIN/IobSiemensFape.cs +++ b/IOB-WIN/IobSiemensFape.cs @@ -4,264 +4,289 @@ using System.Linq; namespace IOB_WIN { - - public class IobSiemensFape : IobSiemens - { - /* -------------------------------------------------------------------------------- - * Controlli SIEMENS FAPE (es punzonatrice Tecnomeccanica di LVF) - * - basasto su SIEMENS - * - S7 vers 1200 - * - abilitata 1 area in lettura DB15 ed 1 in scrittura DB16 (NON la usano) - * - x poter funzionare --> protezione: meccanismi di collegamento / consenti put/get - * - lettura/scrittura primi 48 byte (240 max x le due DB) - * - * LETTURA seguenti byte: - * - B0, WORD, Stato Macchina Generale - * - B2, WORD, Posizione sequenza contatore - * - B4, WORD, contatore cicli eseguiti per lubrifica - * - B40, DWORD, contapezzi azzerabile da operatore - * - B44, DWORD, contapezzi ASSOLUTO - * - * -------------------------------------------------------------------------------- */ - - - #region area principale adapter - - /// - /// Enum degli stati macchina (B0) - /// - public enum statoMacchina + public class IobSiemensFape : IobSiemens { - COMUNICAZIONE_ASSENTE = 0, - EMERGENZA_INSERITA = 1, - AVARIA_ARIA = 2, - AVARIA_PRESSIONE_OLIO = 3, - AVARIA_LIVELLO_OLIO = 4, - AVARIA_TEMPERATURA_OLIO = 5, - AVARIA_MOTORE_POMPA_IDRAULICA = 6, - AVARIA_MOTORE_RAFFREDDO_IDRAULICA = 7, - AVARIA_SINCRONISMO_PORTE = 8, - AVARIA_LIBERA = 9, - ATTIVAZIONE_IN_CORSO = 10, - MODO_MANUALE_ATTREZZAGGIO = 11, - MODO_AUTOMATICO_LOCALE = 12, - MODO_AUTOMATICO_ROBOT = 13, - CICLO_IN_CORSO = 14, - LIBERO = 15 - } - /// - /// Posizione sequenza ciclo standard punzonatrice - /// - public enum posizioneSequenza - { - CICLO_AUTOMATICO_FERMO = 0, - CONTROLLO_MODO_OPERATIVO = 5, - MODO_ATTIVO_CON_ROBOT = 8, - SBLOCCAGGIO_PEZZO = 10, - APERTURA_PORTELLO_ROBOT = 11, - CONSENSO_ACCESSO_AL_ROBOT = 12, - CARICO_ROBOT_IN_CORSO = 14, - CARICO_ROBOT_CONCLUSO = 16, - CHIUSURA_PORTELLO_ROBOT = 18, - VERIFICA_POSIZIONE_CARRI = 20, - BLOCCAGGIO_PEZZO = 22, - ATTESA_CARRO_A_DESTRA = 24, - DISCESA_RAPIDO_BROCCIATURA = 25, - CICLO_DI_BROCCIATURA = 26, - RITORNO_BROCCIATRICE = 28, - COMANDO_CARRO_A_SINISTRA = 30, - CICLO_DI_ALESATURA = 32, - RITORNO_CARRO_ALESATURA = 34, - COMANDO_CARRO_A_DESTRA = 36, - INCREMENTO_CONTAPEZZI = 38, - CONTROLLO_TIME_OUT_CICLO = 40, - RILANCIO_CICLO_F42 = 42, - ATTESA_FINE_CICLO = 45 - } + /* -------------------------------------------------------------------------------- + * Controlli SIEMENS FAPE (es punzonatrice Tecnomeccanica di LVF) + * - basasto su SIEMENS + * - S7 vers 1200 + * - abilitata 1 area in lettura DB15 ed 1 in scrittura DB16 (NON la usano) + * - x poter funzionare --> protezione: meccanismi di collegamento / consenti put/get + * - lettura/scrittura primi 48 byte (240 max x le due DB) + * + * LETTURA seguenti byte: + * - B0, WORD, Stato Macchina Generale + * - B2, WORD, Posizione sequenza contatore + * - B4, WORD, contatore cicli eseguiti per lubrifica + * - B40, DWORD, contapezzi azzerabile da operatore + * - B44, DWORD, contapezzi ASSOLUTO + * + * -------------------------------------------------------------------------------- */ - /// - /// Classe base con i metodi x Siemens - /// - /// - /// - public IobSiemensFape(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) - { - // dovebbe fare init della classe base, VERIFICARE... - lgInfo("NEW IOB SIEMENS versione FAPE"); - } + #region Public Constructors - #endregion - - #region Metodi specifici (da verificare/completare in implementazione) - - /// - /// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid) - /// - public override void processOverride() - { - } - - /// - /// Recupero dati override in formato dictionary - /// - /// - public override Dictionary getDynData() - { - Dictionary outVal = new Dictionary(); - ushort valStatus = S7.Net.Types.Word.FromByteArray(RawInput.Skip(0).Take(2).ToArray()); - ushort valPosit = S7.Net.Types.Word.FromByteArray(RawInput.Skip(2).Take(2).ToArray()); - outVal.Add("CURR_STATO", ((statoMacchina)valStatus).ToString()); - outVal.Add("CURR_POSIT", ((posizioneSequenza)valPosit).ToString()); - return outVal; - } - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - protected override void decodeToBaseBitmap() - { - // init a zero... - B_input = 0; - // FAPE: leggo i primi 2 WORD x decodifica stato e posizione... - ushort valStatus = S7.Net.Types.Word.FromByteArray(RawInput.Skip(0).Take(2).ToArray()); - ushort valPosit = S7.Net.Types.Word.FromByteArray(RawInput.Skip(2).Take(2).ToArray()); - statoMacchina _stMacch = ((statoMacchina)valStatus); - posizioneSequenza _posSeq = ((posizioneSequenza)valPosit); - - /* ----------------------------------------------------- - * bitmap MAPO - * B0: POWER_ON - * B1: RUN - * B2: pzCount - * B3: allarme - * B4: manuale - * B5: emergenza - ----------------------------------------------------- */ - - // bit 0 (poweron) imposto a 1 SE connected... - B_input = currPLC.IsConnected ? 1 : 0; - // controllo stato macchina x impostare altri bit... - switch (_stMacch) - { - case statoMacchina.EMERGENZA_INSERITA: - B_input += (1 << 5); - break; - case statoMacchina.AVARIA_ARIA: - case statoMacchina.AVARIA_PRESSIONE_OLIO: - case statoMacchina.AVARIA_LIVELLO_OLIO: - case statoMacchina.AVARIA_TEMPERATURA_OLIO: - B_input += (1 << 3); - B_input += (1 << 6); - break; - case statoMacchina.AVARIA_MOTORE_POMPA_IDRAULICA: - case statoMacchina.AVARIA_MOTORE_RAFFREDDO_IDRAULICA: - case statoMacchina.COMUNICAZIONE_ASSENTE: - case statoMacchina.AVARIA_SINCRONISMO_PORTE: - case statoMacchina.AVARIA_LIBERA: - case statoMacchina.ATTIVAZIONE_IN_CORSO: - B_input += (1 << 3); - break; - case statoMacchina.MODO_MANUALE_ATTREZZAGGIO: - B_input += (1 << 4); - break; - case statoMacchina.CICLO_IN_CORSO: - B_input += (1 << 1); - break; - case statoMacchina.MODO_AUTOMATICO_LOCALE: - case statoMacchina.MODO_AUTOMATICO_ROBOT: - B_input += (1 << 7); - break; - case statoMacchina.LIBERO: - default: - break; - } - - string currODL = ""; - try - { - currODL = utils.callUrl(urlGetCurrODL); - // solo SE HO un ODL... - if (string.IsNullOrWhiteSpace(currODL) || currODL == "0") + /// + /// Classe base con i metodi x Siemens + /// + /// + /// + public IobSiemensFape(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { - if (periodicLog) - { - lgInfo(string.Format("SiemensFape | Lettura ODL andata a vuoto: currODL: {0}", currODL)); - } + // dovebbe fare init della classe base, VERIFICARE... + lgInfo("NEW IOB SIEMENS versione FAPE"); } - else - { - // se variato o scaduto timeout log... - if (periodicLog || (currIdxODL.ToString() != currODL)) - { - lgInfo(string.Format("SiemensFape | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); - } - // 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 (!string.IsNullOrWhiteSpace(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)) - { - // se sono differenti MOSTRO... - if (contapezziPLC != contapezziIOB) - { - // registro contapezzi - lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - } - // verifico se variato contapezzi... e se passato ritardo minimo... - if (contapezziPLC > contapezziIOB) - { - // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio - contapezziIOB++; - needRefreshPzCount = true; - // salvo in semaforo! - B_input += (1 << 2); - // registro contapezzi - lgInfo($"contapezziPLC SIEMENS: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - } - // invio a server contapezzi (aggiornato) - string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); - // verifica se tutto OK - if (retVal != contapezziIOB.ToString()) - { - // errore salvataggio contapezzi - lgInfo($"Errore salvataggio Contapezzi SIEMENS: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); - // rileggo il counter pezzi da server - pzCntReload(true); - } - // resetto timer... - lastPzCountSend = DateTime.Now; - } - } - else - { - if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) - { - lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC SIEMENS {contapezziPLC} | contapezziIOB {contapezziIOB}"); - // resetto timer... - lastPzCountSend = DateTime.Now; - } - } + #endregion Public Constructors - // log opzionale! - if (verboseLog) - { - lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); - } + #region Public Enums + + /// + /// Posizione sequenza ciclo standard punzonatrice + /// + public enum posizioneSequenza + { + CICLO_AUTOMATICO_FERMO = 0, + CONTROLLO_MODO_OPERATIVO = 5, + MODO_ATTIVO_CON_ROBOT = 8, + SBLOCCAGGIO_PEZZO = 10, + APERTURA_PORTELLO_ROBOT = 11, + CONSENSO_ACCESSO_AL_ROBOT = 12, + CARICO_ROBOT_IN_CORSO = 14, + CARICO_ROBOT_CONCLUSO = 16, + CHIUSURA_PORTELLO_ROBOT = 18, + VERIFICA_POSIZIONE_CARRI = 20, + BLOCCAGGIO_PEZZO = 22, + ATTESA_CARRO_A_DESTRA = 24, + DISCESA_RAPIDO_BROCCIATURA = 25, + CICLO_DI_BROCCIATURA = 26, + RITORNO_BROCCIATRICE = 28, + COMANDO_CARRO_A_SINISTRA = 30, + CICLO_DI_ALESATURA = 32, + RITORNO_CARRO_ALESATURA = 34, + COMANDO_CARRO_A_DESTRA = 36, + INCREMENTO_CONTAPEZZI = 38, + CONTROLLO_TIME_OUT_CICLO = 40, + RILANCIO_CICLO_F42 = 42, + ATTESA_FINE_CICLO = 45 + } + + /// + /// Enum degli stati macchina (B0) + /// + public enum statoMacchina + { + COMUNICAZIONE_ASSENTE = 0, + EMERGENZA_INSERITA = 1, + AVARIA_ARIA = 2, + AVARIA_PRESSIONE_OLIO = 3, + AVARIA_LIVELLO_OLIO = 4, + AVARIA_TEMPERATURA_OLIO = 5, + AVARIA_MOTORE_POMPA_IDRAULICA = 6, + AVARIA_MOTORE_RAFFREDDO_IDRAULICA = 7, + AVARIA_SINCRONISMO_PORTE = 8, + AVARIA_LIBERA = 9, + ATTIVAZIONE_IN_CORSO = 10, + MODO_MANUALE_ATTREZZAGGIO = 11, + MODO_AUTOMATICO_LOCALE = 12, + MODO_AUTOMATICO_ROBOT = 13, + CICLO_IN_CORSO = 14, + LIBERO = 15 + } + + #endregion Public Enums + + #region Protected Methods + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + protected override void decodeToBaseBitmap() + { + // init a zero... + B_input = 0; + // FAPE: leggo i primi 2 WORD x decodifica stato e posizione... + ushort valStatus = S7.Net.Types.Word.FromByteArray(RawInput.Skip(0).Take(2).ToArray()); + ushort valPosit = S7.Net.Types.Word.FromByteArray(RawInput.Skip(2).Take(2).ToArray()); + statoMacchina _stMacch = ((statoMacchina)valStatus); + posizioneSequenza _posSeq = ((posizioneSequenza)valPosit); + + /* ----------------------------------------------------- + * bitmap MAPO + * B0: POWER_ON + * B1: RUN + * B2: pzCount + * B3: allarme + * B4: manuale + * B5: emergenza + ----------------------------------------------------- */ + + // bit 0 (poweron) imposto a 1 SE connected... + B_input = currPLC.IsConnected ? 1 : 0; + // controllo stato macchina x impostare altri bit... + switch (_stMacch) + { + case statoMacchina.EMERGENZA_INSERITA: + B_input += (1 << 5); + break; + + case statoMacchina.AVARIA_ARIA: + case statoMacchina.AVARIA_PRESSIONE_OLIO: + case statoMacchina.AVARIA_LIVELLO_OLIO: + case statoMacchina.AVARIA_TEMPERATURA_OLIO: + B_input += (1 << 3); + B_input += (1 << 6); + break; + + case statoMacchina.AVARIA_MOTORE_POMPA_IDRAULICA: + case statoMacchina.AVARIA_MOTORE_RAFFREDDO_IDRAULICA: + case statoMacchina.COMUNICAZIONE_ASSENTE: + case statoMacchina.AVARIA_SINCRONISMO_PORTE: + case statoMacchina.AVARIA_LIBERA: + case statoMacchina.ATTIVAZIONE_IN_CORSO: + B_input += (1 << 3); + break; + + case statoMacchina.MODO_MANUALE_ATTREZZAGGIO: + B_input += (1 << 4); + break; + + case statoMacchina.CICLO_IN_CORSO: + B_input += (1 << 1); + break; + + case statoMacchina.MODO_AUTOMATICO_LOCALE: + case statoMacchina.MODO_AUTOMATICO_ROBOT: + B_input += (1 << 7); + break; + + case statoMacchina.LIBERO: + default: + break; + } + + // procedo SOLO SE è enabled IOB + if (IobOnline) + { + try + { + currODL = utils.callUrl(urlGetCurrODL); + // solo SE HO un ODL... + if (string.IsNullOrWhiteSpace(currODL) || currODL == "0") + { + if (periodicLog) + { + lgInfo(string.Format("SiemensFape | Lettura ODL andata a vuoto: currODL: {0}", currODL)); + } + } + else + { + // se variato o scaduto timeout log... + if (periodicLog || (currIdxODL.ToString() != currODL)) + { + lgInfo(string.Format("SiemensFape | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL)); + } + // 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; + } + } + } + else + { + // imposto currODL a vuoto! + currODL = ""; + if (periodicLog) + { + lgInfo($"Fanuc | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); + } + } + if (!string.IsNullOrWhiteSpace(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)) + { + // se sono differenti MOSTRO... + if (contapezziPLC != contapezziIOB) + { + // registro contapezzi + lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + } + // verifico se variato contapezzi... e se passato ritardo minimo... + if (contapezziPLC > contapezziIOB) + { + // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio + contapezziIOB++; + needRefreshPzCount = true; + // salvo in semaforo! + B_input += (1 << 2); + // registro contapezzi + lgInfo($"contapezziPLC SIEMENS: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + } + + // invio a server contapezzi (aggiornato) + string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString()); + // verifica se tutto OK + if (retVal != contapezziIOB.ToString()) + { + // errore salvataggio contapezzi + lgInfo($"Errore salvataggio Contapezzi SIEMENS: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); + // rileggo il counter pezzi da server + pzCntReload(true); + } + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + else + { + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC SIEMENS {contapezziPLC} | contapezziIOB {contapezziIOB}"); + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + + // log opzionale! + if (verboseLog) + { + lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); + } + } + + #endregion Protected Methods + + #region Public Methods + + /// + /// Recupero dati override in formato dictionary + /// + /// + public override Dictionary getDynData() + { + Dictionary outVal = new Dictionary(); + ushort valStatus = S7.Net.Types.Word.FromByteArray(RawInput.Skip(0).Take(2).ToArray()); + ushort valPosit = S7.Net.Types.Word.FromByteArray(RawInput.Skip(2).Take(2).ToArray()); + outVal.Add("CURR_STATO", ((statoMacchina)valStatus).ToString()); + outVal.Add("CURR_POSIT", ((posizioneSequenza)valPosit).ToString()); + return outVal; + } + + /// + /// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid) + /// + public override void processOverride() + { + } + + #endregion Public Methods } - - #endregion - } -} +} \ No newline at end of file diff --git a/IOB-WIN/IobSiemensTorri.cs b/IOB-WIN/IobSiemensTorri.cs index 25a6e15d..fadd5832 100644 --- a/IOB-WIN/IobSiemensTorri.cs +++ b/IOB-WIN/IobSiemensTorri.cs @@ -8,15 +8,16 @@ namespace IOB_WIN { public class IobSiemensTorri : IobSiemens { - /* -------------------------------------------------------------------------------- + /* -------------------------------------------------------------------------------- * Controlli SIEMENS TORRI * - basasto su SIEMENS * - S7 vers 1200 - * + * * mod: 2019.01.19: aggiunta gestione segnale test/accensione/spegnimento (DB700.B1.4) --> mod StateMachine! * mod: 2019.04.06: aggiunta indicazione (IOB--> PLC) di stato setup su DB701.B0.4 * -------------------------------------------------------------------------------- */ + #region Public Constructors /// /// estende l'init della classe base con i metodi x Siemens specifici x Torri @@ -28,6 +29,183 @@ namespace IOB_WIN // dovebbe fare init della classe base, VERIFICARE... lgInfo("NEW IOB SIEMENS versione TORRI"); } + + #endregion Public Constructors + + #region Protected Methods + + /// + /// Decodifica il resto dell'area TORRI x i dati accessori (allarmi, ...) + /// + protected override void decodeOtherData() + { + if (verboseLog) + { + } + } + + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + protected override void decodeToBaseBitmap() + { + // init a zero... + B_input = 0; + // TORRI: leggo i primi 8 bit hard coded... + int byteSem = RawInput[0]; + + // azzero powerOn... + byteSem &= ~(1 << 0); + // bit 0 (powerOn) imposto a 1 SE connected... + if (currPLC.IsConnected) + { + byteSem += (1 << 0); + } + + // azzero i bit NON gestiti (2-5-6-7) + byteSem &= ~(1 << 2); + byteSem &= ~(1 << 5); + byteSem &= ~(1 << 6); + byteSem &= ~(1 << 7); + // leggo bit DB700.B1.4 e lo porto al bit 5 --> ciclo test/accensione/spegnimento + if ((RawInput[1] & (1 << 4)) != 0) //se RawInput[1] & 16-- > 5° bit-- > TEST + { + byteSem += (1 << 5); + } + // salvo infine variabile bit x invio + B_input = byteSem; + + // procedo SOLO SE è enabled IOB + if (IobOnline) + { + try + { + currODL = utils.callUrl(urlGetCurrODL); + // solo SE HO un ODL... + if (string.IsNullOrEmpty(currODL) || currODL == "0") + { + if (periodicLog) + { + lgInfo($"SiemensTorri | Lettura ODL andata a vuoto: currODL: {currODL}"); + } + } + else + { + // se variato o scaduto timeout log... + if (periodicLog || (currIdxODL.ToString() != currODL)) + { + lgInfo($"SiemensTorri | Lettura ODL, currODL: {currODL} --> currIdxODL prec: {currIdxODL}"); + } + // 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: {urlGetCurrODL}"); + lastWarnODL = DateTime.Now; + } + } + } + else + { + // imposto currODL a vuoto! + currODL = ""; + if (periodicLog) + { + lgInfo($"Fanuc | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto"); + } + } + if (!string.IsNullOrEmpty(currODL) && currODL != "0") + { + // ora processo il contapezzi... + string retVal = ""; + // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + // Salvo il contapezzi della macchina + retVal = utils.callUrlNow(urlSetPzCountMAC + contapezziPLC.ToString()); + // verifica se tutto OK, ovvero conferma i pezzi inviati + if (retVal != contapezziPLC.ToString()) + { + // errore salvataggio contapezzi + lgInfo($"Errore salvataggio Contapezzi PLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB {contapezziIOB} | Valore tornato: {retVal}"); + // rileggo il counter pezzi da server + pzCntReload(true); + } + + // se sono differenti MOSTRO... + if (contapezziPLC != contapezziIOB) + { + // registro contapezzi + lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); + } + if ((contapezziPLC > contapezziIOB)) + { + // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio + contapezziIOB++; + needRefreshPzCount = true; + // salvo in semaforo! + B_input += 1 << 2; + // registro contapezzi + lgInfo($"contapezziPLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); + } + + // Salvo il contapezzi della macchina + retVal = utils.callUrlNow(urlSetPzCount + contapezziIOB.ToString()); + // verifica se tutto OK, ovvero conferma i pezzi inviati + if (retVal != contapezziIOB.ToString()) + { + // errore salvataggio contapezzi + lgInfo($"Errore salvataggio contapezziPLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB {contapezziIOB} | Valore tornato: {retVal}"); + // rileggo il counter pezzi da server + pzCntReload(true); + } + + // verifico se variato contapezzi... e se passato ritardo minimo... + if ((contapezziPLC - contapezziIOB) > minSendPzCountBlock) + { + trySendPzCountBlock(); + } + + // invio a server contapezzi (aggiornato) + retVal = utils.callUrlNow(urlSetPzCount + contapezziIOB.ToString()); + // verifica se tutto OK + if (retVal != contapezziIOB.ToString()) + { + // errore salvataggio contapezzi + lgInfo($"Errore salvataggio Contapezzi SIEMENS-TORRI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); + // rileggo il counter pezzi da server + pzCntReload(true); + } + + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + else + { + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + + // log opzionale! + if (verboseLog) + { + lgInfo("Trasformazione B_input: {B_input}"); + } + } + + #endregion Protected Methods + + #region Public Methods + /// /// Processo i task richiesti e li elimino dalla coda 1:1 /// @@ -63,19 +241,23 @@ namespace IOB_WIN taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); break; + case taskType.fixStopSetup: taskVal = "VALUE DB701.0.4 --> 0"; lgInfo($"Chiamata fixStopSetup: taskOk: {taskOk} | taskVal: {taskVal}"); break; + case taskType.startSetup: MemBlock[0] += (1 << 4); taskVal = "VALUE DB701.0.4 --> 1"; lgInfo($"Chiamata startSetup: taskOk: {taskOk} | taskVal: {taskVal}"); break; + case taskType.stopSetup: taskVal = "VALUE DB701.0.4 --> 0"; lgInfo($"Chiamata stopSetup: taskOk: {taskOk} | taskVal: {taskVal}"); break; + default: taskVal = "SKIPPED | NO EXEC"; lgInfo($"Chiamata default senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); @@ -89,269 +271,24 @@ namespace IOB_WIN return taskDone; } - #region da verificare - /// - /// Recupero dati override in formato dictionary + /// Recupera ULTIMO allarme... /// /// - 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; - } - - /// - /// Decodifica il resto dell'area TORRI x i dati accessori (allarmi, ...) - /// - protected override void decodeOtherData() - { - if (verboseLog) - { - - } - } - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - protected override void decodeToBaseBitmap() - { - // init a zero... - B_input = 0; - // TORRI: leggo i primi 8 bit hard coded... - int byteSem = RawInput[0]; - - // azzero powerOn... - byteSem &= ~(1 << 0); - // bit 0 (powerOn) imposto a 1 SE connected... - if (currPLC.IsConnected) - { - byteSem += (1 << 0); - } - - // azzero i bit NON gestiti (2-5-6-7) - byteSem &= ~(1 << 2); - byteSem &= ~(1 << 5); - byteSem &= ~(1 << 6); - byteSem &= ~(1 << 7); - // leggo bit DB700.B1.4 e lo porto al bit 5 --> ciclo test/accensione/spegnimento - if ((RawInput[1] & (1 << 4)) != 0) //se RawInput[1] & 16-- > 5° bit-- > TEST - { - byteSem += (1 << 5); - } - // salvo infine variabile bit x invio - B_input = byteSem; - - - string currODL = ""; - try - { - currODL = utils.callUrl(urlGetCurrODL); - // solo SE HO un ODL... - if (string.IsNullOrEmpty(currODL) || currODL == "0") - { - if (periodicLog) - { - lgInfo($"SiemensTorri | Lettura ODL andata a vuoto: currODL: {currODL}"); - } - } - else - { - // se variato o scaduto timeout log... - if (periodicLog || (currIdxODL.ToString() != currODL)) - { - lgInfo($"SiemensTorri | Lettura ODL, currODL: {currODL} --> currIdxODL prec: {currIdxODL}"); - } - // 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: {urlGetCurrODL}"); - lastWarnODL = DateTime.Now; - } - } - if (!string.IsNullOrEmpty(currODL) && currODL != "0") - { - // ora processo il contapezzi... - string retVal = ""; - // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture - if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) - { - // Salvo il contapezzi della macchina - retVal = utils.callUrlNow(urlSetPzCountMAC + contapezziPLC.ToString()); - // verifica se tutto OK, ovvero conferma i pezzi inviati - if (retVal != contapezziPLC.ToString()) - { - // errore salvataggio contapezzi - lgInfo($"Errore salvataggio Contapezzi PLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB {contapezziIOB} | Valore tornato: {retVal}"); - // rileggo il counter pezzi da server - pzCntReload(true); - } - - // se sono differenti MOSTRO... - if (contapezziPLC != contapezziIOB) - { - // registro contapezzi - lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); - } - if ((contapezziPLC > contapezziIOB)) - { - // salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio - contapezziIOB++; - needRefreshPzCount = true; - // salvo in semaforo! - B_input += 1 << 2; - // registro contapezzi - lgInfo($"contapezziPLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB {contapezziIOB}"); - } - - // Salvo il contapezzi della macchina - retVal = utils.callUrlNow(urlSetPzCount + contapezziIOB.ToString()); - // verifica se tutto OK, ovvero conferma i pezzi inviati - if (retVal != contapezziIOB.ToString()) - { - // errore salvataggio contapezzi - lgInfo($"Errore salvataggio contapezziPLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB {contapezziIOB} | Valore tornato: {retVal}"); - // rileggo il counter pezzi da server - pzCntReload(true); - } - - // verifico se variato contapezzi... e se passato ritardo minimo... - if ((contapezziPLC - contapezziIOB) > minSendPzCountBlock) - { - trySendPzCountBlock(); - } - - // invio a server contapezzi (aggiornato) - retVal = utils.callUrlNow(urlSetPzCount + contapezziIOB.ToString()); - // verifica se tutto OK - if (retVal != contapezziIOB.ToString()) - { - // errore salvataggio contapezzi - lgInfo($"Errore salvataggio Contapezzi SIEMENS-TORRI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}"); - // rileggo il counter pezzi da server - pzCntReload(true); - } - - // resetto timer... - lastPzCountSend = DateTime.Now; - } - } - else - { - if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) - { - lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC SIEMENST-TORRI: {contapezziPLC} | contapezziIOB: {contapezziIOB}"); - // resetto timer... - lastPzCountSend = DateTime.Now; - } - } - - // log opzionale! - if (verboseLog) - { - lgInfo("Trasformazione B_input: {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() + public override Dictionary getCncAlarms() { Dictionary outVal = new Dictionary(); try { - outVal.Add("CPU", currPLC.CPU.ToString()); - outVal.Add("MAX_PDU", currPLC.MaxPDUSize.ToString()); - outVal.Add("RACK", currPLC.Rack.ToString()); - outVal.Add("SLOT", currPLC.Slot.ToString()); + string almMsg = string.Format("{0} | {1}", currPLC.LastErrorCode.ToString(), currPLC.LastErrorString); + outVal.Add("CNC_ALARM", almMsg); } catch (Exception exc) { - lgError(exc, "Errore in getSysInfo"); + lgError(exc, "Errore in getCncAlarms"); } 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 - } - } /// /// Recupero dati dinamici... @@ -393,29 +330,115 @@ namespace IOB_WIN catch (Exception exc) { lgError(exc, "Errore in getDynData"); - } + } #endif return outVal; } + /// - /// Recupera ULTIMO allarme... + /// Recupero dati override in formato dictionary /// /// - public override Dictionary getCncAlarms() + 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; + } + + /// + /// 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(); try { - string almMsg = string.Format("{0} | {1}", currPLC.LastErrorCode.ToString(), currPLC.LastErrorString); - outVal.Add("CNC_ALARM", almMsg); + outVal.Add("CPU", currPLC.CPU.ToString()); + outVal.Add("MAX_PDU", currPLC.MaxPDUSize.ToString()); + outVal.Add("RACK", currPLC.Rack.ToString()); + outVal.Add("SLOT", currPLC.Slot.ToString()); } catch (Exception exc) { - lgError(exc, "Errore in getCncAlarms"); + lgError(exc, "Errore in getSysInfo"); } 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 + } + } + /// /// Override salvataggio valori in memoria... /// @@ -424,6 +447,6 @@ namespace IOB_WIN { } - #endregion + #endregion Public Methods } -} +} \ No newline at end of file diff --git a/Jenkinsfile b/Jenkinsfile index 1b98cbf7..582b7e98 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -9,7 +9,7 @@ pipeline { steps { /* calcolo numero versione... diverso x branch MASTER/DEVELOP */ script { - withEnv(['NEXT_BUILD_NUMBER=750']) { + withEnv(['NEXT_BUILD_NUMBER=751']) { // env.versionNumber = VersionNumber(versionNumberString : '3.4.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2006-01-01', skipFailedBuilds: true) env.versionNumber = VersionNumber(versionNumberString : '3.4.${BUILD_DATE_FORMATTED, "yyMM"}.${BUILDS_ALL_TIME}', projectStartDate : '2006-01-01', skipFailedBuilds: true, overrideBuildsAllTime: '${NEXT_BUILD_NUMBER}') env.APP_NAME = 'MAPO-IOB-WIN' @@ -24,7 +24,6 @@ pipeline { currentBuild.description = "TEST ${env.versionNumber}" } } - /* CAMBIO numero versione in file sorgente!!! */ bat "e:\\fart.exe VersGen\\VersGen.cs 1.0.0.0 ${env.versionNumber} || EXIT /B 0" }