Files
Mapo-IOB-WIN/IOB-WIN-NEXT/IobFanuc.cs
T
2021-12-02 11:19:37 +01:00

1535 lines
65 KiB
C#

using CncLib.CNC;
using IOB_UT_NEXT;
using MapoSDK;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
namespace IOB_WIN_NEXT
{
public class IobFanuc : IobGeneric
{
#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 Protected Fields
/// <summary>
/// Dati dell'area D
/// </summary>
protected memAreaFanuc areaD;
/// <summary>
/// Dati dell'area PARameters
/// </summary>
protected memAreaFanuc areaPAR;
/// <summary>
/// Dati dell'area R
/// </summary>
protected memAreaFanuc areaR;
/// <summary>
/// Dati dell'area X
/// </summary>
protected memAreaFanuc areaX;
/// <summary>
/// Dati dell'area Y
/// </summary>
protected memAreaFanuc areaY;
/// <summary>
/// Oggetto MAIN x connessione FANUC
/// </summary>
protected FANUC FANUC_ref;
/// <summary>
/// Area memoria G (copia)
/// </summary>
protected byte[] MemBlockG = new byte[2];
/// <summary>
/// Area memoria R (copia)
/// </summary>
protected byte[] MemBlockR = new byte[2];
/// <summary>
/// Area memoria X (copia)
/// </summary>
protected byte[] MemBlockX = new byte[2];
/// <summary>
/// Area memoria Y (copia)
/// </summary>
protected byte[] MemBlockY = new byte[2];
#endregion Protected Fields
#region Public Constructors
/// <summary>
/// estende l'init della classe base...
/// </summary>
/// <param name="caller"></param>
/// <param name="adpConf"></param>
public IobFanuc(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf)
{
// i dati RAW principali sono 6 byte...
RawInput = new byte[6];
// gestione invio ritardato contapezzi
pzCountDelay = utils.CRI("pzCountDelay");
lastPzCountSend = DateTime.Now;
lastWarnODL = DateTime.Now;
// inizializzo correttamente aree memoria secondo CONF - iniFileName
IniFile fIni = new IniFile(IOBConf.iniFileName);
// inizializzo aree di memoria correnti...
MemBlockG = new byte[fIni.ReadInteger("MEMORY", "AREAG_SIZE", 8)];
MemBlockR = new byte[fIni.ReadInteger("MEMORY", "AREAR_SIZE", 8)];
MemBlockX = new byte[fIni.ReadInteger("MEMORY", "AREAX_SIZE", 8)];
MemBlockY = new byte[fIni.ReadInteger("MEMORY", "AREAY_SIZE", 8)];
// loggo aree di memoria avviate...
lgInfo(string.Format("Avviare area di memoria MemBlockG: {0} byte", MemBlockG.Length));
lgInfo(string.Format("Avviare area di memoria MemBlockR: {0} byte", MemBlockR.Length));
lgInfo(string.Format("Avviare area di memoria MemBlockX: {0} byte", MemBlockX.Length));
lgInfo(string.Format("Avviare area di memoria MemBlockY: {0} byte", MemBlockY.Length));
// fix enable prgName
enablePrgName = fIni.ReadBoolean("CNC", "GETPRGNAME", true);
// salvo le aree X-Y-D (per dump/sample/ottimizzazione lettura)
areaD = new memAreaFanuc
{
areaName = "AreaD",
startIdx = fIni.ReadInteger("MEMORY", "AREAD_START", 0),
arraySize = fIni.ReadInteger("MEMORY", "AREAD_SIZE", 0)
};
areaPAR = new memAreaFanuc
{
areaName = "AreaPARR",
startIdx = fIni.ReadInteger("MEMORY", "PAR_START", 0),
arraySize = fIni.ReadInteger("MEMORY", "PAR_SIZE", 0)
};
areaR = new memAreaFanuc
{
areaName = "AreaR",
startIdx = fIni.ReadInteger("MEMORY", "AREAR_START", 0),
arraySize = fIni.ReadInteger("MEMORY", "AREAR_SIZE", 0)
};
areaX = new memAreaFanuc
{
areaName = "AreaX",
startIdx = fIni.ReadInteger("MEMORY", "AREAX_START", 0),
arraySize = fIni.ReadInteger("MEMORY", "AREAX_SIZE", 0)
};
areaY = new memAreaFanuc
{
areaName = "AreaY",
startIdx = fIni.ReadInteger("MEMORY", "AREAY_START", 0),
arraySize = fIni.ReadInteger("MEMORY", "AREAY_SIZE", 0)
};
lgInfo(string.Format("Salvata area di memoria: {0}, da {1} per {2} byte", areaD.areaName, areaD.startIdx, areaD.arraySize));
lgInfo(string.Format("Salvata area di memoria: {0}, da {1} per {2} byte", areaR.areaName, areaR.startIdx, areaR.arraySize));
lgInfo(string.Format("Salvata area di memoria: {0}, da {1} per {2} byte", areaX.areaName, areaX.startIdx, areaX.arraySize));
lgInfo(string.Format("Salvata area di memoria: {0}, da {1} per {2} byte", areaY.areaName, areaY.startIdx, areaY.arraySize));
// effettuo lettura della conf sigLUT... cercando 1:1 i bit...
string currBit = "";
string memArea = "";
for (int i = 0; i < 8; i++)
{
currBit = string.Format("BIT{0}", i);
memArea = fIni.ReadString("MEMORY", currBit, "");
// se trovo un valore...
if (!string.IsNullOrEmpty(memArea))
{
signLUT.Add(currBit, memArea);
}
}
// è little endian (NON serve conversione)
hasBigEndian = false;
lgInfo("Start init Adapter FANUC all'IP {0}:{1} per IOB {2}", IOBConf.cncIpAddr, IOBConf.cncPort, IOBConf.codIOB);
// Creo oggetto connessione NC
parentForm.commPlcActive = true;
Runtime.CreateNC(CNC.NcType.FANUC, IOBConf.cncIpAddr, IOBConf.cncPort);
parentForm.commPlcActive = false;
// aggiungo referenza obj FANUC
FANUC_ref = (FANUC)Runtime.NC;
if (isVerboseLog)
{
lgInfo("FANUC_ref da CncLib");
}
// disconnetto e connetto...
if (isVerboseLog)
{
lgInfo("FANUC: tryDisconnect");
}
tryDisconnect();
lgInfo("FANUC: tryConnect");
tryConnect();
if (utils.CRB("enableContapezzi"))
{
lgInfo("FANUC: inizio gestione contapezzi");
try
{
// verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con indicazione area)
if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE")))
{
if (getOptPar("PZCOUNT_MODE").StartsWith("STD"))
{
lgInfo("Init contapezzi FANUC: pzCntReload(true)");
pzCntReload(true);
// refresh associazione Macchina - IOB
sendM2IOB();
// per adesso imposto lettura fanuc == contapezzi (poi farà vera lettura...)
contapezziPLC = contapezziIOB;
}
else
{
contapezziIOB = 0;
lgInfo("Contapezzi STD disabilitato: modalità {0}", getOptPar("PZCOUNT_MODE"));
}
}
else
{
contapezziIOB = 0;
lgInfo("Parametro mancante PZCOUNT_MODE");
}
}
catch (Exception exc)
{
lgError(exc, "Errore in contapezzi FANUC");
}
}
// finisco INIT ADAPTER
lgInfo("End init Adapter FANUC");
}
#endregion Public Constructors
#region Private Methods
/// <summary>
/// Effettua decodifica aree memoria alla bitmap usata x MAPO
/// </summary>
private void decodeToBitmap()
{
// init a zero...
B_input = 0;
if (connectionOk)
{
// SE SI E' CONNESSO al FANUC allora è 1=powerON...
if (FANUC_ref.Connected)
{
B_input += 1 << 0;
}
// decodifico impiegando dictionary... cercando il TIPO di memoria & co...
string bKey = "";
string bVal = "";
char area;
// valore INVERTED (default è false)
bool invSignal = false;
string memArea = "";
string[] memIdx;
int bitNum = 0;
int byteNum = 0;
int byte2check = 0;
for (int i = 0; i < 8; i++)
{
bKey = string.Format("BIT{0}", i);
// cerco se ci sia in LUT
if (signLUT.ContainsKey(bKey))
{
// recupero nome variabile...
bVal = signLUT[bKey];
// se l'area è PZCOUNT... processo PUNTUALMENTE il CONTAPEZZI...
if (bVal.StartsWith("PZCOUNT"))
{
// procedo SOLO SE è enabled IOB
if (IobOnline)
{
try
{
currODL = utils.callUrl(urlGetCurrODL);
// solo SE HO un ODL...
if (string.IsNullOrEmpty(currODL) || currODL == "0")
{
if (periodicLog)
{
lgInfo(string.Format("Fanuc | Lettura ODL andata a vuoto: currODL: {0}", currODL));
}
}
else
{
// se variato o scaduto timeout log...
if (periodicLog || ($"{currIdxODL}" != currODL))
{
lgInfo(string.Format("Fanuc | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL));
}
// provo a salvare nuovo ODL
int.TryParse(currODL, out currIdxODL);
}
}
catch (Exception exc)
{
if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15)
{
lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL);
lastWarnODL = DateTime.Now;
}
}
}
else
{
// imposto currODL a vuoto!
currODL = "";
if (periodicLog)
{
lgInfo($"Fanuc | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto");
}
}
if (!string.IsNullOrEmpty(currODL) && currODL != "0")
{
// controllo se è passato intervallo minimo tra 2 controlli/elaborazioni x distanziare invio e ridurre letture
if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay))
{
// se sono differenti MOSTRO...
if (contapezziPLC != contapezziIOB)
{
// registro contapezzi
lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB {contapezziIOB}");
}
// verifico se variato contapezzi...
if (contapezziPLC > contapezziIOB)
{
// salvo nuovo contapezzi (incremento di 1...) + richiesta refresh conteggio
contapezziIOB++;
needRefreshPzCount = true;
// salvo in semaforo!
B_input += 1 << 2;
// registro contapezzi
lgInfo($"contapezziPLC FANUC: {contapezziPLC} | contapezziIOB {contapezziIOB}");
}
// invio a server contapezzi (aggiornato)
string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString());
// verifica se tutto OK
if (retVal != contapezziIOB.ToString())
{
// errore salvataggio contapezzi
lgInfo($"Errore salvataggio Contapezzi FANUC: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}");
// rileggo il counter pezzi da server
pzCntReload(true);
}
// resetto timer...
lastPzCountSend = DateTime.Now;
}
}
else
{
if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay))
{
lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC FANUC: {contapezziPLC} | contapezziIOB {contapezziIOB}");
// resetto timer...
lastPzCountSend = DateTime.Now;
}
}
}
else // area "normale" byte.bit
{
// di norma è segnale normale => 1, altrimenti inverse => 0...
invSignal = false;
// cerco se sia inverse (ultimo char "!") --> registro e elimino char...
invSignal = bVal.StartsWith("!");
// tolgo comunque inversione...
bVal = bVal.Replace("!", "");
// recupero area...
area = bVal[0];
// altrimenti decodifico area...
memArea = bVal.Substring(1, bVal.Length - 1);
memIdx = memArea.Split('.');
// calcolo bit e byte number...
int.TryParse(memIdx[0], out byteNum);
if (memIdx.Length > 1)
{
int.TryParse(memIdx[1], out bitNum);
}
// in base al nome cerco in una delle aree.. e prendo solo solo quel bit di quel byte...
switch (area)
{
case 'G':
byte2check = MemBlockG[byteNum];
break;
case 'R':
byte2check = MemBlockR[byteNum];
break;
case 'X':
byte2check = MemBlockX[byteNum];
break;
case 'Y':
byte2check = MemBlockY[byteNum];
break;
default:
break;
}
// a secondo che sia segnale normale o inverso...
if (invSignal)
{
// controllo se il bit sia NON attivo (basso)... == 0...
if ((byte2check & (1 << bitNum)) == 0)
{
B_input += 1 << i;
}
}
else
{
// controllo se il bit sia attivo (alto)... != 0
if ((byte2check & (1 << bitNum)) != 0)
{
B_input += 1 << i;
}
}
}
}
}
}
// log opzionale!
if (verboseLog)
{
lgInfo(string.Format("Trasformazione B_input: {0}", B_input));
}
}
/// <summary>
/// Dump area D della memoria
/// </summary>
/// <param name="tipo">tipo di DUMP: START (sovrascrivendo) / SAMPLE (salva tanti campionamenti)</param>
/// <param name="tipoMem">tipo memoria</param>
/// <param name="memIndex">area memoria di partenza</param>
/// <param name="memSizeByte">dimensione memoria</param>
private void dump_MemArea(dumpType tipo, FANUC.MemType tipoMem, int memIndex, int memSizeByte)
{
DateTime adesso = DateTime.Now;
string nomeFileB = "";
string nomeFileW = "";
string nomeFileDW = "";
Dictionary<string, string> mappaValori = new Dictionary<string, string>();
// per sicurezza verifico < 9999 byte
if (memSizeByte > 9999)
{
memSizeByte = 9999;
}
// leggo TUTTI i (MAX 9999) byte della memoria D...
byte[] MemBlockCurr = new byte[memSizeByte];
if (verboseLog)
{
lgInfo("START MemDump", tipoMem);
}
stopwatch.Restart();
FanucMemRW(R, tipoMem, memIndex, ref MemBlockCurr);
if (utils.CRB("recTime"))
{
TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-{1}", MemBlockCurr.Length, tipoMem), stopwatch.ElapsedTicks);
}
if (verboseLog)
{
lgInfo("END MemDump", tipoMem);
}
// seconda del tipo di lettura definisco i nomi delle variabili...
if (tipo == dumpType.SAMPLE)
{
nomeFileB = string.Format(@"{0}\SAMPLES\{1}_{2}_Byte_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem, adesso);
nomeFileW = string.Format(@"{0}\SAMPLES\{1}_{2}_W_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem, adesso);
nomeFileDW = string.Format(@"{0}\SAMPLES\{1}_{2}_DW_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem, adesso);
}
else
{
// salvo in file i dati letti come BYTE
nomeFileB = string.Format(@"{0}\{1}_{2}_Byte.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem);
nomeFileW = string.Format(@"{0}\{1}_{2}_W.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem);
nomeFileDW = string.Format(@"{0}\{1}_{2}_DW.dat", utils.dataDatDir, cIobConf.codIOB, tipoMem);
}
// salvo in file i dati letti come BYTE
mappaValori = new Dictionary<string, string>();
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<string, string>();
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<string, string>();
for (int i = 0; i < MemBlockCurr.Length / 4; i++)
{
mappaValori.Add(i.ToString("0000"), BitConverter.ToUInt32(MemBlockCurr, i * 4).ToString());
}
utils.WritePlain(mappaValori, nomeFileDW);
}
/// <summary>
/// Dump area PARAMETRI
/// </summary>
/// <param name="tipo">tipo di DUMP: START (sovrascrivendo) / SAMPLE (salva tanti campionamenti)</param>
/// <param name="memIndex">Parametro di partenza</param>
/// <param name="numPar">Numero parametri da esportare... memoria</param>
private void dump_ParArea(dumpType tipo, int memIndex, int numPar)
{
DateTime adesso = DateTime.Now;
string nomeFile = "";
Dictionary<string, string> mappaValori = new Dictionary<string, string>();
// per sicurezza verifico < 9999 parametri
if (numPar > 9999)
{
numPar = 9999;
}
// leggo TUTTI i (MAX 9999) byte della memoria D...
object[] paramsArray = new object[numPar];
if (verboseLog)
{
lgInfo("START ParamDump");
}
stopwatch.Restart();
for (int i = 0; i < numPar; i++)
{
FANUC_ref.F_RW_Param_Integer(false, memIndex + i, 3, ref paramsArray[i]);
}
if (utils.CRB("recTime"))
{
TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-PAR", 4 * numPar), stopwatch.ElapsedTicks);
}
if (verboseLog)
{
lgInfo("END ParamDump");
}
// seconda del tipo di lettura definisco i nomi delle variabili...
if (tipo == dumpType.SAMPLE)
{
nomeFile = string.Format(@"{0}\SAMPLES\{1}_{2}_{3:yyyyMMdd_HHmmss}.dat", utils.dataDatDir, cIobConf.codIOB, "PAR", adesso);
}
else
{
nomeFile = string.Format(@"{0}\{1}_{2}.dat", utils.dataDatDir, cIobConf.codIOB, "PAR");
}
// salvo in file i dati letti
mappaValori = new Dictionary<string, string>();
for (int i = 0; i < paramsArray.Length; i++)
{
mappaValori.Add(i.ToString("0000"), paramsArray[i].ToString());
}
utils.WritePlain(mappaValori, nomeFile);
}
/// <summary>
/// Recupera il valore INT dal nome del parametro per successivo processing
/// </summary>
/// <param name="varName"></param>
/// <returns></returns>
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
/// <summary>
/// decodifica il modo dai valori del byte G43
/// </summary>
/// <param name="currVal"></param>
/// <returns></returns>
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
/// <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>();
if (task2exe != null)
{
bool taskOk = false;
string taskVal = "";
// cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4
foreach (var item in task2exe)
{
taskOk = false;
taskVal = "";
// converto richiesta in enum...
taskType tName = taskType.nihil;
Enum.TryParse(item.Key, out tName);
switch (tName)
{
case taskType.nihil:
case taskType.fixStopSetup:
case taskType.forceResetPzCount:
case taskType.forceSetPzCount:
case taskType.setArt:
case taskType.setComm:
case taskType.setProg:
case taskType.sendWatchDogMes2Plc:
taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC";
lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}");
break;
case taskType.startSetup:
// reset contapezzi inizio setup
taskOk = resetcontapezziPLC();
taskVal = taskOk ? "RESET: SETUP START" : "PZ RESET DISABLED | NO EXEC";
lgInfo($"Chiamata startSetup: taskOk: {taskOk} | taskVal: {taskVal}");
break;
case taskType.stopSetup:
// reset contapezzi fine setup SE ESPLICITAMENTE IMPOSTATO
if (cIobConf.optPar.Count > 0 && getOptPar("ENABLE_PZ_RESET_stopSetup") == "TRUE")
{
taskOk = resetcontapezziPLC();
}
taskVal = taskOk ? "RESET: SETUP END" : "PZ RESET DISABLED | NO EXEC";
lgInfo($"Chiamata stopSetup: taskOk: {taskOk} | taskVal: {taskVal}");
break;
default:
taskVal = "SKIPPED | NO EXEC";
lgInfo($"Chiamata default senza processing: taskOk: {taskOk} | taskVal: {taskVal}");
break;
}
// aggiungo task!
taskDone.Add(item.Key, taskVal);
}
}
return taskDone;
}
/// <summary>
/// wrapper chiamata lettura/scrittura SINGOLO BYTE...
/// </summary>
/// <param name="bWrite"></param>
/// <param name="MemType"></param>
/// <param name="memIndex"></param>
/// <param name="Value"></param>
/// <returns></returns>
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;
}
/// <summary>
/// wrapper chiamata lettura/scrittura MULTI BYTE...
/// </summary>
/// <param name="bWrite"></param>
/// <param name="MemType"></param>
/// <param name="memIndex"></param>
/// <param name="MATRICE Value"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Recupero dati dinamici...
/// </summary>
public override Dictionary<string, string> getDynData()
{
Dictionary<string, string> outVal = new Dictionary<string, string>();
// 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;
}
/// <summary>
/// Recupero dati override (da area G che è già stata letta...)
/// </summary>
/// <returns></returns>
public override Dictionary<string, string> getOverrides()
{
Dictionary<string, string> outVal = new Dictionary<string, string>();
// 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;
}
/// <summary>
/// Recupero programma in lavorazione
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// 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
/// </summary>
/// <returns></returns>
public override Dictionary<string, string> getSysInfo()
{
Dictionary<string, string> outVal = new Dictionary<string, string>();
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;
}
/// <summary>
/// Effettua vero processing contapezzi:
/// 6711: pezzi lavorati
/// 6712: pezzi lavorati totali
/// 6713: pezzi richiesti
/// </summary>
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");
}
}
}
/// <summary>
/// Esegue processing MODE (e nel contempo recupera altri dati dell'area G)
/// </summary>
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();
}
}
}
}
}
/// <summary>
/// Recupero altri counters se ci sono
/// </summary>
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");
}
}
/// <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;
// 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;
}
}
/// <summary>
/// Effettua reset del contapezzi
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// Override salvataggio valori in memoria...
/// </summary>
/// <param name="tipo">tipo di DUMP</param>
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);
}
}
/// <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("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;
try
{
// se != null --> uso address...
if (address != null)
{
reply = pingSender.Send(address, 100);
}
else
{
reply = pingSender.Send(cIobConf.cncIpAddr, 100);
}
}
catch
{
reply = pingSender.Send(IPAddress.Loopback, 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();
}
}
/// <summary>
/// Override disconnessione
/// </summary>
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
}
}