using EgwProxy.MultiCncLib.CNC; using IOB_UT; using MapoSDK; using System; using System.Collections.Generic; using System.Net; using System.Net.NetworkInformation; namespace IOB_WIN { public class IobFanuc : IobGeneric { #region Private Fields /// /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO /// private Dictionary signLUT = new Dictionary(); #endregion Private Fields #region Protected Fields /// /// Dati dell'area D /// protected memAreaFanuc areaD; /// /// Dati dell'area PARameters /// 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; /// /// 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]; #endregion Protected Fields #region Public Constructors /// /// estende l'init della classe base... /// /// /// public IobFanuc(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) { // i dati RAW principali sono 6 byte... RawInput = new byte[6]; // gestione invio ritardato contapezzi pzCountDelay = utils.CRI("pzCountDelay"); lastPzCountSend = DateTime.Now; lastWarnODL = DateTime.Now; // inizializzo correttamente aree memoria secondo CONF - iniFileName IniFile fIni = new IniFile(IOBConf.iniFileName); // inizializzo aree di memoria correnti... MemBlockG = new byte[fIni.ReadInteger("MEMORY", "AREAG_SIZE", 8)]; MemBlockR = new byte[fIni.ReadInteger("MEMORY", "AREAR_SIZE", 8)]; MemBlockX = new byte[fIni.ReadInteger("MEMORY", "AREAX_SIZE", 8)]; MemBlockY = new byte[fIni.ReadInteger("MEMORY", "AREAY_SIZE", 8)]; // loggo aree di memoria avviate... lgInfo(string.Format("Avviare area di memoria MemBlockG: {0} byte", MemBlockG.Length)); lgInfo(string.Format("Avviare area di memoria MemBlockR: {0} byte", MemBlockR.Length)); lgInfo(string.Format("Avviare area di memoria MemBlockX: {0} byte", MemBlockX.Length)); lgInfo(string.Format("Avviare area di memoria MemBlockY: {0} byte", MemBlockY.Length)); // fix enable prgName enablePrgName = fIni.ReadBoolean("CNC", "GETPRGNAME", true); // salvo le aree X-Y-D (per dump/sample/ottimizzazione lettura) areaD = new memAreaFanuc { areaName = "AreaD", startIdx = fIni.ReadInteger("MEMORY", "AREAD_START", 0), arraySize = fIni.ReadInteger("MEMORY", "AREAD_SIZE", 0) }; areaPAR = new memAreaFanuc { areaName = "AreaPARR", startIdx = fIni.ReadInteger("MEMORY", "PAR_START", 0), arraySize = fIni.ReadInteger("MEMORY", "PAR_SIZE", 0) }; areaR = new memAreaFanuc { areaName = "AreaR", startIdx = fIni.ReadInteger("MEMORY", "AREAR_START", 0), arraySize = fIni.ReadInteger("MEMORY", "AREAR_SIZE", 0) }; areaX = new memAreaFanuc { areaName = "AreaX", startIdx = fIni.ReadInteger("MEMORY", "AREAX_START", 0), arraySize = fIni.ReadInteger("MEMORY", "AREAX_SIZE", 0) }; areaY = new memAreaFanuc { areaName = "AreaY", startIdx = fIni.ReadInteger("MEMORY", "AREAY_START", 0), arraySize = fIni.ReadInteger("MEMORY", "AREAY_SIZE", 0) }; lgInfo(string.Format("Salvata area di memoria: {0}, da {1} per {2} byte", areaD.areaName, areaD.startIdx, areaD.arraySize)); lgInfo(string.Format("Salvata area di memoria: {0}, da {1} per {2} byte", areaR.areaName, areaR.startIdx, areaR.arraySize)); lgInfo(string.Format("Salvata area di memoria: {0}, da {1} per {2} byte", areaX.areaName, areaX.startIdx, areaX.arraySize)); lgInfo(string.Format("Salvata area di memoria: {0}, da {1} per {2} byte", areaY.areaName, areaY.startIdx, areaY.arraySize)); // 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 FANUC all'IP {0}:{1} per IOB {2}", IOBConf.cncIpAddr, IOBConf.cncPort, IOBConf.codIOB); // Creo oggetto connessione NC parentForm.commPlcActive = true; Runtime.CreateNC(CNC.NcType.FANUC, IOBConf.cncIpAddr, IOBConf.cncPort); parentForm.commPlcActive = false; // aggiungo referenza obj FANUC FANUC_ref = (FANUC)Runtime.NC; if (isVerboseLog) { lgInfo("FANUC_ref da EgwProxy.MultiCncLib"); } // disconnetto e connetto... if (isVerboseLog) { lgInfo("FANUC: tryDisconnect"); } tryDisconnect(); lgInfo("FANUC: tryConnect"); tryConnect(); if (utils.CRB("enableContapezzi")) { lgInfo("FANUC: 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 FANUC: 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 FANUC"); } } // finisco INIT ADAPTER lgInfo("End init Adapter FANUC"); } #endregion Public Constructors #region Private Methods /// /// Effettua decodifica aree memoria alla bitmap usata x MAPO /// private void decodeToBitmap() { // init a zero... B_input = 0; if (connectionOk) { // SE SI E' CONNESSO al FANUC allora è 1=powerON... if (FANUC_ref.Connected) { B_input += 1 << 0; } // decodifico impiegando dictionary... cercando il TIPO di memoria & co... string bKey = ""; string bVal = ""; char area; // valore INVERTED (default è false) bool invSignal = false; string memArea = ""; string[] memIdx; int bitNum = 0; int byteNum = 0; int byte2check = 0; for (int i = 0; i < 8; i++) { bKey = string.Format("BIT{0}", i); // cerco se ci sia in LUT if (signLUT.ContainsKey(bKey)) { // recupero nome variabile... bVal = signLUT[bKey]; // se l'area è PZCOUNT... processo PUNTUALMENTE il CONTAPEZZI... if (bVal.StartsWith("PZCOUNT")) { // 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("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); } } 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.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... 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 FANUC: {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 FANUC: 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 FANUC: {contapezziPLC} | contapezziIOB {contapezziIOB}"); // resetto timer... lastPzCountSend = DateTime.Now; } } } else // area "normale" byte.bit { // di norma è segnale normale => 1, altrimenti inverse => 0... invSignal = false; // cerco se sia inverse (ultimo char "!") --> registro e elimino char... invSignal = bVal.StartsWith("!"); // tolgo comunque inversione... bVal = bVal.Replace("!", ""); // recupero area... area = bVal[0]; // altrimenti decodifico area... memArea = bVal.Substring(1, bVal.Length - 1); memIdx = memArea.Split('.'); // calcolo bit e byte number... int.TryParse(memIdx[0], out byteNum); if (memIdx.Length > 1) { int.TryParse(memIdx[1], out bitNum); } // in base al nome cerco in una delle aree.. e prendo solo solo quel bit di quel byte... switch (area) { case 'G': byte2check = MemBlockG[byteNum]; break; case 'R': byte2check = MemBlockR[byteNum]; break; case 'X': byte2check = MemBlockX[byteNum]; break; case 'Y': byte2check = MemBlockY[byteNum]; break; default: break; } // a secondo che sia segnale normale o inverso... if (invSignal) { // controllo se il bit sia NON attivo (basso)... == 0... if ((byte2check & (1 << bitNum)) == 0) { B_input += 1 << i; } } else { // controllo se il bit sia attivo (alto)... != 0 if ((byte2check & (1 << bitNum)) != 0) { B_input += 1 << i; } } } } } } // log opzionale! if (verboseLog) { lgInfo(string.Format("Trasformazione B_input: {0}", B_input)); } } /// /// Dump area D della memoria /// /// tipo di DUMP: START (sovrascrivendo) / SAMPLE (salva tanti campionamenti) /// tipo memoria /// area memoria di partenza /// dimensione memoria private void dump_MemArea(dumpType tipo, FANUC.MemType tipoMem, int memIndex, int memSizeByte) { DateTime adesso = DateTime.Now; string nomeFileB = ""; string nomeFileW = ""; string nomeFileDW = ""; Dictionary mappaValori = new Dictionary(); // per sicurezza verifico < 9999 byte if (memSizeByte > 9999) { memSizeByte = 9999; } // leggo TUTTI i (MAX 9999) byte della memoria D... byte[] MemBlockCurr = new byte[memSizeByte]; if (verboseLog) { lgInfo("START MemDump", tipoMem); } stopwatch.Restart(); FanucMemRW(R, tipoMem, memIndex, ref MemBlockCurr); if (utils.CRB("recTime")) { TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-{1}", MemBlockCurr.Length, tipoMem), stopwatch.ElapsedTicks); } if (verboseLog) { lgInfo("END MemDump", tipoMem); } // seconda del tipo di lettura definisco i nomi delle variabili... if (tipo == dumpType.SAMPLE) { nomeFileB = string.Format(@"{0}\SAMPLES\{1}_{2}_Byte_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem, adesso); nomeFileW = string.Format(@"{0}\SAMPLES\{1}_{2}_W_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem, adesso); nomeFileDW = string.Format(@"{0}\SAMPLES\{1}_{2}_DW_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem, adesso); } else { // salvo in file i dati letti come BYTE nomeFileB = string.Format(@"{0}\{1}_{2}_Byte.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem); nomeFileW = string.Format(@"{0}\{1}_{2}_W.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem); nomeFileDW = string.Format(@"{0}\{1}_{2}_DW.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem); } // salvo in file i dati letti come BYTE mappaValori = new Dictionary(); for (int i = 0; i < MemBlockCurr.Length; i++) { mappaValori.Add(i.ToString("0000"), MemBlockCurr[i].ToString()); } utils.WritePlain(mappaValori, nomeFileB); // salvo in file i dati letti come Word (2byte) mappaValori = new Dictionary(); for (int i = 0; i < MemBlockCurr.Length / 2; i++) { mappaValori.Add(i.ToString("0000"), BitConverter.ToUInt16(MemBlockCurr, i * 2).ToString()); } utils.WritePlain(mappaValori, nomeFileW); // salvo in file i dati letti come DWord (4byte) mappaValori = new Dictionary(); for (int i = 0; i < MemBlockCurr.Length / 4; i++) { mappaValori.Add(i.ToString("0000"), BitConverter.ToUInt32(MemBlockCurr, i * 4).ToString()); } utils.WritePlain(mappaValori, nomeFileDW); } /// /// Dump area PARAMETRI /// /// tipo di DUMP: START (sovrascrivendo) / SAMPLE (salva tanti campionamenti) /// Parametro di partenza /// Numero parametri da esportare... memoria private void dump_ParArea(dumpType tipo, int memIndex, int numPar) { DateTime adesso = DateTime.Now; string nomeFile = ""; Dictionary mappaValori = new Dictionary(); // per sicurezza verifico < 9999 parametri if (numPar > 9999) { numPar = 9999; } // leggo TUTTI i (MAX 9999) byte della memoria D... object[] paramsArray = new object[numPar]; if (verboseLog) { lgInfo("START ParamDump"); } stopwatch.Restart(); for (int i = 0; i < numPar; i++) { FANUC_ref.F_RW_Param_Integer(false, memIndex + i, 3, ref paramsArray[i]); } if (utils.CRB("recTime")) { TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-PAR", 4 * numPar), stopwatch.ElapsedTicks); } if (verboseLog) { lgInfo("END ParamDump"); } // seconda del tipo di lettura definisco i nomi delle variabili... if (tipo == dumpType.SAMPLE) { nomeFile = string.Format(@"{0}\SAMPLES\{1}_{2}_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, cIobConf.codIOB, "PAR", adesso); } else { nomeFile = string.Format(@"{0}\{1}_{2}.dat", utils.dataDatDir, cIobConf.codIOB, "PAR"); } // salvo in file i dati letti mappaValori = new Dictionary(); for (int i = 0; i < paramsArray.Length; i++) { mappaValori.Add(i.ToString("0000"), paramsArray[i].ToString()); } 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(); if (task2exe != null) { 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(); EgwProxy.MultiCncLib.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... EgwProxy.MultiCncLib.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(); EgwProxy.MultiCncLib.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 } }