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"
}