8bb0f158b5
- proj di base con le 2 form da ereditare - progetto globale che contiene TUTTI gli adapter (pronto a venire spezzettato - gettate le basi x "portare fuori" i vari componenti oppure fare compilazione condizonale
1103 lines
40 KiB
C#
1103 lines
40 KiB
C#
using IOB_UT_NEXT;
|
|
using MapoSDK;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Net.NetworkInformation;
|
|
|
|
namespace IOB_WIN_NEXT.Iob
|
|
{
|
|
public class Kawasaki : Iob.GenericNext, IDisposable
|
|
{
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// estende l'init della classe base...
|
|
/// </summary>
|
|
/// <param name="caller"></param>
|
|
/// <param name="adpConf"></param>
|
|
public Kawasaki(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf)
|
|
{
|
|
// gestione invio ritardato contapezzi
|
|
pzCountDelay = utils.CRI("pzCountDelay");
|
|
lastPzCountSend = DateTime.Now;
|
|
lastWarnODL = DateTime.Now;
|
|
// init connessione
|
|
setConnection();
|
|
|
|
// test completo funzionalità kawasaki, da TOGLIERE in prod...
|
|
#if DEBUG
|
|
kawasakiFullTest();
|
|
#endif
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Enums
|
|
|
|
/// <summary>
|
|
/// Enum segnali macchina ulteriori (ByteSignals)
|
|
/// </summary>
|
|
[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
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enum segnali status macchina (ByteStatus) come flag
|
|
/// </summary>
|
|
[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 Public Methods
|
|
|
|
/// <summary>
|
|
/// Metodo dispose x il currPLC contenuto
|
|
/// </summary>
|
|
public void Dispose()
|
|
{
|
|
KAWASAKI_ref.disconnect();
|
|
KAWASAKI_ref.Dispose();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processo i task richiesti e li elimino dalla coda 1:1
|
|
/// </summary>
|
|
/// <param name="task2exe"></param>
|
|
public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe)
|
|
{
|
|
// Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti...
|
|
Dictionary<string, string> taskDone = new Dictionary<string, string>();
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupero dati dinamici...
|
|
/// </summary>
|
|
public override Dictionary<string, string> getDynData()
|
|
{
|
|
// valore non presente in vers default... se gestito fare override
|
|
Dictionary<string, string> outVal = new Dictionary<string, string>();
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupero programma in lavorazione
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override string getPrgName()
|
|
{
|
|
// valore non presente in vers default... se gestito fare override
|
|
string prgName = "";
|
|
return prgName;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupero info sistema generiche
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override Dictionary<string, string> getSysInfo()
|
|
{
|
|
// valore non presente in vers default... se gestito fare override
|
|
Dictionary<string, string> outVal = new Dictionary<string, string>();
|
|
outVal.Add("MACHINE", machineName);
|
|
return outVal;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua vero processing contapezzi
|
|
/// </summary>
|
|
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 false
|
|
string memAddr = getOptPar("PZCOUNT_MODE");
|
|
if (memAddr.StartsWith("STD"))
|
|
{
|
|
// inizio verifica area memoria/parametro levando prima parte codice
|
|
memAddr = memAddr.Replace("STD.", "");
|
|
object outputVal = new object();
|
|
// verifico se si tratta di lettura area DB... formato tipo STD.DB700.DBB22.W
|
|
if (memAddr.StartsWith("DB"))
|
|
{
|
|
memAreaSiemens areaCounter = new memAreaSiemens(memAddr);
|
|
|
|
if (isVerboseLog)
|
|
{
|
|
lgInfo("[0] area memoria: {1}.{2}.{3}", memAddr, areaCounter.DbNum, areaCounter.indiceMem, areaCounter.tipoMem);
|
|
}
|
|
// copio da blocco già letto... con switch x tipo dati --> tipo lettura... e salvo
|
|
// ultimo conteggio rilevato
|
|
switch (areaCounter.tipoMem)
|
|
{
|
|
case "B":
|
|
byte valB = RawInput[areaCounter.indiceMem];
|
|
outputVal = valB;
|
|
break;
|
|
|
|
case "W":
|
|
ushort valW = S7.Net.Types.Word.FromByteArray(RawInput.Skip(areaCounter.indiceMem).Take(2).ToArray());
|
|
outputVal = valW;
|
|
break;
|
|
|
|
case "DW":
|
|
uint valDW = S7.Net.Types.Word.FromByteArray(RawInput.Skip(areaCounter.indiceMem).Take(4).ToArray());
|
|
outputVal = valDW;
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
// salvo...
|
|
Int32.TryParse(outputVal.ToString(), out contapezziPLC);
|
|
if (isVerboseLog)
|
|
{
|
|
lgInfo("[2] outputVal contapezzi: {0}", outputVal);
|
|
lgInfo("[3] contapezziPLC contapezzi: {0}", contapezziPLC);
|
|
}
|
|
}
|
|
stopwatch.Stop();
|
|
}
|
|
#endif
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lgError(exc, "Errore in contapezzi KAWASAKI");
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua processing del recupero delle OVERRIDE (spindle, feedrate, rapid)
|
|
/// </summary>
|
|
public override void processOverride()
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
|
|
/// aggiornare x display in form</paramref>
|
|
/// </summary>
|
|
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
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua reset del contapezzi
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override bool resetContapezziPLC()
|
|
{
|
|
// impiego override metodo set...
|
|
bool answ = setcontapezziPLC(0);
|
|
#if false
|
|
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");
|
|
}
|
|
#endif
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua IMPOSTAZIONE FORZATA del contapezzi
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
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;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Override connessione
|
|
/// </summary>
|
|
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)
|
|
{
|
|
queueInEnabCurr = true;
|
|
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.cncPingAddr));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// se non è ancora connesso faccio processing memoria caso disconnesso...
|
|
if (!connectionOk)
|
|
{
|
|
// processo semafori ed invio...
|
|
processMemoryDiscon();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Override disconnessione
|
|
/// </summary>
|
|
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...");
|
|
}
|
|
queueInEnabCurr = false;
|
|
needRefresh = true;
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Protected Fields
|
|
|
|
/// <summary>
|
|
/// Comando inviato al robot
|
|
/// </summary>
|
|
protected string comando;
|
|
|
|
/// <summary>
|
|
/// Variabile SIGNALS corrente (8bit INT)
|
|
/// </summary>
|
|
protected string cSignals;
|
|
|
|
/// <summary>
|
|
/// Variabile STATUS corrente (8bit INT)
|
|
/// </summary>
|
|
protected string cStatus;
|
|
|
|
/// <summary>
|
|
/// Oggetto MAIN x connessione KAWASAKI
|
|
/// </summary>
|
|
protected KRcc.Commu KAWASAKI_ref;
|
|
|
|
/// <summary>
|
|
/// Ultima missione svolta da robot
|
|
/// </summary>
|
|
protected string lastMissRobot;
|
|
|
|
/// <summary>
|
|
/// Ultimo TC registrato da robot
|
|
/// </summary>
|
|
protected decimal lastRecTC;
|
|
|
|
/// <summary>
|
|
/// Nome e seriale macchina
|
|
/// </summary>
|
|
protected string macName = "";
|
|
|
|
/// <summary>
|
|
/// Num pezzi prelevati
|
|
/// </summary>
|
|
protected int numPzPrel;
|
|
|
|
/// <summary>
|
|
/// Array delle risposte dal controllo KAWASAKI
|
|
/// </summary>
|
|
protected System.Collections.ArrayList resDataArray;
|
|
|
|
/// <summary>
|
|
/// Variabile verifica thread comunicazione
|
|
/// </summary>
|
|
protected bool threadOk = false;
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Properties
|
|
|
|
/// <summary>
|
|
/// Verifica se il thread 4 di comm sia attivo
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 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
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera ultima missione svolta
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Oggetto per lettura ULTIMO TC rilevato
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Recupera nome e seriale macchina
|
|
/// </summary>
|
|
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;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Oggetto per lettura/scrittura counter pezzi robot
|
|
/// </summary>
|
|
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"
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Oggetto per lettura counter pezzi PRELEVATI
|
|
/// </summary>
|
|
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 Protected Methods
|
|
|
|
/// <summary>
|
|
/// Imposto connessione
|
|
/// </summary>
|
|
protected virtual void setConnection()
|
|
{
|
|
// Creo oggetto connessione NC
|
|
parentForm.commPlcActive = true;
|
|
lgInfoStartup("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)
|
|
{
|
|
lgInfoStartup("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();
|
|
// invio altri dati accessori...
|
|
SendMachineConf();
|
|
// 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");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Fields
|
|
|
|
/// <summary>
|
|
/// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO
|
|
/// </summary>
|
|
private Dictionary<string, string> signLUT = new Dictionary<string, string>();
|
|
|
|
#endregion Private Fields
|
|
|
|
#region Private Methods
|
|
|
|
/// <summary>
|
|
/// Decodifica il resto dell'area x i dati accessori (allarmi, ...)
|
|
/// </summary>
|
|
private void decodeOtherData()
|
|
{
|
|
if (verboseLog)
|
|
{
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua decodifica aree memoria alla bitmap usata x MAPO
|
|
/// </summary>
|
|
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}");
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Test completo funzioni kawasaki
|
|
/// </summary>
|
|
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;
|
|
// imposto a 100
|
|
pzCounter = 100;
|
|
// rileggo x verifica
|
|
int newCount = pzCounter;
|
|
// reimposto corretti
|
|
pzCounter = currCount;
|
|
#endif
|
|
// test gest programmi
|
|
#if true
|
|
//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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua salvataggio del programma corrente
|
|
/// </summary>
|
|
/// <param name="progDir">Dir di riferimento</param>
|
|
/// <param name="progName">Nome Programma (se mancasse *.as lo aggiunge)</param>
|
|
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 --> ""
|
|
|
|
//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)
|
|
{
|
|
// Success
|
|
}
|
|
if (ret == -1)
|
|
{
|
|
// Communication error
|
|
}
|
|
if (ret == -2)
|
|
{
|
|
// Robot Controller error
|
|
}
|
|
if (ret == -3)
|
|
{
|
|
// Internal error
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua invio del programma di alvorazione al ROBOT <param name="progDir">Dir di
|
|
/// riferimento</param><param name="progName">Nome Programma (se mancasse *.as lo aggiunge)</param>
|
|
/// </summary>
|
|
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)
|
|
{
|
|
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]
|
|
}
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |