Files
CMS-MTConn/MTC_Adapter/MTC_Adapter/AdapterESA.cs
T
2017-03-08 22:33:48 +01:00

1132 lines
45 KiB
C#
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using System;
using System.Linq;
using System.Text;
using SCMCncLib;
using System.Windows.Forms;
using System.Threading;
using System.IO;
using System.Collections.Generic;
namespace MTC_Adapter
{
public class AdapterESA : AdapterGeneric
{
#if false
// vettore valori in file interscambio
public Dictionary<string, string> generalStatus;
#endif
/// <summary>
/// Configurazione valori da leggere IOT_Byte
/// </summary>
public otherData[] mapIOT_Byte;
/// <summary>
/// Configurazione valori da leggere IOT_Word
/// </summary>
public otherData[] mapIOT_Word;
/// <summary>
/// Configurazione valori da leggere IOT_DWord
/// </summary>
public otherData[] mapIOT_DWord;
/// <summary>
/// Configurazione valori da leggere IOT_String
/// </summary>
public otherData[] mapIOT_String;
/// <summary>
/// variabile globale x usare IOT MEMORY (!!! da eliminare alla fine dei test)
/// </summary>
protected bool useIotMem = true;
/// <summary>
/// Carico file conf dati IOT
/// </summary>
protected override void loadOtherFile()
{
base.loadOtherFile();
loadByteListMap();
loadWordListMap();
loadDWordListMap();
loadStringListMap();
}
/// <summary>
/// Carico conf vettore dati STRING
/// </summary>
private void loadStringListMap()
{
loadConfFile(ref mapIOT_String, filePath("IOTStringFilePath"), 1);
}
/// <summary>
/// Carico conf vettore dati DWORD
/// </summary>
private void loadDWordListMap()
{
loadConfFile(ref mapIOT_DWord, filePath("IOTDWordFilePath"), 1);
}
/// <summary>
/// Carico conf vettore dati WORD
/// </summary>
private void loadWordListMap()
{
loadConfFile(ref mapIOT_Word, filePath("IOTWordFilePath"), 1);
}
/// <summary>
/// Carico conf vettore dati BYTE
/// </summary>
private void loadByteListMap()
{
loadConfFile(ref mapIOT_Byte, filePath("IOTByteFilePath"), 1);
}
/// <summary>
/// Restituisce path completo file da chaive configurazione
/// </summary>
/// <param name="keyFile">chaive conf x file richiesto</param>
/// <returns></returns>
protected string filePath(string keyFile)
{
return string.Format(@"{0}\{1}", utils.confDir, utils.CRS(keyFile));
}
/// <summary>
/// Legge il file di conf di una MAP di informazioni da gestire con lettura set memoria
/// </summary>
/// <param name="vettoreConf">nome vettore memoria</param>
/// <param name="nomeFile">file origine</param>
/// <param name="memSize">dimensione (in byte) della memoria</param>
protected void loadConfFile(ref otherData[] vettoreConf, string nomeFile, int memSize)
{
//// carico dati x Maintenance
//if (utils.CRB("verbose")) lg.Info("Inizio caricamento vettore mappa " + nomeFile);
int totRighe = 0;
string linea;
totRighe = File.ReadLines(nomeFile).Count();
// creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco...
vettoreConf = new otherData[File.ReadLines(nomeFile).Count()];
// carica da file...
System.IO.StreamReader file = new System.IO.StreamReader(nomeFile);
// leggo 1 linea alla volta...
int numRiga = 0;
int bitNum = 0;
int byteNum = 0;
while ((linea = file.ReadLine()) != null)
{
// SE non è un commento...
if (linea.Substring(0, 1) != "#")
{
// se finisce per BIT allora processo bit-a-bit...
if (linea.EndsWith("BIT"))
{
try
{
string[] memIdx = linea.Split(utils.CRC("testCharSep"))[0].Split('.');
// calcolo bit e byte number...
int.TryParse(memIdx[0], out byteNum);
if (memIdx.Length > 1)
{
int.TryParse(memIdx[1], out bitNum);
}
else
{
bitNum = 0;
}
}
catch
{
byteNum = 0;
bitNum = 0;
}
vettoreConf[numRiga] = decodeBitData(linea, utils.CRC("testCharSep"), "", byteNum, 1, bitNum);
}
else
{
//int.TryParse(linea.Split(utils.CRC("testCharSep"))[0], out byteNum);
vettoreConf[numRiga] = decodeOtherData(linea, utils.CRC("testCharSep"), "", 1, memSize);
}
numRiga++;
}
}
// chiudo file
file.Close();
// ora trimmo vettore al solo numero VERO dei valori caricati...
Array.Resize<otherData>(ref vettoreConf, numRiga);
if (utils.CRB("verbose")) lg.Info(string.Format("Fine caricamento vettore di {0} variabili per file {1}", numRiga, nomeFile));
}
/// <summary>
/// oggetto onnessione ESA
/// </summary>
protected thdNcEsaGvKvara ncDevice;
/// <summary>
/// thread del processo comunicazione esa
/// </summary>
protected Thread thdDevice;
/// <summary>
/// estende l'init della classe base...
/// </summary>
/// <param name="caller"></param>
/// <param name="adpConf"></param>
public AdapterESA(MainForm caller, AdapterConf adpConf) : base(caller, adpConf)
{
string iniPath = string.Format(@"{0}\{1}", utils.confDir, utils.CRS("defaultEsaFile"));
lg.Info("Start init Adapter ESA dal file {0}", iniPath);
IniFiles.IniFile EsaIni = new IniFiles.IniFile(iniPath);
if (utils.CRB("verbose")) lg.Info("step 01: impostato INI File {0}", iniPath);
loadOtherFile();
ncDevice = new thdNcEsaGvKvara(EsaIni, mapIOT_Byte.Length, mapIOT_Word.Length, mapIOT_DWord.Length, mapIOT_String.Length);
if (utils.CRB("verbose")) lg.Info("step 02: avviato thdNcEsaGvKvara da INI File {0}", iniPath);
// inizializzo posizioni assi...
prevPosAxis = new double[adpConf.nAxis];
prevDirAxis = new int[adpConf.nAxis];
// verifica avvio...
lg.Info("ESA: tryConnect");
tryConnect();
lg.Info("End init Adapter ESA");
}
public override void tryDisconnect()
{
base.tryDisconnect();
// disconnetto
ncDevice.Disconnect();
connectionOk = false;
}
public override void tryConnect()
{
base.tryConnect();
// se non già connesso provo a connettermi...
if (!ncDevice.Connected)
{
// provo a collegarmi
if (!ncDevice.Connect())
{
//altrimenti disconnette...
ncDevice.Disconnect();
connectionOk = false;
}
else
{
connectionOk = true;
}
}
}
/// <summary>
/// Verifico connessione ESA...
/// </summary>
/// <returns></returns>
public override bool connectionOk
{
get
{
return ncDevice.Connected;
}
}
/// <summary>
/// Carica ed acquisisce dati del buffer Byte (8 bit) di memoria
/// </summary>
protected void getIotMem_Byte()
{
// HARD CODE: forzo path 1 (indice 0...)
int idxPath = 0;
// accodo dati path in DataMonitor......
StringBuilder sb = new StringBuilder();
if (connectionOk)
{
// leggo TUTTO il blocco di memoria
inizio = DateTime.Now;
ncDevice.ReadBufferByte();
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-PLC_IOT-Byte", ncDevice.PLC_MemoryAreaIOT_Byte.Length), DateTime.Now.Subtract(inizio).Ticks);
}
else
{
lg.Error("Errore connessione mancante in getIotMem_Byte");
}
// Processing area BYTE
int numero = 0;
string status = "";
int bitNum = 0;
int byteNum = 0;
byte currByte;
for (int i = 0; i < mapIOT_Byte.Length; i++)
{
// gestisco in primis le variabili BIT
if (mapIOT_Byte[i].dataType == "BIT")
{
string[] memIdx = mapIOT_Byte[i].memAddr.Split('.');
// calcolo bit e byte number...
int.TryParse(memIdx[0], out byteNum);
if (memIdx.Length > 1)
{
int.TryParse(memIdx[1], out bitNum);
}
// leggo byte...
currByte = ncDevice.PLC_MemoryAreaIOT_Byte[byteNum];
if (mapIOT_Byte[i].varName == "IOT_EXEC")
{
if (((StFlag8)currByte).HasFlag((StFlag8)Math.Pow(2, bitNum)))
{
vettPath[idxPath].mPathExeMode.Value = "RUN";
// !!!FARE per ora prendo ANCHE poweron...
mPower.Value = "ON";
}
else
{
vettPath[idxPath].mPathExeMode.Value = "READY";
// !!!FARE per ora prendo ANCHE poweron...
mPower.Value = "OFF";
}
}
else if (mapIOT_Byte[i].varName == "IOT_HOLD")
{
if (((StFlag8)currByte).HasFlag((StFlag8)Math.Pow(2, bitNum))) //(ncDevice.PLC_MemoryAreaIOT_Byte[byteNum] != 0)
{
vettPath[idxPath].mPathExeMode.Value = "FEED_HOLD"; //"FEEDHOLD";
}
}
else if (mapIOT_Byte[i].varName == "IOT_EMG")
{
// 2017.03.07 controllo bit emergenza...
if (((StFlag8)currByte).HasFlag((StFlag8)Math.Pow(2, bitNum))) //(ncDevice.PLC_MemoryAreaIOT_Byte[byteNum] != 0)
{
mEStop.Value = "TRIGGERED";
}
else
{
mEStop.Value = "ARMED";
}
}
else if (mapIOT_Byte[i].varName == "IOT_ALRM")
{
if (((StFlag8)currByte).HasFlag((StFlag8)Math.Pow(2, bitNum))) //(ncDevice.PLC_MemoryAreaIOT_Byte[byteNum] != 0)
{
// carico IN BLOCCO memoria allarmi...
// FARE!!!
}
}
}
// vado poi a gestire le variabili BYTE
else if (mapIOT_Byte[i].dataType == "BYTE")
{
int.TryParse(mapIOT_Byte[i].memAddr, out byteNum);
if (mapIOT_Byte[i].varName == "IOT_OVRF")
{
// -------------------------------------------
// recupero dati FeedOverride
// FeedOver: 100% = 213 (il pannello è 0-120 --> 0-255, quindi 100% è 100/120*255=213)
FeedRateOver = Convert.ToInt16((decimal)(ncDevice.PLC_MemoryAreaIOT_Byte[byteNum] * 100) / 213);
sb.AppendLine(string.Format("FeedRateOver: {0} %", FeedRateOver));
}
else if (mapIOT_Byte[i].varName == "IOT_OVRS")
{
// -------------------------------------------
// recupero dati SpeedOverride
// SpeedOver: 50% = 128
SpeedRateOver = Convert.ToInt16((decimal)(ncDevice.PLC_MemoryAreaIOT_Byte[byteNum] * 100) / 255);
sb.AppendLine(string.Format("SpeedRateOver: {0} %", SpeedRateOver));
}
else if (mapIOT_Byte[i].varName.StartsWith("IOT_LUB_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_Byte[i].varName.Replace("IOT_LUB_", "").Replace("_Status", ""));
}
catch
{
// se non trovo --> 1!
numero = 1;
}
if (mapIOT_Byte[i].varName.EndsWith("_STA"))
{
if (ncDevice.PLC_MemoryAreaIOT_Byte[byteNum] != 0)
{
status = "EMPTY";
}
else
{
status = "OK";
}
vettLubro[numero - 1].mLubroStatus.Value = status;
}
else if (mapIOT_Byte[i].varName.EndsWith("_CNT"))
{
vettLubro[numero - 1].mLubroNum.Value = ncDevice.PLC_MemoryAreaIOT_Byte[i];
}
}
else if (mapIOT_Byte[i].varName.StartsWith("IOT_I_MD_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_Byte[i].varName.Replace("IOT_I_MD_", ""));
}
catch
{
// se non trovo --> 1!
numero = 1;
}
// salvo in vettore carico mandrini
try
{
vettUnOp[numero - 1].mUnOpLoad.Value = ncDevice.PLC_MemoryAreaIOT_Byte[i];
}
catch
{ }
}
else if (mapIOT_Byte[i].varName.StartsWith("IOT_PGMR_A_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_Byte[i].varName.Replace("IOT_I_MD_", ""));
}
catch
{
// se non trovo --> 1!
numero = 1;
}
//// salvo in vettore carico mandrini
//try
//{
// vettUnOp[numero - 1].mUnOpLoad.Value = ncDevice.PLC_MemoryAreaIOT_Byte[i];
//}
//catch
//{ }
}
}
}
parentForm.dataMonitor += sb.ToString();
}
/// <summary>
/// Carica ed acquisisce dati del buffer WORD (16 bit) di memoria
/// </summary>
protected void getIotMem_Word()
{
if (connectionOk)
{
// leggo TUTTO il blocco di memoria
inizio = DateTime.Now;
ncDevice.ReadBufferWord();
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-PLC_IOT-Word", ncDevice.PLC_MemoryAreaIOT_Word.Length), DateTime.Now.Subtract(inizio).Ticks);
}
else
{
lg.Error("Errore connessione mancante in getIotMem_Word");
}
int numero = 0;
int byteNum = 0;
// Processing area WORD
for (int i = 0; i < mapIOT_Word.Length; i++)
{
int.TryParse(mapIOT_Word[i].memAddr, out byteNum);
if (mapIOT_Word[i].varName.StartsWith("IOT_S_MD_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_Word[i].varName.Replace("IOT_S_MD_", ""));
vettUnOp[numero - 1].mUnOpSpeed.Value = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
}
catch
{
// se non trovo --> 1!
numero = 1;
}
}
else if (mapIOT_Word[i].varName.StartsWith("IOT_T_MD_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_Word[i].varName.Replace("IOT_T_MD_", ""));
vettUnOp[numero - 1].mUnOpToolId.Value = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
}
catch
{
// se non trovo --> 1!
numero = 1;
}
}
else if (mapIOT_Word[i].varName.StartsWith("IOT_C_H_VAC_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_Word[i].varName.Replace("IOT_C_H_VAC_", ""));
vettVacAct[numero - 1].mVacActCount.Value = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
}
catch
{
// se non trovo --> 1!
numero = 1;
}
}
else if (mapIOT_Word[i].varName.StartsWith("IOT_C_TC_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_Word[i].varName.Replace("IOT_C_TC_", ""));
vettUnOp[numero - 1].mUnOpNumCU.Value = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
}
catch
{
// se non trovo --> 1!
numero = 1;
}
}
else if (mapIOT_Word[i].varName.StartsWith("IOT_C_H_MD_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_Word[i].varName.Replace("IOT_C_H_MD_", ""));
vettUnOp[numero - 1].mUnOpAccTime.Value = ncDevice.PLC_MemoryAreaIOT_Word[byteNum];
}
catch
{
// se non trovo --> 1!
numero = 1;
}
}
}
}
/// <summary>
/// Carica ed acquisisce dati del buffer DWORD (32 bit) di memoria
/// </summary>
protected void getIotMem_DWord()
{
if (connectionOk)
{
// leggo TUTTO il blocco di memoria
inizio = DateTime.Now;
ncDevice.ReadBufferDWord();
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R{0}-PLC_IOT-DWord", ncDevice.PLC_MemoryAreaIOT_DWord.Length), DateTime.Now.Subtract(inizio).Ticks);
}
else
{
lg.Error("Errore connessione mancante in getIotMem_DWord");
}
int numero = 0;
int byteNum = 0;
double valDouble = 0;
// Processing area WORD
for (int i = 0; i < mapIOT_DWord.Length; i++)
{
int.TryParse(mapIOT_DWord[i].memAddr, out byteNum);
if (mapIOT_DWord[i].varName.StartsWith("IOT_C_KU_AX_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_DWord[i].varName.Replace("IOT_C_KU_AX_", ""));
vettAxis[numero - 1].mAxDistDone.Value = ncDevice.PLC_MemoryAreaIOT_DWord[byteNum];
}
catch
{
// se non trovo --> 1!
numero = 1;
}
}
else if (mapIOT_DWord[i].varName.StartsWith("IOT_C_KINV_AX_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_DWord[i].varName.Replace("IOT_C_KINV_AX_", ""));
vettAxis[numero - 1].mAxInvDDone.Value = ncDevice.PLC_MemoryAreaIOT_DWord[byteNum];
}
catch
{
// se non trovo --> 1!
numero = 1;
}
}
else if (mapIOT_DWord[i].varName.StartsWith("IOT_POS_AX_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_DWord[i].varName.Replace("IOT_POS_AX_", ""));
// recupero valore pos assi (in micron)
valDouble = (double)BitConverter.ToInt32(BitConverter.GetBytes(ncDevice.PLC_MemoryAreaIOT_DWord[byteNum]), 0);
// riporto il dato in mm (divido x 1000)
vettAxis[numero - 1].mAxPosAct.Value = valDouble / utils.CRI("fattdecimale");
}
catch
{
// se non trovo --> 1!
numero = 1;
}
}
else if (mapIOT_DWord[i].varName.StartsWith("IOT_C_KREV_MD_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_DWord[i].varName.Replace("IOT_C_KREV_MD_", ""));
vettUnOp[numero - 1].mUnOpKRev.Value = ncDevice.PLC_MemoryAreaIOT_DWord[byteNum];
}
catch
{
// se non trovo --> 1!
numero = 1;
}
}
else if (mapIOT_DWord[i].varName.StartsWith("IOT_PLC_MSG_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_DWord[i].varName.Replace("IOT_PLC_MSG_", ""));
// copio allarmi in vettore generale AlarmFlags (dove lo gestisce) 4 byte alla volta
Buffer.BlockCopy(BitConverter.GetBytes(ncDevice.PLC_MemoryAreaIOT_DWord[byteNum]), 0, AlarmFlags, numero * 4, 4);
}
catch
{
// se non trovo --> 1!
numero = 1;
}
}
else if (mapIOT_DWord[i].varName.StartsWith("IOT_C_EXEC_A_"))
{
// recupero NUMERO
try
{
numero = Convert.ToInt32(mapIOT_DWord[i].varName.Replace("IOT_C_EXEC_A_", ""));
//vettAxis[numero - 1].mAxInvDDone.Value = ncDevice.PLC_MemoryAreaIOT_DWord[byteNum];
// FARE!!!! nuovo oggetto ed area x programmi caricati in area...
//mMessage.Code = mapIOT_DWord[i].varName;
//mMessage.Value = ncDevice.PLC_MemoryAreaIOT_DWord[byteNum];
}
catch
{
// se non trovo --> 1!
numero = 1;
}
}
}
}
public override void getGlobalData()
{
base.getGlobalData();
// 2017.03.07 IN BLOCCO processo TUTTI i valori della memoria WORD/DWORD...
if (useIotMem)
{
processAllMemory();
}
else
{
// accodo dati path in DataMonitor......
StringBuilder sb = new StringBuilder();
if (connectionOk)
{
// leggo TUTTO il blocco di memoria
inizio = DateTime.Now;
ncDevice.ReadBuffer();
if (utils.CRB("recTime")) TimingData.addResult(string.Format("R-PLC_FullMemoryRead", ncDevice.PLC_MemoryRead.Length), DateTime.Now.Subtract(inizio).Ticks);
}
else
{
lg.Error("Errore connessione mancante in getGlobalData");
}
// dati override feed/speed...
Byte v82 = ncDevice.PLC_MemoryAreaV[14];
Byte v83 = ncDevice.PLC_MemoryAreaV[15];
// 2 byte x speed da copiare...
byte[] tmpByte = new byte[2];
Buffer.BlockCopy(ncDevice.PLC_MemoryAreaV, 16, tmpByte, 0, 2);
short v84 = BitConverter.ToInt16(tmpByte, 0);
// lista allarmi PLC/CNC
Byte v87 = ncDevice.PLC_MemoryAreaV[19]; // Allarme CN (almeno 1?!?)
// -------------------------------------------
// recupero dati Feed/Speed/override
// FeedOver: 100% = 213 (il pannello è 0-120 --> 0-255, quindi 100% è 100/120*255=213)
FeedRateOver = Convert.ToInt16((decimal)(v82 * 100) / 213);
sb.AppendLine(string.Format("FeedRateOver: {0} %", FeedRateOver));
// SpeedOver: 50% = 128
SpeedRateOver = Convert.ToInt16((decimal)(v83 * 100) / 255);
sb.AppendLine(string.Format("SpeedRateOver: {0} %", SpeedRateOver));
// Speed S5000 OK!!!
SpeedRate = v84;
sb.AppendLine(string.Format("SpeedRate: {0} rpm", SpeedRate));
// -------------------------------------------
// da recuperare da qualche parte?!?
UnOpLoad = 0;
sb.AppendLine(string.Format("Load: {0}", UnOpLoad));
// -------------------------------------------
// recupero dati dai contatori EOK
bool needSave = false;
// ore totali accensione
int MinMaccOn = (int)ncDevice.PLC_MemoryAreaEOK[0];
int OreMaccOn = (int)ncDevice.PLC_MemoryAreaEOK[1];
istOreMaccOn = OreMaccOn + (double)MinMaccOn / 60;
needSave = procOreMaccOn(needSave);
// ore totali lavoro
int MinMaccLav = (int)ncDevice.PLC_MemoryAreaEOK[2];
int OreMaccLav = (int)ncDevice.PLC_MemoryAreaEOK[3];
istOreMaccLav = OreMaccLav + (double)MinMaccLav / 60;
needSave = procOreMaccLav(needSave);
// giri totali degli elettromandrini!
for (int i = 0; i < currAdpConf.nUnOp; i++)
{
istGiriElettrom[i] = (uint)ncDevice.PLC_MemoryAreaEOK[4 + i];
}
needSave = procGiriTotUnOp(needSave);
needSave = procNumCU(needSave);
// per ESA calcolo a mano se ci sia stato impiego assi... salvo le istantanee mov precedenti...
double precVal = 0;
DateTime adesso = DateTime.Now;
TimeSpan accumTime = adesso.Subtract(lastChekAccumTimeAxis);
// spostamento totale assi!
for (int i = 0; i < 3; i++)
{
precVal = istDistMovAssi[i];
// primo è metri, secondo km (moltiplico x 1000)
istDistMovAssi[i] = ncDevice.PLC_MemoryAreaEOK[8 + 2 * i] + ncDevice.PLC_MemoryAreaEOK[9 + 2 * i] * 1000;
// verifico SE devo aggiungere tempo lavoro sui singoli assi (se si sono spostati...) -- è a maglie LARGHE poiché leggiamo lo "scatto ogni metro" x cui se campiono velocemente ma assi muovono lenti prendo MENO tempo di movimento del reale...
if (precVal != istDistMovAssi[i])
{
istAccTimeAssi[i] += accumTime.TotalHours;
}
}
// salvo valore lastChekAccumTimeAxis
lastChekAccumTimeAxis = adesso;
needSave = procMovTotAssi(needSave);
needSave = procAccTimeAssi(needSave);
needSave = procProgrName(needSave);
needSave = procPartId(needSave);
needSave = procPzProd(needSave);
needSave = procNumInvAssi(needSave);
needSave = procVacPump(needSave);
needSave = procVacAct(needSave);
needSave = procLubro(needSave);
// salvo se necessario!
if (needSave) parentForm.persistData();
// -------------------------------------------
// copio allarmi in vettore generale AlarFlags (dove lo gestisce)...
Buffer.BlockCopy(ncDevice.PLC_MemoryAreaAllarmi, 0, AlarmFlags, 0, ncDevice.PLC_MemoryAreaAllarmi.Length);
parentForm.dataMonitor = sb.ToString();
}
}
/// <summary>
/// Path percorso file prod
/// </summary>
protected string ScmProdFileName
{
get
{
return string.Format(@"{0}\{1}", utils.confDir, utils.CRS("ScmProdFile"));
}
}
/// <summary>
/// Oggetto elenco dati produzione
/// </summary>
public datiProdSCM[] elencoDatiProd;
/// <summary>
/// leggo altri file:
/// - dati produzione
/// </summary>
public override void getSlowChangingData()
{
base.getSlowChangingData();
// carico dati x Maintenance
if (utils.CRB("verbose")) lg.Info(string.Format("Inizio caricamento file dati produzione ({0})", ScmProdFileName));
int totRighe = 0;
string linea;
// controllo se file esista, altrimenti loggo errore!
if (!File.Exists(ScmProdFileName))
{
lg.Error(string.Format("ATTENZIONE! file dati produzione ({0}) non trovato!", ScmProdFileName));
}
else
{
totRighe = File.ReadLines(ScmProdFileName).Count();
// creo un vettore della dimensione corretta... conta anche commenti tanto poi riduco...
datiProdSCM[] elencoDatiProdNew = new datiProdSCM[File.ReadLines(ScmProdFileName).Count()];
// carica da file...
System.IO.StreamReader file = new System.IO.StreamReader(ScmProdFileName);
// leggo 1 linea alla volta...
int rumRiga = 0;
while ((linea = file.ReadLine()) != null)
{
// SE non è un valore totale... lungh > 50 e 22 virgole (23 valori)
if (linea.Length > 50)
{
// comma separated!
elencoDatiProdNew[rumRiga] = decodeScmProdLine(linea, ',');
// se !=null conto!
if (elencoDatiProdNew != null) rumRiga++;
}
}
// chiudo file
file.Close();
// ora trimmo vettore al solo numero VERO degli allarmi caricati...
Array.Resize<datiProdSCM>(ref elencoDatiProdNew, rumRiga);
/*--------------------------------------------------
* Gestione verifica dati prod (naive)
* - se file curr vuoto --> inizio a popolare
* - se i 2 file hanno stessa lunghezza --> verifico + update last row
* - se nNew > nCurr --> accodo
* - se nCurr > nNew e nNew ==0 --> aggiorno last row giorno prec
* - se nCurr > nNew e nNew > 0 --> svuoto file curr e riparto
*--------------------------------------------------*/
// verifica preliminare dati da lung vettori
int nRecCur = 0;
int nRecIst = 0;
if (elencoDatiProd != null)
{
try
{
nRecCur = elencoDatiProd.Length;
}
catch
{ }
}
if (elencoDatiProdNew != null)
{
try
{
nRecIst = elencoDatiProdNew.Length;
}
catch
{ }
}
// uso un INT x delta qta da sommare...
int deltaQta = 0;
// in primis devo verificare che sia > 0 num oggetti su entrambi i vettori
if (nRecCur + nRecIst > 0)
{
// verifico se ho meno valori CURR e quindi devo accodare
if (nRecCur < nRecIst)
{
// resize vettore!
Array.Resize<datiProdSCM>(ref elencoDatiProd, nRecCur + 1);
// carico nuovo record
elencoDatiProd[nRecCur] = elencoDatiProdNew[nRecCur];
deltaQta = elencoDatiProd[nRecCur].qta;
nRecCur++;
}
else if (nRecCur == nRecIst)
{
// devo confrontare ULTIMO record Curr con equivalente record NEW x verificare se sia variato.. verifico PRG + start
bool checkName = elencoDatiProd[nRecCur - 1].fileName == elencoDatiProdNew[nRecCur - 1].fileName;
bool checkStart = elencoDatiProd[nRecCur - 1].start == elencoDatiProdNew[nRecCur - 1].start;
if (checkName && checkStart)
{
// salvo se variata quantità...
deltaQta = elencoDatiProdNew[nRecCur - 1].qta - elencoDatiProd[nRecCur - 1].qta;
elencoDatiProd[nRecCur - 1] = elencoDatiProdNew[nRecCur - 1];
}
}
else
{
// inizio svuotando elenco eventi CURR (migliorabile leggendo da data prec?!?)
elencoDatiProd = null;
nRecCur = 0;
}
// riporto comunque ultima riga del vettore CURR (sia perché variato sia perché aggiunto)
if (nRecCur > 0)
{
string prgName = elencoDatiProd[nRecCur - 1].fileName;
prgName = prgName.Substring(prgName.LastIndexOf(@"\") + 1);
// se il mio articolo NON cambia...
if (istPathPartId[0] == prgName)
{
istPathPartCount[0] += (uint)deltaQta;
}
else
{
istPathPartId[0] = prgName;
// 2016.07.27 riporto puntualmente qta nuovo record...
istPathPartCount[0] = (uint)deltaQta;
// old sostituito
//istPathPartCount[0] = Convert.ToUInt32(elencoDatiProd[nRecCur - 1].qta);
}
}
}
}
}
/// <summary>
/// Processing di TUTTA l'area di memoria configurata e delle variabili derivate...
/// </summary>
public override void processAllMemory()
{
//!!!FARE!!! completare e validare parti commentate...
// inizializzo data monitor su FORM
parentForm.dataMonitor = "";
// recupero le varie memorie
getIotMem_Byte();
getIotMem_Word();
getIotMem_DWord();
//getIotMem_String();
// processo componenti specifici x info...
//getUnOp();
//getPath();
getAxis();
// !!!FARE verifica...
//getConfigParam();
////acquisisco dati su programma in esecuzione e dati generali (stato, orologio, power...)
//getSlowChangingData();
}
/// <summary>
/// Processo stti macchina...
/// </summary>
public override void processStatus()
{
// HARD CODE: forzo path 1 (indice 0...)
int idxPath = 0;
// accodo dati path in DataMonitor......
StringBuilder sb = new StringBuilder();
// 2017.03.07 IN BLOCCO processo TUTTI i valori della memoria BYTE...
if (useIotMem)
{
processAllMemory();
}
else
{
// verifica macchina accesa...
Byte V73 = ncDevice.PLC_MemoryAreaV[5];
if (((StFlag8)V73).HasFlag(StFlag8.B2))
{
mPower.Value = "ON";
}
else
{
mPower.Value = "OFF";
}
// switch su EXE mode...
/*
* MODO_X V[70/71] --> byte (2-3)
* V70.2 = Modo RUN 
* V70.3 = Modo FeedHold
* V71.5 = Ready
* */
Byte V70 = ncDevice.PLC_MemoryAreaV[2];
Byte V71 = ncDevice.PLC_MemoryAreaV[3];
if (((StFlag8)V70).HasFlag(StFlag8.B3))
{
vettPath[idxPath].mPathExeMode.Value = "FEED_HOLD"; //"FEEDHOLD";
}
else if (((StFlag8)V70).HasFlag(StFlag8.B2))
{
vettPath[idxPath].mPathExeMode.Value = "ACTIVE";
}
else if (((StFlag8)V71).HasFlag(StFlag8.B5))
{
vettPath[idxPath].mPathExeMode.Value = "READY";
}
//// appunto: modi da creare
//STOPPED/HOLD(da creare)
//INTERRUPTED(da creare)
//OPTIONAL_STOP(da creare)
//PROGRAM_STOPPED(da creare)
//PROGRAM_COMPLETED(da creare)
// switch su run mode...
/*
* MODO_X V[74].W --> byte (6)
* 0 = Modo NESSUNO 
* 1 = Modo MANUALE 
* 2 = Modo AUTOMATICO 
* 3 = Modo POM 
* 4 = Modo MDI 
* 5 = Modo SEMIAUTOMATICO 
* 6 = Modo RAP 
* 7 = Modo TES
* */
uint V74 = ncDevice.PLC_MemoryAreaV[6];
switch (V74)
{
case 1:
vettPath[idxPath].mPathRunMode.Value = "EDIT";
break;
case 2:
vettPath[idxPath].mPathRunMode.Value = "AUTOMATIC";
break;
case 3:
vettPath[idxPath].mPathRunMode.Value = "MANUAL";
break;
case 4:
vettPath[idxPath].mPathRunMode.Value = "MANUAL_DATA_INPUT";
break;
case 5:
vettPath[idxPath].mPathRunMode.Value = "SEMI_AUTOMATIC"; //"SEMIAUTO";
break;
case 6:
vettPath[idxPath].mPathRunMode.Value = "MANUAL"; //"RAP";
break;
case 7:
vettPath[idxPath].mPathRunMode.Value = "MANUAL"; //"TES";
break;
case 0:
default:
vettPath[idxPath].mPathRunMode.Value = "NA";
break;
}
}
//parentForm.dataMonitor = sb.ToString();
}
/// <summary>
/// Recupera la speed override x i mandrini (UnOp)
/// </summary>
public override void getUnOp()
{
// cicl su UnOp
for (int i = 0; i < currAdpConf.nUnOp; i++)
{
vettUnOp[i].mUnOpSpeedOverr.Value = SpeedRateOver;
}
}
/// <summary>
/// Carica info accessorie assi (direzione, feed, ...)
/// </summary>
public override void getAxis()
{
// mostro assi in DataMonitor......
StringBuilder sb = new StringBuilder();
// nuova posizione (per calcoli)
double newPos = 0;
double distPerc = 0;
int newDir = 0;
string tipoAsse = "";
string direzione = "";
// leggo in modo "cablato" i dati dei vari assi...
for (int i = 0; i < currAdpConf.nAxis; i++)
{
vettAxis[i].mAxFeedAct.Value = FeedRate;
// calcolo distanza e salvo valore...
newPos = Convert.ToDouble(vettAxis[i].mAxPosAct.Value);
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;
// se la direzione è variata salvo il cambio direzione...
if (newDir != prevDirAxis[i])
{
// salvo "+1" come cambi direzione
istNumInvAssi[i]++;
}
if (utils.CRB("verbose"))
{
sb.AppendLine(string.Format("Asse {0}: PosAct:{1:N3}, | {2}", i, (double)(newPos), direzione));
}
// salvo valori vettore prec...
prevPosAxis[i] = newPos;
prevDirAxis[i] = newDir;
}
parentForm.dataMonitor += sb.ToString();
}
#if false
public override void processAlarm()
{
base.processAlarm();
if (!useIotMem)
{
// ora controllo "allarmi speciali" se si sono...
if (AlarmFlags != null)
{
// variabili helper
StFlag32 AlarmBlock = 0;
int eStopCode = utils.CRI("eStopCode") - 1; // è base zero memoria, ma allarmi base 1...
int memStart = (int)Math.Floor((double)eStopCode / 8);
// leggo 32bit alla volta...
AlarmBlock = (StFlag32)BitConverter.ToUInt32(AlarmFlags, memStart);
int eStopIndex = eStopCode - memStart * 8;
// converto! e aggiungo allarmi sollevati al corretto controller allarmi...
if (AlarmBlock.HasFlag((StFlag32)Math.Pow(2, eStopIndex)))
{
mEStop.Value = "TRIGGERED";
}
else
{
mEStop.Value = "ARMED";
}
}
}
}
#endif
}
}