diff --git a/Documentazione/Kawasaki/Appunti Kawasaki.txt b/Documentazione/Kawasaki/Appunti Kawasaki.txt new file mode 100644 index 00000000..53eae90e --- /dev/null +++ b/Documentazione/Kawasaki/Appunti Kawasaki.txt @@ -0,0 +1,95 @@ +Kawasaki: + +in realtà tutte real values +se non ci sono decimali non li restituisce + +0 = false +1 = true + +192.168.0.92 +255.255.252.0 + + +1) primo ctrl: ping +oppure meglio, col comando TI TASK 1004 = chiedo se il processo 4 è in esecuzione (task parallelo di comunicazione) +2) leggo con ty nome_variabile (max 15 CHAR, START 1 LETTERA) +3) ho (hold) BLOCCA IL CICLO + + +nome stringa = $status (1 byte) + += Word 0: 8bit 0000000 + +B0 = power --> derivo ping + communicazione +B1 = AUTO (cycle + repeat + TeachLock_OFF) +B2 = RUN (se non c'è sono in HOLD) +B3 = ERROR KAWASAKI - SYSERROR - allarme sistema (es collisione, posizione irraggiungibile, batterie scariche) +B4 = ERRORE LOGICO (allarme di programma) +B5 = EMERGENZA ARMATA (1= tutto ok, 0 = triggered = problema) +B6 = SAFETY FENCE (cancelli chiusi - 1= tutto ok, 0 = triggered = problema) +B7 = PRONTO AL CARICAMENTO + +nome: +$signals += Word 1: 8bit 0000000 + +B0 = transfer in AUTOMATICO +B1 = punzonatrice in AUTOMATICO +B2 = barriera tavola RIPRISTINATA (sennò blocca ciclo robot quando finsice pezzi) +B3 = pressione aria insufficiente +B4 = console fuori posizione +B5 = +B6 = +B7 = + + + +RESET CONTAPEZZI (R/W), con questa istruzione lo resetto +$i_cicli = 0 + +Tempo ciclo: +$r_tempo rappresenta il TCiclo misurato dell'ultimo ciclo + +La "missione in atto" (iniziano con m, es mPrelievo) mi fa capire DOVE sia l'allarme (corrente o successiva) +$exe + +SE E' VUOTA significa NON DEVE FARE NULLA... + +MODELLO ROBOT + seriale Robot (READ ONLY) +$id_true + +la DLL, anche sul mio pc, se trova lo stesso file, crea prima il backup... +file: *.as (advanced software) +backup: *.bas (backup adv sw) + +SA / SAVE (in ogni momento) posso salvare + +attrezzaggio con file transfer potrebbe essere con questi comandi + +SUL ROBOT, prima di fare tutto, IL ROBOT NON DEVE ESSERE in ciclo, in repeat, in automatico, in errore... + + +FERMA (ferma i programmi) + +sleep(3 sec) + +TOGLI (toglie i programmi da pronta esecuzione, principale + task paralleli) + +sleep(3 sec) + +LO (LOAD) nome dole mio programma x caricarlo (dal gestionale Notyo) + +mi restituisce "load file 0 error" + +sleep(3) + +PARTI (avvio tutti i processi) + + + +ARTICOLO IN PROD (READ ONLY) +$modello = modelo caricato sul programma x fare confronto LO LEGGO; se NON E' uguale al mio, mando comando ho/hold x poter bloccare avvio (SE non è coerente il programma) + +seconda variabile: $prod + + diff --git a/IOB-UT/baseUtils.cs b/IOB-UT/baseUtils.cs index 769ff67c..2f7a8f45 100644 --- a/IOB-UT/baseUtils.cs +++ b/IOB-UT/baseUtils.cs @@ -693,6 +693,10 @@ namespace IOB_UT /// FANUC, /// + /// adapter KAWASAKI e-controller + /// + KAWASAKI, + /// /// Adapter non specificato /// ND, diff --git a/IOB-WIN/AdapterForm.cs b/IOB-WIN/AdapterForm.cs index 6d374d91..ca10e639 100644 --- a/IOB-WIN/AdapterForm.cs +++ b/IOB-WIN/AdapterForm.cs @@ -618,6 +618,10 @@ namespace IOB_WIN iobObj = new IobFanuc(this, IOBConf); start.Enabled = true; break; + case tipoAdapter.KAWASAKI: + iobObj = new IobKawasaki(this, IOBConf); + start.Enabled = true; + break; case tipoAdapter.SIEMENS: iobObj = new IobSiemens(this, IOBConf); start.Enabled = true; diff --git a/IOB-WIN/DATA/CONF/4000.ini b/IOB-WIN/DATA/CONF/4000.ini new file mode 100644 index 00000000..0d1fb4d1 --- /dev/null +++ b/IOB-WIN/DATA/CONF/4000.ini @@ -0,0 +1,57 @@ +;Configurazione IOB-WIN +[IOB] +CNCTYPE=KAWASAKI + +[MACHINE] +VENDOR=KAWASAKI +MODEL=E-CONTROLLER + +[CNC] +; TEST KAWASAKI +IP=192.168.0.92 +;PORT=8193 + +[SERVER] +MPIP=SRV-MAPO +MPURL=/MP/IO +CMDBASE=/IOB/input/ +CMDFLOG=/IOB/flog/ +CMDALIVE=/IOB +CMDENABLED=/IOB/enabled/ +CMDADV1=?valore= +CMDREBO=/sendReboot.aspx?idxMacchina= + +[MEMORY] +BITRED=Y8.4 +BITYELLOW=Y8.5 +BITGREEN=Y8.6 +AREAD_START=0 +AREAD_SIZE=9999 +AREAY_START=0 +AREAY_SIZE=64 + +[BLINK] +;MAX_COUNTER_BLINK = 30 +MAX_COUNTER_BLINK = 15 +;bit0 = 0 +;bit1 = 0 +;bit2 = 1 +;bit3 = 1 +;bit4 = 1 +;bit5 = 0 +;bit6 = 0 +;bit7 = 0 +BLINK_FILT=0 +;BLINK_FILT=28 + +[OPTPAR] +;PZCOUNT_MODE=STD.[PAR/MEM].info|BIT.indice +; attenzione memoria sempre base BYTE (1604 DW --> 6416...) +PZCOUNT_MODE=BIT +PZ_CAD_MADDR=1602 +PZ_REQ_MADDR=1603 +PZ_DONE_MADDR=1604 +PZ_GTOT_MADDR=1605 + +[BRANCH] +NAME=master \ No newline at end of file diff --git a/IOB-WIN/DATA/CONF/MAIN.ini b/IOB-WIN/DATA/CONF/MAIN.ini index 1925004e..313045c6 100644 --- a/IOB-WIN/DATA/CONF/MAIN.ini +++ b/IOB-WIN/DATA/CONF/MAIN.ini @@ -4,14 +4,14 @@ NAME=develop [SERVER] -MPIP=192.168.1.7 -#MPIP=10.74.82.219 +#MPIP=192.168.1.7 +MPIP=10.74.82.219 MPURL=/MP/IO CMDREBO=/IOB/sendRebootGateway?GWIP= CMDIOB2CALL=/IOB/getIob2call?GWIP= [IOB] -STARTLIST=C502 +STARTLIST=4000 ;STARTLIST=3013 MAXCNC=4 ;STARTLIST=3001,3002,3003,3004,3005 \ No newline at end of file diff --git a/IOB-WIN/ExtLib/krcc.dll b/IOB-WIN/ExtLib/krcc.dll new file mode 100644 index 00000000..2986f93c Binary files /dev/null and b/IOB-WIN/ExtLib/krcc.dll differ diff --git a/IOB-WIN/ExtLib/krcc64.dll b/IOB-WIN/ExtLib/krcc64.dll new file mode 100644 index 00000000..77b91761 Binary files /dev/null and b/IOB-WIN/ExtLib/krcc64.dll differ diff --git a/IOB-WIN/IOB-WIN.csproj b/IOB-WIN/IOB-WIN.csproj index ef38f385..47932d4a 100644 --- a/IOB-WIN/IOB-WIN.csproj +++ b/IOB-WIN/IOB-WIN.csproj @@ -52,6 +52,10 @@ ..\packages\Autoupdater.NET.Official.1.4.9\lib\net452\AutoUpdater.NET.dll + + False + ExtLib\krcc.dll + ..\packages\NLog.4.5.3\lib\net45\NLog.dll @@ -80,6 +84,7 @@ VersGen.cs + @@ -109,6 +114,8 @@ TestForm.cs + + Always @@ -197,6 +204,9 @@ Always + + Always + diff --git a/IOB-WIN/IobKawasaki.cs b/IOB-WIN/IobKawasaki.cs new file mode 100644 index 00000000..ec216796 --- /dev/null +++ b/IOB-WIN/IobKawasaki.cs @@ -0,0 +1,1181 @@ +using System; + +namespace IOB_WIN +{ + public class IobKawasaki : IobGeneric + { +#if false + /// + /// 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]; + /// + /// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO + /// + Dictionary signLUT = new Dictionary(); + + /// + /// wrapper chiamata lettura/scrittura SINGOLO BYTE... + /// + /// + /// + /// + /// + /// + public bool FanucMemRW(bool bWrite, FANUC.MemType MemType, Int32 memIndex, ref byte Value) + { + bool answ = false; + 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 (FANUC_ref.Connected) + { + try + { + parentForm.commPlcActive = true; + answ = FANUC_ref.F_RW_Byte(bWrite, MemType, memIndex, ref Value); + } + catch + { } + } + parentForm.commPlcActive = false; + return answ; + } + /// + /// Oggetto MAIN x connessione FANUC + /// + protected FANUC FANUC_ref; + + /// + /// Dati dell'area D + /// + protected memAreaFanuc areaD; + /// + /// Dati dell'area PARameters + /// + protected memAreaFanuc areaPAR; + /// + /// Dati dell'area R + /// + protected memAreaFanuc areaR; + /// + /// Dati dell'area X + /// + protected memAreaFanuc areaX; + /// + /// Dati dell'area Y + /// + protected memAreaFanuc areaY; +#endif + + /// + /// estende l'init della classe base... + /// + /// + /// + public IobKawasaki(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf) + { + + try + { + KRcc.Commu com = new KRcc.Commu("TCP 192.168.0.92"); + if (com.IsConnected) + { + // connect ok + //KRcc.Commu com = new KRcc.Commu("TCP 192.168.0.92"); + System.Collections.ArrayList resp; + resp = com.command("where", 3000); // WHERE [RET] + Console.WriteLine(resp[0]); + + resp = com.command("TYPE TASK (1004)", 3000); // thread 4 ok --> " 1\r\n" + + + resp = com.command("TYPE $id_true", 3000); // id macchina --> "BX100N-B001 Sn. 2366\r\n" + + resp = com.command("TYPE $status", 3000); // status --> "0|0|1|0|0|1|0|0\r\n" + + resp = com.command("TYPE $signal", 3000); // segnali --> "1|0|1|1|1|0|0|0\r\n" + + resp = com.command("TYPE i_prelevati", 3000); // num pz prelevati --> "0\r\n" + + + resp = com.command("TYPE i_cicli", 3000); // num cicli depositati/fatti --> " 0\r\n" + + resp = com.command("TYPE r_tempo", 3000); // ultimo TCiclo rilevato --> " 349.19\r\n" + + resp = com.command("TYPE $exe", 3000); // missione --> "\r\n" (vuoto, no missione) + + + // scrivo valore cicli + resp = com.command("i_cicli=3", 3000); // imposto cicli depositati/fatti a 3 --> " 0\r\n" + + resp = com.command("TYPE i_cicli", 3000); // num cicli depositati/fatti --> " 0\r\n" + + + // comandi x setup programma... + + resp = com.command("ferma", 3000); // ferma processi (all) --> "" + + resp = com.command("togli", 3000); // toglie processi da pronta esecuzione --> "" + + //resp = com.command("SAVE nome_del_file", 3000); // salvataggio file... FORSE --> "\u0005\u0002Bnome_del_file.as\u0017" --> verificare DOVE salva... + + + int ret = com.save("foo_02.as"); // SAVE foo.as[RET] + if (ret == 0) + { // Success + } + if (ret == -1) + { // Communication error + } + if (ret == -2) + { // Robot Controller error + } + if (ret == -3) + { // Internal error + } + + // carico... + com.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 = com.load("foo.as", "/Q"); // LOAD/Q foo.as[RET] + + + } + } + catch (Exception e) + { // e.Message = "can't connect TCP/IP" or // "can't login" + Console.WriteLine(e.Message); + } + + +#if false + // i dati RAW principali sono 6 byte... + RawInput = new byte[6]; + + // gestione invio ritardato contapezzi + pzCountDelay = utils.CRI("pzCountDelay"); + lastPzCountSend = DateTime.Now; + lastWarnODL = DateTime.Now; + + // inizializzo correttamente aree memoria secondo CONF - iniFileName + IniFile fIni = new IniFile(IOBConf.iniFileName); + // inizializzo aree di memoria correnti... + MemBlockG = new byte[fIni.ReadInteger("MEMORY", "AREAG_SIZE", 8)]; + MemBlockR = new byte[fIni.ReadInteger("MEMORY", "AREAR_SIZE", 8)]; + MemBlockX = new byte[fIni.ReadInteger("MEMORY", "AREAX_SIZE", 8)]; + MemBlockY = new byte[fIni.ReadInteger("MEMORY", "AREAY_SIZE", 8)]; + // loggo aree di memoria avviate... + lgInfo(string.Format("Avviare area di memoria MemBlockG: {0} byte", MemBlockG.Length)); + lgInfo(string.Format("Avviare area di memoria MemBlockR: {0} byte", MemBlockR.Length)); + lgInfo(string.Format("Avviare area di memoria MemBlockX: {0} byte", MemBlockX.Length)); + lgInfo(string.Format("Avviare area di memoria MemBlockY: {0} byte", MemBlockY.Length)); + + // fix enable prgName + enablePrgName = fIni.ReadBoolean("CNC", "GETPRGNAME", true); + + // salvo le aree X-Y-D (per dump/sample/ottimizzazione lettura) + areaD = new memAreaFanuc + { + areaName = "AreaD", + startIdx = fIni.ReadInteger("MEMORY", "AREAD_START", 0), + arraySize = fIni.ReadInteger("MEMORY", "AREAD_SIZE", 0) + }; + areaPAR = new memAreaFanuc + { + areaName = "AreaPARR", + startIdx = fIni.ReadInteger("MEMORY", "PAR_START", 0), + arraySize = fIni.ReadInteger("MEMORY", "PAR_SIZE", 0) + }; + areaR = new memAreaFanuc + { + areaName = "AreaR", + startIdx = fIni.ReadInteger("MEMORY", "AREAR_START", 0), + arraySize = fIni.ReadInteger("MEMORY", "AREAR_SIZE", 0) + }; + areaX = new memAreaFanuc + { + areaName = "AreaX", + startIdx = fIni.ReadInteger("MEMORY", "AREAX_START", 0), + arraySize = fIni.ReadInteger("MEMORY", "AREAX_SIZE", 0) + }; + areaY = new memAreaFanuc + { + areaName = "AreaY", + startIdx = fIni.ReadInteger("MEMORY", "AREAY_START", 0), + arraySize = fIni.ReadInteger("MEMORY", "AREAY_SIZE", 0) + }; + lgInfo(string.Format("Salvata area di memoria: {0}, da {1} per {2} byte", areaD.areaName, areaD.startIdx, areaD.arraySize)); + lgInfo(string.Format("Salvata area di memoria: {0}, da {1} per {2} byte", areaR.areaName, areaR.startIdx, areaR.arraySize)); + lgInfo(string.Format("Salvata area di memoria: {0}, da {1} per {2} byte", areaX.areaName, areaX.startIdx, areaX.arraySize)); + lgInfo(string.Format("Salvata area di memoria: {0}, da {1} per {2} byte", areaY.areaName, areaY.startIdx, areaY.arraySize)); + + // effettuo lettura della conf sigLUT... cercando 1:1 i bit... + string currBit = ""; + string memArea = ""; + for (int i = 0; i < 8; i++) + { + currBit = string.Format("BIT{0}", i); + memArea = fIni.ReadString("MEMORY", currBit, ""); + // se trovo un valore... + if (memArea != "") + { + signLUT.Add(currBit, memArea); + } + } + + // è little endian (NON serve conversione) + hasBigEndian = false; + lgInfo("Start init Adapter FANUC all'IP {0}:{1} per IOB {2}", IOBConf.cncIpAddr, IOBConf.cncPort, IOBConf.codIOB); + + // Creo oggetto connessione NC + parentForm.commPlcActive = true; + Runtime.CreateNC(CNC.NcType.FANUC, IOBConf.cncIpAddr, IOBConf.cncPort); + parentForm.commPlcActive = false; + + // aggiungo referenza obj FANUC + FANUC_ref = (FANUC)Runtime.NC; + if (utils.CRB("verbose")) + { + lgInfo("FANUC_ref da CncLib"); + } + + // disconnetto e connetto... + if (utils.CRB("verbose")) + { + lgInfo("FANUC: tryDisconnect"); + } + + tryDisconnect(); + lgInfo("FANUC: tryConnect"); + tryConnect(); + if (utils.CRB("enableContapezzi")) + { + lgInfo("FANUC: inizio gestione contapezzi"); + try + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + if (currIobConf.optPar.Count > 0 && currIobConf.optPar["PZCOUNT_MODE"] != "") + { + if (currIobConf.optPar["PZCOUNT_MODE"].StartsWith("STD")) + { + pzCntReload(); + // refresh associazione Macchina - IOB + sendM2IOB(); + // per adesso imposto lettura fanuc == contapezzi (poi farà vera lettura...) + lastCountCNC = contapezzi; + } + else + { + contapezzi = 0; + lgInfo("Contapezzi STD disabilitato: modalità {0}", currIobConf.optPar["PZCOUNT_MODE"]); + } + } + else + { + contapezzi = 0; + lgInfo("Parametro mancante PZCOUNT_MODE"); + } + } + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi FANUC"); + } + } + // finisco INIT ADAPTER + lgInfo("End init Adapter FANUC"); +#endif + } + +#if false + + /// + /// 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("ConnKO - tryConnect"); + } + // in primis salvo data ping... + lastPING = DateTime.Now; + // ora PING!!! + Ping pingSender = new Ping(); + IPAddress address = IPAddress.Loopback; + IPAddress.TryParse(currIobConf.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) + { + // carico status allarmi (completo) + lgInfo("Inizio refresh completo stato allarmi..."); + forceAlarmCheck(); + lgInfo("Completato refresh completo stato allarmi!"); + } + else + { + lgInfo("Connessione OK"); + } + } + else + { + lgError("Impossibile procedere, connessione mancante..."); + } + } + catch (Exception exc) + { + lgFatal(string.Format("Errore nella connessione all'adapter 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}", currIobConf.cncIpAddr, reply.Status)); + } + } + } + } + // se non è ancora connesso faccio procesisng memoria caso disconnesso... + if (!connectionOk) + { + // processo semafori ed invio... + processMemoryDiscon(); + } + } + /// + /// lettura principale (bit semafori) + /// + public override void readSemafori() + { + base.readSemafori(); + try + { + if (verboseLog) + { + lgInfo("inizio read semafori"); + } + + parentForm.sIN = 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(currIobConf.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(currIobConf.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(currIobConf.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(); + } + catch (Exception exc) + { + lgError(string.Format("Eccezione in readSemafori:{0}{1}", Environment.NewLine, exc)); + connectionOk = false; + } + } + /// + /// Effettua decodifica aree memoria alla bitmap usata x MAPO + /// + private void decodeToBitmap() + { + // init a zero... + B_input = 0; + // SE SI E' CONNESSO al FANUC allora è 1=powerON... + if (FANUC_ref.Connected) + { + B_input += 1 << 0; + } + + // decodifico impiegando dictionary... cercando il TIPO di memoria & co... + string bKey = ""; + string bVal = ""; + char area; + // valore INVERTED (default è false) + bool invSignal = false; + string memArea = ""; + string[] memIdx; + int bitNum = 0; + int byteNum = 0; + int byte2check = 0; + for (int i = 0; i < 8; i++) + { + bKey = string.Format("BIT{0}", i); + // cerco se ci sia in LUT + if (signLUT.ContainsKey(bKey)) + { + // recupero nome variabile... + bVal = signLUT[bKey]; + // se l'area è PZCOUNT... processo PUNTUALMENTE il CONTAPEZZI... + if (bVal.StartsWith("PZCOUNT")) + { + string currODL = ""; + try + { + currODL = utils.callUrl(urlGetCurrODL); + lgInfo(string.Format("Lettura ODL, {0} --> {1}", currIdxODL, currODL)); + // provo a salvare nuovo ODL + int.TryParse(currODL, out currIdxODL); + } + catch (Exception exc) + { + if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15) + { + lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL); + lastWarnODL = DateTime.Now; + } + } + if (currODL != null && currODL != "" && currODL != "0") + { + // controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + // verifico se variato contapezzi in area STD PAR6711... e se passato ritardo minimo... + if (lastCountCNC > contapezzi) + { + // salvo nuovo contapezzi (incremento di 1...) + contapezzi++; + // salvo in semaforo! + B_input += 1 << 2; + } + // registro contapezzi + lgInfo(string.Format("Contapezzi FANUC: {0} | Contapezzi interno {1}", lastCountCNC, contapezzi)); + + // 2018.06.26 NON resetto perché si deve resettare da solo da conteggio TC POST cambio ODL... +#if false + else if (contapezzi > lastCountCNC) // in questo caso resetto + { + contapezzi = lastCountCNC; + } +#endif + // invio a server contapezzi (aggiornato) + string retVal = utils.callUrl(urlSetPzCount + contapezzi.ToString()); + // verifica se tutto OK + if (retVal != "OK") + { + // errore salvataggio contapezzi + lgInfo(string.Format("Errore salvataggio Contapezzi FANUC: {0} | Contapezzi interno {1} | Errore salvataggio: {2}", lastCountCNC, contapezzi, retVal)); + } + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + else + { + if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay)) + { + lgInfo(string.Format("Attenzione: mancanza ODL non procedo con gestione contapezzi. Contapezzi FANUC: {0} | Contapezzi interno {1}", lastCountCNC, contapezzi)); + // resetto timer... + lastPzCountSend = DateTime.Now; + } + } + } + else // area "normale" byte.bit + { + // di norma è segnale normale => 1, altrimenti inverse => 0... + invSignal = false; + // cerco se sia inverse (ultimo char "!") --> registro e elimino char... + invSignal = bVal.StartsWith("!"); + // tolgo comunque inversione... + bVal = bVal.Replace("!", ""); + // recupero area... + area = bVal[0]; + // altrimenti decodifico area... + memArea = bVal.Substring(1, bVal.Length - 1); + memIdx = memArea.Split('.'); + // calcolo bit e byte number... + int.TryParse(memIdx[0], out byteNum); + if (memIdx.Length > 1) + { + int.TryParse(memIdx[1], out bitNum); + } + // in base al nome cerco in una delle aree.. e prendo solo solo quel bit di quel byte... + switch (area) + { + case 'G': + byte2check = MemBlockG[byteNum]; + break; + case 'R': + byte2check = MemBlockR[byteNum]; + break; + case 'X': + byte2check = MemBlockX[byteNum]; + break; + case 'Y': + byte2check = MemBlockY[byteNum]; + break; + default: + break; + } + // a secondo che sia segnale normale o inverso... + if (invSignal) + { + // controllo se il bit sia NON attivo (basso)... == 0... + if ((byte2check & (1 << bitNum)) == 0) + { + B_input += 1 << i; + } + } + else + { + // controllo se il bit sia attivo (alto)... != 0 + if ((byte2check & (1 << bitNum)) != 0) + { + B_input += 1 << i; + } + } + +#if false + // da rivedere x gestione contapezzi a bit... + // verifico se si tratta di un segnale contapezzo... nel qual caso conteggio ed invio... + if (currIobConf.optPar["PZCOUNT_MODE"].StartsWith("BIT")) + { + // salvo nuovo contapezzi (incremento di 1...) + contapezzi++; + // invio a server contapezzi (aggiornato) + utils.callUrl(urlSetPzCount + contapezzi.ToString()); + lgInfo("Aggiornato contapezzi: {0}", contapezzi); + // resetto timer... + lastPzCountSend = DateTime.Now; + } +#endif + } + + } + } + // 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 = 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(currIobConf.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")) + { + try + { + // verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area) + if (currIobConf.optPar.Count > 0 && currIobConf.optPar["PZCOUNT_MODE"] != "") + { + string memAddr = currIobConf.optPar["PZCOUNT_MODE"]; + if (memAddr.StartsWith("STD")) + { + // inizio verifica area memoria/parametro levando prima parte codice + memAddr = memAddr.Replace("STD.", ""); + // 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(currIobConf.codIOB, string.Format("R{0}-PAR", 4), stopwatch.ElapsedTicks); + } + + // salvo ultimo conteggio rilevato + Int32.TryParse(outputVal.ToString(), out lastCountCNC); + } + // altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW + else + { + memAddressFanuc areaCounter = new memAddressFanuc(memAddr); + + if (utils.CRB("verbose")) + { + 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 (utils.CRB("verbose")) + { + lgInfo("[1] valDW contapezzi: {0}", valDW); + } + + outputVal = valDW; + if (utils.CRB("verbose")) + { + lgInfo("[2] outputVal contapezzi: {0}", outputVal); + } + + break; + default: + break; + } + if (utils.CRB("recTime")) + { + TimingData.addResult(currIobConf.codIOB, string.Format("R-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks); + } + + // salvo... + Int32.TryParse(outputVal.ToString(), out lastCountCNC); + if (utils.CRB("verbose")) + { + lgInfo("[3] lastCountCNC contapezzi: {0}", lastCountCNC); + } + } + stopwatch.Stop(); + } + } + } + catch (Exception exc) + { + lgError(exc, "Errore in contapezzi FANUC"); + connectionOk = false; + } + } + } + /// + /// Esegue processing MODE (e nel contempo recupera altri dati dell'area G) + /// + public override void processMode() + { + if (utils.CRB("enableMode")) + { + 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(currIobConf.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 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(); + stopwatch.Restart(); + CncLib.Focas1.ODBDY2_1 answ = FANUC_ref.getAllDynData(); + if (utils.CRB("recTime")) + { + TimingData.addResult(currIobConf.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(); + if (utils.CRB("enableMode") && MemBlockG != null) + { + 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 + /// + /// tipo di DUMP: START (sovrascrivendo) / SAMPLE (salva tanti campionamenti) + /// tipo memoria + /// area memoria di partenza + /// dimensione memoria + private void dump_MemArea(dumpType tipo, FANUC.MemType tipoMem, int memIndex, int memSizeByte) + { + DateTime adesso = DateTime.Now; + string nomeFileB = ""; + string nomeFileW = ""; + string nomeFileDW = ""; + Dictionary mappaValori = new Dictionary(); + // per sicurezza verifico < 9999 byte + if (memSizeByte > 9999) + { + memSizeByte = 9999; + } + // leggo TUTTI i (MAX 9999) byte della memoria D... + byte[] MemBlockCurr = new byte[memSizeByte]; + if (verboseLog) + { + lgInfo("START MemDump", tipoMem); + } + + stopwatch.Restart(); + FanucMemRW(R, tipoMem, memIndex, ref MemBlockCurr); + if (utils.CRB("recTime")) + { + TimingData.addResult(currIobConf.codIOB, string.Format("R{0}-{1}", MemBlockCurr.Length, tipoMem), stopwatch.ElapsedTicks); + } + + if (verboseLog) + { + lgInfo("END MemDump", tipoMem); + } + + // seconda del tipo di lettura definisco i nomi delle variabili... + if (tipo == dumpType.SAMPLE) + { + nomeFileB = string.Format(@"{0}\SAMPLES\{1}_{2}_Byte_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, currIobConf.codIOB, tipoMem, adesso); + nomeFileW = string.Format(@"{0}\SAMPLES\{1}_{2}_W_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, currIobConf.codIOB, tipoMem, adesso); + nomeFileDW = string.Format(@"{0}\SAMPLES\{1}_{2}_DW_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, currIobConf.codIOB, tipoMem, adesso); + } + else + { + // salvo in file i dati letti come BYTE + nomeFileB = string.Format(@"{0}\{1}_{2}_Byte.dat", utils.dataDatDir, currIobConf.codIOB, tipoMem); + nomeFileW = string.Format(@"{0}\{1}_{2}_W.dat", utils.dataDatDir, currIobConf.codIOB, tipoMem); + nomeFileDW = string.Format(@"{0}\{1}_{2}_DW.dat", utils.dataDatDir, currIobConf.codIOB, tipoMem); + } + + // salvo in file i dati letti come BYTE + mappaValori = new Dictionary(); + for (int i = 0; i < MemBlockCurr.Length; i++) + { + mappaValori.Add(i.ToString("0000"), MemBlockCurr[i].ToString()); + } + utils.WritePlain(mappaValori, nomeFileB); + + // salvo in file i dati letti come Word (2byte) + mappaValori = new Dictionary(); + for (int i = 0; i < MemBlockCurr.Length / 2; i++) + { + mappaValori.Add(i.ToString("0000"), BitConverter.ToUInt16(MemBlockCurr, i * 2).ToString()); + } + utils.WritePlain(mappaValori, nomeFileW); + + // salvo in file i dati letti come DWord (4byte) + mappaValori = new Dictionary(); + for (int i = 0; i < MemBlockCurr.Length / 4; i++) + { + mappaValori.Add(i.ToString("0000"), BitConverter.ToUInt32(MemBlockCurr, i * 4).ToString()); + } + utils.WritePlain(mappaValori, nomeFileDW); + } + /// + /// Dump area PARAMETRI + /// + /// tipo di DUMP: START (sovrascrivendo) / SAMPLE (salva tanti campionamenti) + /// Parametro di partenza + /// Numero parametri da esportare... memoria + private void dump_ParArea(dumpType tipo, int memIndex, int numPar) + { + DateTime adesso = DateTime.Now; + string nomeFile = ""; + Dictionary mappaValori = new Dictionary(); + // per sicurezza verifico < 9999 parametri + if (numPar > 9999) + { + numPar = 9999; + } + + // leggo TUTTI i (MAX 9999) byte della memoria D... + object[] paramsArray = new object[numPar]; + if (verboseLog) + { + lgInfo("START ParamDump"); + } + + stopwatch.Restart(); + for (int i = 0; i < numPar; i++) + { + FANUC_ref.F_RW_Param_Integer(false, memIndex + i, 3, ref paramsArray[i]); + } + + if (utils.CRB("recTime")) + { + TimingData.addResult(currIobConf.codIOB, string.Format("R{0}-PAR", 4 * numPar), stopwatch.ElapsedTicks); + } + + if (verboseLog) + { + lgInfo("END ParamDump"); + } + + // seconda del tipo di lettura definisco i nomi delle variabili... + if (tipo == dumpType.SAMPLE) + { + nomeFile = string.Format(@"{0}\SAMPLES\{1}_{2}_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, currIobConf.codIOB, "PAR", adesso); + } + else + { + nomeFile = string.Format(@"{0}\{1}_{2}.dat", utils.dataDatDir, currIobConf.codIOB, "PAR"); + } + + // salvo in file i dati letti + mappaValori = new Dictionary(); + for (int i = 0; i < paramsArray.Length; i++) + { + mappaValori.Add(i.ToString("0000"), paramsArray[i].ToString()); + } + utils.WritePlain(mappaValori, nomeFile); + } +#endif + } +}