Files
CMS-MTConn/MTC_Adapter/SCMA/AdapterOsai.cs
T

1159 lines
40 KiB
C#

using CMSCncLib.CNC;
using MTC;
using SCMA.AdapterCom;
using System;
using System.Collections.Generic;
using System.Text;
namespace SCMA
{
public class AdapterOsai : AdapterGeneric
{
/// <summary>
/// Oggetto MAIN x connessione OSAI
/// </summary>
protected OSAI OSAI_ref;
/// <summary>
/// wrapper chiamata lettura/scrittura OSAI x BYTE...
/// </summary>
/// <param name="bWrite"></param>
/// <param name="MemType"></param>
/// <param name="memIndex"></param>
/// <param name="memOrderStart">0/1 orimo o secondo byte della word...</param>
/// <param name="MATRICE Value"></param>
/// <returns></returns>
public bool OsaiMemRW_Byte(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, Int32 memOrderStart, ref byte[] Value)
{
bool answ = false;
if (OSAI_ref.Connected)
{
try
{
parentForm.commPlcActive = true;
answ = OSAI_ref.O_RW_Byte(bWrite, MemType, memIndex, memOrderStart, ref Value);
}
catch (Exception exc)
{
lg.Error(exc, "Eccezione in OsaiMemRW_Byte");
}
}
parentForm.commPlcActive = false;
return answ;
}
/// <summary>
/// wrapper chiamata lettura/scrittura x WORD...
/// </summary>
/// <param name="bWrite"></param>
/// <param name="MemType"></param>
/// <param name="memIndex"></param>
/// <param name="MATRICE Value"></param>
/// <returns></returns>
public bool OsaiMemRW_Word(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, ref ushort[] Value)
{
bool answ = false;
if (OSAI_ref.Connected)
{
try
{
parentForm.commPlcActive = true;
answ = OSAI_ref.O_RW_Word(bWrite, MemType, memIndex, ref Value);
}
catch (Exception exc)
{
lg.Error(exc, "Eccezione in OsaiMemRW_Word");
}
}
parentForm.commPlcActive = false;
return answ;
}
/// <summary>
/// wrapper chiamata lettura/scrittura x DOUBLE-WORD...
/// </summary>
/// <param name="bWrite"></param>
/// <param name="MemType"></param>
/// <param name="memIndex"></param>
/// <param name="MATRICE Value"></param>
/// <returns></returns>
public bool OsaiMemRW_DWord(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, ref uint[] Value)
{
bool answ = false;
if (OSAI_ref.Connected)
{
try
{
parentForm.commPlcActive = true;
answ = OSAI_ref.O_RW_DWord(bWrite, MemType, memIndex, ref Value);
}
catch (Exception exc)
{
lg.Error(exc, "Eccezione in OsaiMemRW_DWord");
}
}
parentForm.commPlcActive = false;
return answ;
}
/// <summary>
/// wrapper chiamata lettura/scrittura x Short...
/// </summary>
/// <param name="bWrite"></param>
/// <param name="MemType"></param>
/// <param name="memIndex"></param>
/// <param name="MATRICE Value"></param>
/// <returns></returns>
public bool OsaiMemRW_Short(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, ref short[] Value)
{
bool answ = false;
if (OSAI_ref.Connected)
{
try
{
parentForm.commPlcActive = true;
answ = OSAI_ref.O_RW_Short(bWrite, MemType, memIndex, ref Value);
}
catch (Exception exc)
{
lg.Error(exc, "Eccezione in OsaiMemRW_Short");
}
}
parentForm.commPlcActive = false;
return answ;
}
/// <summary>
/// wrapper chiamata lettura/scrittura x INT...
/// </summary>
/// <param name="bWrite"></param>
/// <param name="MemType"></param>
/// <param name="memIndex"></param>
/// <param name="MATRICE Value"></param>
/// <returns></returns>
public bool OsaiMemRW_Integer(bool bWrite, OSAI.MemTypeWord MemType, Int32 memIndex, ref int[] Value)
{
bool answ = false;
if (OSAI_ref.Connected)
{
try
{
parentForm.commPlcActive = true;
answ = OSAI_ref.O_RW_Integer(bWrite, MemType, memIndex, ref Value);
}
catch (Exception exc)
{
lg.Error(exc, "Eccezione in OsaiMemRW_Integer");
}
}
parentForm.commPlcActive = false;
return answ;
}
/// <summary>
/// wrapper chiamata lettura/scrittura x Double...
/// </summary>
/// <param name="bWrite"></param>
/// <param name="MemType"></param>
/// <param name="memIndex"></param>
/// <param name="MATRICE Value"></param>
/// <returns></returns>
public bool OsaiMemRW_Double(bool bWrite, OSAI.MemTypeDouble MemType, Int32 memIndex, ref double[] Value)
{
bool answ = false;
if (OSAI_ref.Connected)
{
try
{
parentForm.commPlcActive = true;
answ = OSAI_ref.O_RW_Double(bWrite, MemType, memIndex, ref Value);
}
catch (Exception exc)
{
lg.Error(exc, "Eccezione in OsaiMemRW_Double");
}
}
parentForm.commPlcActive = false;
return answ;
}
/// <summary>
/// variabile contatore cicli prima di rileggere codici G di un path inattivo...
/// </summary>
public int contChkGCod;
/// <summary>
/// Vettore codici G attivi x PATH 1...
/// </summary>
ushort[] vettGCodes_01;
/// <summary>
/// Vettore codici G attivi x PATH 2...
/// </summary>
ushort[] vettGCodes_02;
/// <summary>
/// struttura dati OSAI x dati NC (pag 148)
/// </summary>
protected CMSCncLib.OPENcontrol.GETINFO1DATA allNcData;
/// <summary>
/// Vettore degli allarmi CNC attivi
/// </summary>
public Dictionary<string, string> allarmiCNC = new Dictionary<string, string>();
/// <summary>
/// estende l'init della classe base...
/// </summary>
/// <param name="caller">FORM chaimante</param>
/// <param name="adpConf">CONFIGURAZIONE adapter</param>
/// <param name="gatewayObj">OGGETTO gestione comunicazione OUT (tipologia e metodi)</param>
public AdapterOsai(MainForm caller, AdapterConf adpConf, Gateway gatewayObj) : base(caller, adpConf, gatewayObj)
{
// !!!HARD CODED!!! aggiunto banco STATUS del 2 processo IN CODA... (4+1)DW=20byte x strobes...!!!
Strobes = new byte[20];
// fix dimensione memorie MST: 52 Byte = 26 short(16bit) x (12+7+7) aree (attenzione: secondo set di 2 bit è VUOTO...)
MemBlock_MST = new byte[52];
// salto necessario!
saltoMST = 1;
// GCodes!
vettGCodes_01 = new ushort[14];
vettGCodes_02 = new ushort[14];
contChkGCod = utils.CRI("contChkGCod");
// è little endian (NON serve conversione)
hasBigEndian = false;
lg.Info("Start init Adapter OSAI all'IP {0}", utils.CRS("ipPLC"));
Runtime.CreateNC(CNC.NcType.OSAI, utils.CRS("ipPLC"));
// inizializzo posizioni assi...
prevPosAxis = new double[adpConf.nAxis];
prevDirAxis = new int[adpConf.nAxis];
parentForm.commPlcActive = true;
OSAI_ref = (OSAI)Runtime.NC;
if (utils.CRB("verbose")) lg.Info(string.Format("Generato oggetto OSAI_ref da CMSCncLib:{0}{1}", Environment.NewLine, OSAI_ref.Descrizione));
parentForm.commPlcActive = false;
// disconnetto e connetto...
if (utils.CRB("verbose")) lg.Info("OSAI: tryDisconnect");
tryDisconnect();
lg.Info("OSAI: tryConnect");
tryConnect();
lg.Info("End init Adapter OSAI");
}
/// <summary>
/// Override disconnessione
/// </summary>
public override void tryDisconnect()
{
if (connectionOk)
{
string szStatusConnection = "";
try
{
parentForm.commPlcActive = true;
OSAI_ref.Disconnect(ref szStatusConnection);
connectionOk = false;
lg.Info(szStatusConnection);
lg.Info("Effettuata disconnessione adapter OSAI!");
}
catch (Exception exc)
{
lg.Fatal(exc, "Errore nella disconnessione dall'adapter OSAI");
}
parentForm.commPlcActive = false;
}
else
{
lg.Error("IMPOSSIBILE effettuare disconnessione: Connessione non disponibile...");
}
}
/// <summary>
/// Override connessione
/// </summary>
public override void tryConnect()
{
if (!connectionOk)
{
string szStatusConnection = "";
try
{
parentForm.commPlcActive = true;
OSAI_ref.Connect(ref szStatusConnection);
lg.Info("szStatusConnection: " + szStatusConnection);
connectionOk = true;
// refresh stato allarmi!!!
if (connectionOk)
{
if (adpRunning)
{
// carico status allarmi (completo)
lg.Info("Inizio refresh completo stato allarmi...");
forceAlarmCheck();
lg.Info("Completato refresh completo stato allarmi!");
}
else
{
lg.Info("Connessione OK");
}
}
else
{
lg.Error("Impossibile procedere, connessione mancante...");
}
}
catch (Exception exc)
{
lg.Fatal(string.Format("Errore nella connessione all'adapter OSAI: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc));
connectionOk = false;
lg.Info(string.Format("Segnalo Adapter NON running, pausa di {0} msec prima di ulteriori tentativi di riconnessione", utils.CRI("waitRecMSec")));
}
parentForm.commPlcActive = false;
}
}
/// <summary>
/// Verifico connessione OSAI...
/// </summary>
/// <returns></returns>
public override bool connectionOk
{
get
{
return OSAI_ref.Connected;
}
}
/// <summary>
/// Effettuo lettura dei 16 byte di strobe/status
/// </summary>
public override void getStrobeAndAckStatus()
{
base.getStrobeAndAckStatus();
if (connectionOk)
{
// leggo TUTTO ack e strobe... in blocco di 16 WORD (32 byte) + altre 2 in coda...
ushort[] MemBlock_A = new ushort[16];
ushort[] MemBlock_B = new ushort[2];
int memIndexA = 19018;
int memIndexB = 19698;
// NB: LEGGO SEMPRE a WORD 16bit (+ veloce...)
// leggo blocco dati + grande...
inizio = DateTime.Now;
OsaiMemRW_Word(R, OSAI.MemTypeWord.MW_CODE, memIndexA, ref MemBlock_A);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R-{0}-W4", MemBlock_A.Length * 2), DateTime.Now.Subtract(inizio).Ticks);
// leggo blocco dati + piccolo
inizio = DateTime.Now;
OsaiMemRW_Word(R, OSAI.MemTypeWord.MW_CODE, memIndexB, ref MemBlock_B);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R-{0}-W1", MemBlock_B.Length * 2), DateTime.Now.Subtract(inizio).Ticks);
// suddivido blocco a blocco... da file di conf x OSAI!!!
// primi 12 byte ad ACK
Buffer.BlockCopy(MemBlock_A, 0, Acknowl, 0, Acknowl.Length - 4);
// altri 4 byte ad ACK blocco secondario
Buffer.BlockCopy(MemBlock_B, 0, Acknowl, Acknowl.Length - 4, 4);
// tutti i 16+4 byte a strobe/status
Buffer.BlockCopy(MemBlock_A, Acknowl.Length - 4, Strobes, 0, Strobes.Length);
}
else
{
lg.Error("Errore connessione mancante in getStrobeAndAckStatus");
}
}
/// <summary>
/// processing strobe!
/// </summary>
public override void processStrobe()
{
// inizializzo userAction
string UserAction = "";
// oggetti "accessori" x processing (1 byte di strobe x ogni path)
StFlag8 currStrobe;
StFlag8 currAck;
// processo ora i dati dei path... di sicuro il primo
currStrobe = (StFlag8)(Strobes[4]); // 5° byte
currAck = (StFlag8)(Acknowl[4]); // 5° byte
procPathStrobes(0, currStrobe, currAck, 19100, 19020, ref UserAction);
//...e se c'è pure il secondo...
if (currAdpConf.nPath > 1)
{
currStrobe = (StFlag8)(Strobes[6]); // 7° byte
currAck = (StFlag8)(Acknowl[6]); // 7° byte
procPathStrobes(1, currStrobe, currAck, 19126, 19021, ref UserAction);
}
// 2017.01.16 INVIO vettore azioni (1 o +)... SE CE NE SONO!
if (UserAction.Trim() != "")
{
mUserAction.ForceChanged();
mUserAction.Value = UserAction.Trim();
}
// verifico strobe dell'auto-test
currStrobe = (StFlag8)(Strobes[7]); // 8° byte
currAck = (StFlag8)(Acknowl[7]); // 8° byte
processTestStrobe(currStrobe, currAck, 19021, 1);
// gestione bit di watchdog... sulal DWord successiva
sendWatchDog();
}
/// <summary>
/// Scrive ACK x dati MST
/// </summary>
/// <param name="idxPath"></param>
/// <param name="memIndexMST"></param>
/// <param name="MemBlock_W"></param>
/// <returns></returns>
public override bool writeMST_ACK(int memIndexAck, ref byte[] currACK_DW)
{
bool fatto = false;
try
{
inizio = DateTime.Now;
fatto = OsaiMemRW_Byte(W, OSAI.MemTypeWord.MW_CODE, memIndexAck, 0, ref currACK_DW);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("W{0}-ACK_DW0", currACK_DW.Length), DateTime.Now.Subtract(inizio).Ticks);
}
catch (Exception exc)
{
lg.Error(string.Format("Errore in scrittura dati ACK MST:{0}{1}", Environment.NewLine, exc));
}
return fatto;
}
/// <summary>
/// Legge area memoria dati MST
/// </summary>
/// <param name="idxPath"></param>
/// <param name="memIndexMST"></param>
/// <param name="MemBlock_MST"></param>
/// <returns></returns>
public override bool readMST_data(int idxPath, int memIndexMST, ref byte[] MemBlock_MST)
{
bool fatto = false;
try
{
// leggo tutto!!!
inizio = DateTime.Now;
fatto = OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndexMST, 0, ref MemBlock_MST);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-STRB_DW1-P{1:00}", MemBlock_MST.Length, idxPath), DateTime.Now.Subtract(inizio).Ticks);
}
catch (Exception exc)
{
lg.Error(string.Format("Errore in lettura dati MST:{0}{1}", Environment.NewLine, exc));
}
return fatto;
}
/// <summary>
/// Scrive watchdog
/// </summary>
/// <param name="retACK_DW"></param>
/// <returns></returns>
public override bool writeWatchDog(ref byte[] retACK_DW)
{
int memIndex = 19022;
return OsaiMemRW_Byte(W, OSAI.MemTypeWord.MW_CODE, memIndex, 0, ref retACK_DW);
}
/// <summary>
/// Effettua lettura dati TESTING
/// </summary>
/// <param name="MemBlockTestData"></param>
/// <returns></returns>
public override bool readTestData(ref uint[] MemBlockTestData)
{
bool fatto = false;
try
{
// leggo tutto!!!
int memIndex = 19700;
inizio = DateTime.Now;
OsaiMemRW_DWord(R, OSAI.MemTypeWord.MW_CODE, memIndex, ref MemBlockTestData);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TEST_DATA", MemBlockTestData.Length), DateTime.Now.Subtract(inizio).Ticks);
fatto = true;
}
catch (Exception exc)
{
lg.Error(string.Format("Errore in lettura dati TEST:{0}{1}", Environment.NewLine, exc));
}
return fatto;
}
/// <summary>
/// Scrive vettore ACK degli allarmi
/// </summary>
/// <param name="retACK_DW0"></param>
/// <returns></returns>
public override bool writeAlarmAck(ref byte[] retACK_DW0)
{
int memIndexAck = 19018;
return OsaiMemRW_Byte(W, OSAI.MemTypeWord.MW_CODE, memIndexAck, 0, ref retACK_DW0);
}
/// <summary>
/// Legge vettore di TUTTE memorie tipo DWord dato vettore memorie (completo)
/// </summary>
/// <param name="MemBlock"></param>
/// <returns></returns>
public override bool readAllAlarms(ref uint[] MemBlock)
{
int memIndex = 19036;
return OsaiMemRW_DWord(R, OSAI.MemTypeWord.MW_CODE, memIndex, ref MemBlock);
}
/// <summary>
/// Legge vettore di TUTTE memorie tipo DWord dato indice di partenza e vettore memorie
/// </summary>
/// <param name="MemBlock"></param>
/// <param name="blockIndex"></param>
/// <returns></returns>
public override bool readAlarmBlock(ref uint[] MemBlock, int blockIndex)
{
int memIndex = 19036;
return OsaiMemRW_DWord(R, OSAI.MemTypeWord.MW_CODE, memIndex + blockIndex * 2, ref MemBlock);
}
#region implementazione processing GlobalData
/// <summary>
/// Legge dati globali...
/// </summary>
public override void readGlobalData()
{
// leggo dati globali...
parentForm.commPlcActive = true;
inizio = DateTime.Now;
OSAI_ref.O_GetNcInfo1(ref allNcData);
if (utils.CRB("recTime")) TimingData.addResult("R-NcInfo", DateTime.Now.Subtract(inizio).Ticks);
parentForm.commPlcActive = false;
// recupero speed e feed...
FeedRate = Convert.ToInt32(allNcData.realfeed);
SpeedRate = Convert.ToInt32(allNcData.realspeed);
}
/// <summary>
/// legge dati override...
/// </summary>
/// <param name="sb1"></param>
/// <returns></returns>
public override bool readOverrides(ref StringBuilder sb1)
{
bool fatto = false;
try
{
// area path1/2: 7 WORD x ogni path...
int memIndex = 19151;
ushort[] PathData_mem = new ushort[14];
inizio = DateTime.Now;
OsaiMemRW_Word(R, OSAI.MemTypeWord.MW_CODE, memIndex, ref PathData_mem);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-PathData", PathData_mem.Length * 2), DateTime.Now.Subtract(inizio).Ticks);
// inizio indicando feed...
sb1.AppendLine(string.Format("FeedRate: {0} mm/min", FeedRate));
sb1.AppendLine(string.Format("SpeedRate: {0} mm/min", SpeedRate));
// 2017.04.20: recupero OVER per Jog/Feed/Rapid/Spindle x i path multipli (qui cablati 1-2)
ushort[] currPathData = new ushort[7];
// processo ora i dai dei path... di sicuro il primo
Array.Copy(PathData_mem, 0, currPathData, 0, 7);
procPathOverride(0, currPathData, ref sb1);
//...e se c'è pure il secondo...
if (currAdpConf.nPath > 1)
{
Array.Copy(PathData_mem, 7, currPathData, 0, 7);
// anche il secondo!
procPathOverride(1, currPathData, ref sb1);
}
fatto = true;
}
catch (Exception exc)
{
lg.Error(exc, "Eccezione in readOverrides");
}
return fatto;
}
/// <summary>
/// processa allarmi CNC...
/// </summary>
public override bool procCncAlarm()
{
bool fatto = false;
try
{
// se ho allarmi li accodo...
if (allNcData.lastncerror != 0)
{
if (utils.CRI("loglevel") > 5)
{
lg.Info(string.Format("Allarmi CNC: {0} ", allNcData.lastncerror));
}
string alarmText = string.Format("CNC Alarm - Cod: {0}", allNcData.lastncerror);
// tolgo eventuali allarmi CNC...
allarmiCNC.Clear();
allarmiCNC.Add(allNcData.lastncerror.ToString(), alarmText);
// 2017.05.09 gestione allarmi commentata
#if false
//-----------------------------------------------------
// PROMO BLOCCO TEST
//-----------------------------------------------------
mAlarmCNC.Add(MTConnect.Condition.Level.FAULT, alarmText, allNcData.lastncerror.ToString(), "", "");
// mostro in form!
sb1.AppendLine(alarmText);
parentForm.dataMonitor_1 += sb1.ToString();
//-----------------------------------------------------
// SECONDO BLOCCO TEST
//-----------------------------------------------------
// il codice è corretto (manca prima aprte codice + traduzione), se cerco di trovare oggett completo NON c'è, verificare con Andrea...
sb1.AppendLine(string.Format("Allarmi CNC: {0}", allNcData.lastncerror));
parentForm.commPlcActive = true;
inizio = DateTime.Now;
OSAI_ref.O_ReadCurrentErrorMsg(ref allarmiCNC);
if (utils.CRB("recTime")) TimingData.addResult("R-CNC-ERROR-MSG", DateTime.Now.Subtract(inizio).Ticks);
parentForm.commPlcActive = false;
checkCNCAlarms();
//-----------------------------------------------------
// TERZO BLOCCO TEST
//-----------------------------------------------------
// provo altri metodi...
parentForm.commPlcActive = true;
CMSCncLib.OPENcontrol.MSGEMERGENCY emergCNC = new CMSCncLib.OPENcontrol.MSGEMERGENCY();
OSAI_ref.O_ReadCurrentEmergMsg(ref emergCNC);
CMSCncLib.OPENcontrol.MSGANOMALY anomCNC = new CMSCncLib.OPENcontrol.MSGANOMALY();
OSAI_ref.O_ReadCurrentAnomalyMsg(ref anomCNC);
parentForm.commPlcActive = false;
#endif
}
else
{
allarmiCNC.Clear();
allarmiCNC = new Dictionary<string, string>();
// 2017.05.09 gestione allarmi commentata
//allarmiCNC = new CMSCncLib.OPENcontrol.MSGERROR();
}
fatto = true;
}
catch (Exception exc)
{
lg.Error(exc, "Eccezione in procCncAlarm");
}
return fatto;
}
/// <summary>
/// Gestione lettura dati manutenzione
/// </summary>
public override bool getMtzDataFromPlc()
{
bool fatto = false;
try
{
if (maintData.Length > 0)
{
// recupero i dati di manutenzione dall'area di memoria IN BLOCCO
int memIndex = 1000;
uint[] tabDatiMtz = new uint[maintData.Length];
inizio = DateTime.Now;
OsaiMemRW_DWord(R, OSAI.MemTypeWord.GW_CODE, memIndex, ref tabDatiMtz);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-DatiMtz", tabDatiMtz.Length * 4), DateTime.Now.Subtract(inizio).Ticks);
// decodifico aree memoria secondo tab configurazione
processMaintData(tabDatiMtz, maintData);
}
fatto = true;
}
catch (Exception exc)
{
lg.Error(string.Format("{0}", exc));
}
return fatto;
}
/// <summary>
/// Gestione lettura dati analogici
/// </summary>
public override bool getAnalogDataFromPlc()
{
bool fatto = false;
try
{
if (analogData.Length > 0)
{
// recupero i dati di manutenzione dall'area di memoria IN BLOCCO
int memIndex = 19434;
uint[] tabDatiAnalog = new uint[analogData.Length];
inizio = DateTime.Now;
OsaiMemRW_DWord(R, OSAI.MemTypeWord.MW_CODE, memIndex, ref tabDatiAnalog);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-DatiAnalog", tabDatiAnalog.Length * 4), DateTime.Now.Subtract(inizio).Ticks);
// decodifico aree memoria secondo tab configurazione
processAnalogData(tabDatiAnalog, analogData);
}
fatto = true;
}
catch (Exception exc)
{
lg.Error(string.Format("{0}", exc));
}
return fatto;
}
/// <summary>
/// Gestione lettura dati status da PLC
/// </summary>
public override bool getStatusDataFromPlc()
{
bool fatto = false;
try
{
if (statusData.Length > 0)
{
// recupero i dati di manutenzione dall'area di memoria IN BLOCCO
int memIndex = 19426;
int numByte = 1 + (statusData.Length / 8);
byte[] tabDatiStatus = new byte[numByte];
inizio = DateTime.Now;
OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, 0, ref tabDatiStatus);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-DatiStatus", tabDatiStatus.Length), DateTime.Now.Subtract(inizio).Ticks);
// decodifico aree memoria secondo tab configurazione
processStatusData(tabDatiStatus, statusData);
}
fatto = true;
}
catch (Exception exc)
{
lg.Error(string.Format("{0}", exc));
}
return fatto;
}
#endregion
/// <summary>
/// Carico file conf dati CMS
/// </summary>
protected override void loadOtherFile()
{
base.loadOtherFile();
//loadMaintData("MW", 19166, 2);
loadMaintData("GL", 500, 1);
loadStatusData("M", 19426, 1);
//loadAnalogData("ML", 19434, 2);
loadAnalogData("ML", 9717, 1);
}
/// <summary>
/// Processing allarmi CNC
/// </summary>
public override void processAlarm()
{
base.processAlarm();
// aggiungo gestione allarmi CNC
checkCNCAlarms();
}
/// <summary>
/// Verifica i 10 allarmi CNC SE presenti
/// </summary>
private void checkCNCAlarms()
{
if (allarmiCNC != null)
{
sendAlarmIfPresent(allarmiCNC);
}
}
/// <summary>
/// Invia singolo allarme CNC se presente (da dictionary)
/// </summary>
/// <param name="allarmi"></param>
protected void sendAlarmIfPresent(Dictionary<string, string> allarmi)
{
// controllo valore...
if (allarmi != null && allarmi.Count > 0)
{
try
{
StringBuilder sb = new StringBuilder();
foreach (KeyValuePair<string, string> item in allarmi)
{
string alarmText = string.Format("{0} - {1}", item.Key, item.Value);
if (utils.CRI("loglevel") > 5)
{
lg.Info(string.Format("Allarme CNC: {0}", alarmText));
}
mAlarmCNC.Add(MTConnect.Condition.Level.FAULT, alarmText, item.Key, "", "");
// mostro in form!
sb.AppendLine(alarmText);
}
parentForm.dataMonitor_1 += sb.ToString();
}
catch (Exception exc)
{
lg.Error(string.Format("{0}", exc));
}
}
}
/// <summary>
/// Recupero dati x UnOp
/// </summary>
public override void getUnOp()
{
// leggo in blocco tutte le speed da memoria...
int memIndex = 2950;
// buffer memoria 60 byte... speed (16bit 2 * 20) + load (8bit 1 * 20) visto che sono 20 teste max
byte[] unOpSpeedMem = new byte[60];
ushort[] unOpSpeedMemW = new ushort[30];
inizio = DateTime.Now;
OsaiMemRW_Word(R, OSAI.MemTypeWord.MW_CODE, memIndex, ref unOpSpeedMemW);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-SPEED_UNOP", unOpSpeedMem.Length), DateTime.Now.Subtract(inizio).Ticks);
// travaso in modalità byte...
Buffer.BlockCopy(unOpSpeedMemW, 0, unOpSpeedMem, 0, unOpSpeedMem.Length);
procUnOp(unOpSpeedMem);
}
/// <summary>
/// Procedura di processing lettura memoria x DatiUt - Step 4
/// </summary>
/// <param name="int32Mem"></param>
/// <param name="j"></param>
/// <returns></returns>
public override int getDatiUt_step4(ref byte[] int32Mem, int j)
{
int memIndex = 6200 + 2 * j;
inizio = DateTime.Now;
OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, 0, ref int32Mem);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-VitaRes", int32Mem.Length), DateTime.Now.Subtract(inizio).Ticks);
return memIndex;
}
/// <summary>
/// Procedura di processing lettura memoria x DatiUt - Step 3b
/// </summary>
/// <param name="int8Mem"></param>
/// <param name="j"></param>
/// <returns></returns>
public override int getDatiUt_step3b(ref byte int8Mem, int j)
{
int memIndex = 5000 + 1 * j / 2; // dovrebeb leggere correttamente solo 1 byte...
byte[] byteMtrx = new byte[1];
int resto = 0;
Math.DivRem(j, 2, out resto);
inizio = DateTime.Now;
OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, resto, ref byteMtrx);
int8Mem = byteMtrx[0];
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-FamUT", 8), DateTime.Now.Subtract(inizio).Ticks);
return memIndex;
}
/// <summary>
/// Procedura di processing lettura memoria x DatiUt - Step 3a
/// </summary>
/// <param name="tabFam_FamUt"></param>
/// <returns></returns>
public override int getDatiUt_step3a(ref byte[] tabFam_FamUt)
{
int memIndex = 4100;
inizio = DateTime.Now;
OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, 0, ref tabFam_FamUt);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabFamUT-FamUT", tabFam_FamUt.Length), DateTime.Now.Subtract(inizio).Ticks);
return memIndex;
}
/// <summary>
/// Procedura di processing lettura memoria x DatiUt - Step 2b
/// </summary>
/// <param name="int16Mem"></param>
/// <param name="j"></param>
/// <returns></returns>
public override int getDatiUt_step2b(ref byte[] int16Mem, int j)
{
int memIndex = 5500 + j;
inizio = DateTime.Now;
OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, 0, ref int16Mem);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-FamUT", int16Mem.Length), DateTime.Now.Subtract(inizio).Ticks);
return memIndex;
}
/// <summary>
/// Procedura di processing lettura memoria x DatiUt - Step 2a
/// </summary>
/// <param name="tabUt_UT"></param>
/// <returns></returns>
public override int getDatiUt_step2a(ref byte[] tabUt_UT)
{
int memIndex = 5300;
inizio = DateTime.Now;
OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, 0, ref tabUt_UT);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-TabUT-UT", tabUt_UT.Length), DateTime.Now.Subtract(inizio).Ticks);
return memIndex;
}
/// <summary>
/// Procedura di processing lettura memoria x DatiUt - Step 1
/// </summary>
/// <param name="elencoUtMem"></param>
/// <returns></returns>
public override int getDatiUt_step1(ref byte[] elencoUtMem)
{
int memIndex = 3020;
inizio = DateTime.Now;
OsaiMemRW_Byte(R, OSAI.MemTypeWord.MW_CODE, memIndex, 0, ref elencoUtMem);
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-NUMUT", elencoUtMem.Length), DateTime.Now.Subtract(inizio).Ticks);
return memIndex;
}
public override void getPath()
{
// NON ci sono nella documentazione metodi x recuperare posizione PuntaUtensile, in attesa news da OSAI/Andrea...
// ciclo su path
StringBuilder sb_2;
StringBuilder sb_3;
ushort[] vettGCodes;
// faccio VERA lettura SOLO ogni TOT cicli...
if (contChkGCod <= 0)
{
// reimposto contatore
contChkGCod = utils.CRI("contChkGCod");
// recupero vettore generale G MODE
parentForm.commPlcActive = true;
inizio = DateTime.Now;
OSAI_ref.getPathGCodeMod(1, ref vettGCodes_01);
if (currAdpConf.nPath > 1)
{
OSAI_ref.getPathGCodeMod(2, ref vettGCodes_02);
}
if (utils.CRB("recTime")) TimingData.addResult("R-GCodModal", DateTime.Now.Subtract(inizio).Ticks);
parentForm.commPlcActive = false;
}
else
{
contChkGCod--;
}
for (int i = 0; i < currAdpConf.nPath; i++)
{
// accodo dati path in DataMonitor...
sb_2 = new StringBuilder();
sb_3 = new StringBuilder();
// attenzione: il vettore contiene come campi "vuoti" il valore MAX di USHort (16bit) ovvero 2^16 -1 (base 0) --> 65535
string GCodAttivi = "";
vettGCodes = i == 0 ? vettGCodes_01 : vettGCodes_02;
for (int j = 0; j < vettGCodes.Length; j++)
{
// se il valore è < di UShort.max (65535)...
if (vettGCodes[j] < ushort.MaxValue)
{
GCodAttivi += string.Format("[G{0}]", vettGCodes[j]);
}
}
vettPath[i].mPathCodG_Act.Value = GCodAttivi;
// 2017.01.16 da rivedere
vettPath[i].mPathCurrProgRowNum.Value = "";
vettPath[i].mPathActiveAxes.Value = "";
sb_2.AppendLine(string.Format("Path {0}, PROG: {1}", i + 1, vettPath[i].mPathCurrProg.Value));
sb_3.AppendLine(string.Format("Path {0}, GCodes: {1}", i + 1, GCodAttivi));
parentForm.dataMonitor_2 += sb_2.ToString();
parentForm.dataMonitor_3 += sb_3.ToString();
}
}
public override void getAxis()
{
// mostro assi in DataMonitor......
StringBuilder sb = new StringBuilder();
parentForm.commPlcActive = true;
inizio = DateTime.Now;
/*------------------------------------------------------------------------
* 2018.01.16 modifica per gestione doppio processo e nome assi duplicato
* ------------------------------------------------------------------------
*
* E' risultato (marco.negri, amcchian OSAI con 2 processi in cui glia ssi di ogni processoa vevano lo stesso nome) ceh OSAI NON restituisce ID univoco asse ma nome etichetta asegnato
* in questo modo glia ssi verso agent (e seguenti) si sovrappongono/sovrascrivono
*
* E' quindi necessario procedere in + step
* - verificare numero processia ttivi
* - chiedere x ogni processo quali assi ci siano (AsixTable (con Id UNIVOCO e consistente e NOME)
* - chiedere x ogni processo le posizioni assi in modo che processo + nome --> Id Univoco --> possiamo popolare la tabella da invaire poi all'agent
*/
// inizializzo x numero assi...
CMSCncLib.OPENcontrol.GETINTDATA[] tmpPosAssiTgt = new CMSCncLib.OPENcontrol.GETINTDATA[currAdpConf.nAxis];
CMSCncLib.OPENcontrol.GETINTDATA[] tmpPosAssi = new CMSCncLib.OPENcontrol.GETINTDATA[currAdpConf.nAxis];
CMSCncLib.OPENcontrol.GETINTDATA[] posAssiTgt = new CMSCncLib.OPENcontrol.GETINTDATA[currAdpConf.nAxis];
CMSCncLib.OPENcontrol.GETINTDATA[] posAssi = new CMSCncLib.OPENcontrol.GETINTDATA[currAdpConf.nAxis];
Dictionary<string, int> axisDict = new Dictionary<string, int>();
char[] axisTable = new char[currAdpConf.nAxis];
short[] axisIdTable = new short[currAdpConf.nAxis];
int currId = 0;
// verifico quanti path ho... e recupero le info sugli assi (se id > 0 è PRESENTE...)
for (short i = 1; i <= currAdpConf.nPath; i++)
{
axisTable = new char[currAdpConf.nAxis];
axisIdTable = new short[currAdpConf.nAxis];
// chiamo lettura tab assi
OSAI_ref.O_GetAxisTab(i, ref axisTable, ref axisIdTable);
//...e popolo i dati...
for (int j = 0; j < currAdpConf.nAxis; j++)
{
// recupero Id...
currId = axisIdTable[j];
// controllo se id > 0...
if (currId > 0)
{
// salvo!!! come path#nome
axisDict.Add(string.Format("{0}#{1}", i, axisTable[j]), currId);
// se conf di leggere nome/path asse..
if (utils.CRB("enableAxNamePath"))
{
// solo se HO UN NOME valido x asse...
if (axisTable[j] != '-' && axisTable[j] != '\0')
{
try
{
// salvo (per ID) descr asse e processo corrente!
vettAxis[currId - 1].mAxDescr.Value = axisTable[j];
vettAxis[currId - 1].mAxMainProc.Value = i;
}
catch (Exception exc)
{
lg.Error(exc, string.Format("Eccezione in salvataggio nome/path asse num {0}", currId));
}
}
}
}
}
}
char axName;
int reIdx = 0;
// ora processo i dati PER PATH delle posizioni assi...
for (short i = 1; i <= currAdpConf.nPath; i++)
{
tmpPosAssiTgt = new CMSCncLib.OPENcontrol.GETINTDATA[currAdpConf.nAxis];
tmpPosAssi = new CMSCncLib.OPENcontrol.GETINTDATA[currAdpConf.nAxis];
OSAI_ref.getAllAxisPos(1, i, ref tmpPosAssiTgt);
OSAI_ref.getAllAxisPos(2, i, ref tmpPosAssi);
// decodifico e salvo in posizione corretta...
for (int j = 0; j < currAdpConf.nAxis; j++)
{
// per sicurezza try-catch
try
{
if (tmpPosAssiTgt[j].AxisName == 0)
{
axName = '-';
}
else
{
axName = Convert.ToChar(tmpPosAssiTgt[j].AxisName);
}
// salvo nella posizione DECODIFICATA da dictionary x path/nome...
if (axName != '\0' && axName != '-')
{
// calcolo ID REALE
reIdx = axisDict[string.Format("{0}#{1}", i, axName)];
posAssiTgt[reIdx - 1] = tmpPosAssiTgt[j];
posAssi[reIdx - 1] = tmpPosAssi[j];
}
}
catch
{ }
}
}
// nuova posizione (per calcoli)
double newPos = 0;
double newPosTgt = 0;
double distPerc = 0;
int newDir = 0;
string tipoAsse = "";
string direzione = "";
// ORA ho tutto in posizione corretta, PROCESSO!!!
for (int i = 0; i < currAdpConf.nAxis; i++)
{
// per sicurezza try-catch
try
{
//string axName = System.Text.Encoding.ASCII.GetString(posAssi[i].AxisName);
if (posAssiTgt[i].AxisName == 0)
{
axName = '-';
}
else
{
axName = Convert.ToChar(posAssiTgt[i].AxisName);
}
// controllo nome asse: se vuoto NON PROCESSARE
if (axName != '\0' && axName != '-')
{
newPos = posAssi[i].position;
newPosTgt = posAssiTgt[i].position;
}
else
{
newPos = 0;
newPosTgt = 0;
}
// popolo valori... LOAD gestito da vettore letto con area memoria AnalogData.map
vettAxis[i].mAxLoad.Value = Convert.ToUInt32(istLoadAssi[i].vcMedian);
vettAxis[i].mAxPosAct.Value = newPos;
vettAxis[i].mAxPosTgt.Value = newPosTgt;
vettAxis[i].mAxFeedAct.Value = FeedRate;
// calcolo distanza e salvo valore...
distPerc = newPos - prevPosAxis[i];
// sistemo direzione +/- (POS/NEG se lineari, CCW/CW se rotativi)
if (distPerc != 0)
{
newDir = Convert.ToInt32(distPerc / Math.Abs(distPerc));
}
else
{
newDir = prevDirAxis[i];
}
// verifico tipo direzione da tipo asse...
tipoAsse = vettAxis[i].mAxType.Value.ToString();
if (tipoAsse == "LINEAR")
{
// ?: conditional operator.
direzione = (newDir > 0) ? "POSITIVE" : "NEGATIVE";
}
else if (tipoAsse == "ROTARY")
{
direzione = (newDir > 0) ? "CLOCKWISE" : "COUNTER_CLOCKWISE";
}
vettAxis[i].mAxDir.Value = direzione;
if (utils.CRB("verbose"))
{
sb.AppendLine(string.Format("Asse {0}: PosAct:{1:N3} | Prg:{2:N3} | Load:{3:N1} | {4}", axName, newPos, newPosTgt, vettAxis[i].mAxLoad.Value, direzione));
}
// salvo valori vettore prec...
prevPosAxis[i] = newPos;
prevDirAxis[i] = newDir;
vettAxis[i].mAxFeedOver.Value = FeedRateOver;
}
catch
{
lg.Error(string.Format("Errore in lettura asse {0}", i));
}
}
// salvo timing!
if (utils.CRB("recTime")) TimingData.addResult("R-AXIS_POS", DateTime.Now.Subtract(inizio).Ticks);
parentForm.commPlcActive = false;
parentForm.dataMonitor_3 += sb.ToString();
}
}
}