8bb0f158b5
- proj di base con le 2 form da ereditare - progetto globale che contiene TUTTI gli adapter (pronto a venire spezzettato - gettate le basi x "portare fuori" i vari componenti oppure fare compilazione condizonale
923 lines
36 KiB
C#
923 lines
36 KiB
C#
using IOB_UT_NEXT;
|
|
using MapoSDK;
|
|
using Newtonsoft.Json;
|
|
using System;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Text.RegularExpressions;
|
|
using System.Threading;
|
|
using System.Windows.Forms;
|
|
|
|
namespace IOB_WIN_NEXT.IobFile
|
|
{
|
|
public class FileEurom63 : IobFile.FileGen
|
|
{
|
|
#region Public Constructors
|
|
|
|
/// <summary>
|
|
/// Estende l'init della classe base...
|
|
/// </summary>
|
|
/// <param name="caller"></param>
|
|
/// <param name="adpConf"></param>
|
|
public FileEurom63(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf)
|
|
{
|
|
lgInfo("INIT IobFileEurom63");
|
|
appPath = Path.GetDirectoryName(Application.ExecutablePath);
|
|
|
|
string MAX_DELAY_SEC = getOptPar("MAX_DELAY_SEC");
|
|
string CACHE_MULT = getOptPar("CACHE_MULT");
|
|
int.TryParse(MAX_DELAY_SEC, out maxDelaySec);
|
|
int.TryParse(CACHE_MULT, out cacheMult);
|
|
|
|
#if DEBUG
|
|
maxDelaySec = 60 * 60 * 24;
|
|
#endif
|
|
}
|
|
|
|
#endregion Public Constructors
|
|
|
|
#region Public Methods
|
|
|
|
/// <summary>
|
|
/// Effettua vero processing contapezzi
|
|
/// </summary>
|
|
public override void processContapezzi()
|
|
{
|
|
if (utils.CRB("enableContapezzi"))
|
|
{
|
|
try
|
|
{
|
|
// controllo se sono in sampling della produzione
|
|
if (actLevel >= Eurom63.ComLevel.ProdRequested)
|
|
{
|
|
/************************************************************
|
|
*
|
|
* EXAMPLE
|
|
* DATE, TIME, ActCntCyc, ActTimCyc, ActTimFill, @OutXhour, SetDescJob
|
|
* 20201007, 21:29:52, 5302, 8.61, 0.50, 10058, Nr. 1000987654.01
|
|
*
|
|
* devo prendere il 3° valore
|
|
*
|
|
*
|
|
************************************************************/
|
|
|
|
// leggo il file della produzione HARD CODED...
|
|
var sessProd = confE63.ActiveSessions[5];
|
|
string currPzCount = "";
|
|
if (sessProd != null)
|
|
{
|
|
if (sessProd.Active)
|
|
{
|
|
// nome file...
|
|
string fileName = $"{BaseDir}\\{sessProd.SessionName}.DAT";
|
|
if (File.Exists(fileName))
|
|
{
|
|
string rawData = "";
|
|
using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
using (var textReader = new StreamReader(fileStream))
|
|
{
|
|
rawData = textReader.ReadToEnd();
|
|
}
|
|
// ora splitto in linee
|
|
string[] rawLines = Regex.Split(rawData, "\r\n|\r|\n");
|
|
int numRow = rawLines.Length;
|
|
|
|
// devo avere almeno 2 righe...
|
|
if (numRow >= 2)
|
|
{
|
|
string[] statusData = rawLines[1].Split(',');
|
|
currPzCount = statusData[2].Trim();
|
|
// salvo se valido
|
|
if (!string.IsNullOrEmpty(currPzCount))
|
|
{
|
|
int newVal = -1;
|
|
Int32.TryParse(currPzCount, out newVal);
|
|
// verifico SE il contapezzi vada moltiplicato x il
|
|
// fattore pzPallet...
|
|
if (confE63.PzPallet > 1)
|
|
{
|
|
newVal = newVal * confE63.PzPallet;
|
|
}
|
|
// aggiorno contapezzi
|
|
contapezziPLC = newVal > -1 ? newVal : contapezziPLC;
|
|
}
|
|
// ora verifico SE siano validi anche le dataora dei valori
|
|
// letti (< 20 sec ritardo da ora...)
|
|
string data = statusData[0].Trim();
|
|
string ora = statusData[1].Trim();
|
|
DateTime adesso = DateTime.Now;
|
|
DateTime lastPub = adesso.AddMinutes(-1);
|
|
CultureInfo provider = CultureInfo.InvariantCulture;
|
|
try
|
|
{
|
|
lastPub = DateTime.ParseExact($"{data} {ora}", "yyyyMMdd HH:mm:ss", provider);
|
|
}
|
|
catch
|
|
{ }
|
|
if (Math.Abs(lastPub.Subtract(adesso).TotalSeconds) > maxDelaySec)
|
|
{
|
|
sessProd.SessionValidUntil = adesso;
|
|
// elimino file RSP...
|
|
cleanupResp(sessProd.SessionName);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
actLevel = Eurom63.ComLevel.StatusRequested;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
actLevel = Eurom63.ComLevel.StatusRequested;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lgError($"Eccezione in processContapezzi:{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <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);
|
|
// in primis controllo status...
|
|
checkCommStatus();
|
|
|
|
// init a zero...
|
|
B_input = 0;
|
|
string currStatus = "99999";
|
|
bool readDone = false;
|
|
DateTime adesso = DateTime.Now;
|
|
// leggo il file dela produzione HARD CODED...
|
|
var sessStatus = confE63.ActiveSessions[4];
|
|
// ciclo!
|
|
try
|
|
{
|
|
// controllo se sono in sampling dello stato
|
|
if (actLevel >= Eurom63.ComLevel.StatusRequested)
|
|
{
|
|
/* -----------------------------------------------------
|
|
* bitmap MAPO
|
|
* B0: POWER_ON
|
|
* B1: RUN
|
|
* B2: pzCount
|
|
* B3: allarme
|
|
* B4: manuale
|
|
* B5: allarme TCiclo (SLOW)
|
|
* B6: avvio/spegnimento
|
|
* B7: Emergenza armata (1= pronto, 0 = emergenza) --> DA INVIARE!!!
|
|
----------------------------------------------------- */
|
|
|
|
/******************************************************************
|
|
*
|
|
* EXAMPLE file content
|
|
* DATE, TIME, ActStsMach
|
|
* 20201007, 21:28:10, 0A000
|
|
*
|
|
* Configurazione array status: 5 char status decoding
|
|
*
|
|
* Pos1: (status)
|
|
* 0: poweron
|
|
* 1: poweroff
|
|
*
|
|
* Pos2: (mode)
|
|
* A: AUTO
|
|
* S: SEMI auto
|
|
* M: Manual
|
|
* U: Setup
|
|
* H: Hord
|
|
* C: Maintenance
|
|
* 0: Unknown
|
|
* I: Idle
|
|
*
|
|
* Pos3: (assist call)
|
|
* 0: No assistance
|
|
* 2: Assistance required
|
|
*
|
|
* Pos4: (Bad part)
|
|
* 0: last cycle not bad
|
|
* 1: last cycle bad
|
|
*
|
|
* Pos5: Active Alarm
|
|
* 0: No alarm
|
|
* 1: Alarm
|
|
*
|
|
*
|
|
*
|
|
*******************************************************************/
|
|
|
|
if (sessStatus != null)
|
|
{
|
|
if (sessStatus.Active)
|
|
{
|
|
// nome file...
|
|
string fileName = $"{BaseDir}\\{sessStatus.SessionName}.DAT";
|
|
if (File.Exists(fileName))
|
|
{
|
|
string rawData = "";
|
|
using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
using (var textReader = new StreamReader(fileStream))
|
|
{
|
|
rawData = textReader.ReadToEnd();
|
|
}
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
// ora splitto in linee
|
|
string[] rawLines = Regex.Split(rawData, "\r\n|\r|\n");
|
|
int numRow = rawLines.Length;
|
|
|
|
// devo avere almeno 2 righe...
|
|
if (numRow >= 2)
|
|
{
|
|
string[] statusData = rawLines[1].Split(',');
|
|
if (statusData.Length >= 3)
|
|
{
|
|
currStatus = statusData[2].Trim();
|
|
if (!string.IsNullOrEmpty(currStatus))
|
|
{
|
|
currDispData.semIn = Semaforo.SV;
|
|
}
|
|
// salvo in cache!
|
|
Last_CurrStatus.Value = currStatus;
|
|
Last_CurrStatus.ValidUntil = DateTime.Now.AddSeconds(maxDelaySec * cacheMult);
|
|
|
|
// ora verifico SE siano validi anche le dataora dei
|
|
// valori letti (< 20 sec ritardo da ora...)
|
|
string data = statusData[0].Trim();
|
|
string ora = statusData[1].Trim();
|
|
DateTime lastPub = adesso.AddMinutes(-1);
|
|
CultureInfo provider = CultureInfo.InvariantCulture;
|
|
try
|
|
{
|
|
lastPub = DateTime.ParseExact($"{data} {ora}", "yyyyMMdd HH:mm:ss", provider);
|
|
}
|
|
catch
|
|
{ }
|
|
if (Math.Abs(lastPub.Subtract(adesso).TotalSeconds) > maxDelaySec)
|
|
{
|
|
sessStatus.SessionValidUntil = adesso;
|
|
// elimino file RSP...
|
|
cleanupResp(sessStatus.SessionName);
|
|
}
|
|
readDone = true;
|
|
}
|
|
else
|
|
{
|
|
lgError($"Decodifica StatusData in errore: trovati {statusData.Length} campi in {rawLines}");
|
|
// se valido RILEGGO ultimo curr status
|
|
if (Last_CurrStatus.ValidUntil > adesso)
|
|
{
|
|
currStatus = Last_CurrStatus.Value;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lgError($"Lettura file stato in errore: trovate {numRow} linee");
|
|
}
|
|
}
|
|
// se valido RILEGGO ultimo curr status
|
|
if (Last_CurrStatus.ValidUntil > adesso)
|
|
{
|
|
currStatus = Last_CurrStatus.Value;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// se valido RILEGGO ultimo curr status
|
|
if (Last_CurrStatus.ValidUntil > adesso)
|
|
{
|
|
currStatus = Last_CurrStatus.Value;
|
|
}
|
|
// abbasso status...
|
|
actLevel--;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// se valido RILEGGO ultimo curr status
|
|
if (Last_CurrStatus.ValidUntil > adesso)
|
|
{
|
|
currStatus = Last_CurrStatus.Value;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// se valido RILEGGO ultimo curr status
|
|
if (Last_CurrStatus.ValidUntil > adesso)
|
|
{
|
|
currStatus = Last_CurrStatus.Value;
|
|
}
|
|
}
|
|
|
|
// processo il currentStatus... parto da poweron
|
|
B_input = currStatus[0] == '1' ? 0 : 1;
|
|
|
|
// aggiungo il bit NON emergenza
|
|
B_input += (1 << 7);
|
|
|
|
// ora MODE
|
|
switch (currStatus[1])
|
|
{
|
|
case 'A':
|
|
B_input += (1 << 1);
|
|
break;
|
|
|
|
case 'S':
|
|
case 'M':
|
|
case 'U':
|
|
B_input += (1 << 4);
|
|
break;
|
|
|
|
default:
|
|
// loggo cosa trovo (CREDO
|
|
break;
|
|
}
|
|
// ora cerco allarmi
|
|
if (currStatus[4] == '1')
|
|
{
|
|
B_input += (1 << 3);
|
|
}
|
|
// controllo se diverso faccio log!
|
|
if (!B_input.Equals(Last_B_Input.Value))
|
|
{
|
|
lgInfo($"B_Input variato: {Last_B_Input.Value} --> {B_input} | currStatus: {currStatus}");
|
|
}
|
|
// salvo B_Input in cache!
|
|
Last_B_Input.Value = B_input;
|
|
Last_B_Input.ValidUntil = DateTime.Now.AddSeconds(maxDelaySec * cacheMult);
|
|
}
|
|
// se disponibile riporto B_Input precedente
|
|
else
|
|
{
|
|
if (Last_B_Input.ValidUntil > adesso)
|
|
{
|
|
B_input = Last_B_Input.Value;
|
|
}
|
|
}
|
|
// riporto bitmap...
|
|
reportRawInput(ref currDispData);
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lgError(exc, "Errore in readSemafori x IOB FILE");
|
|
if (currDispData != null)
|
|
currDispData.semIn = Semaforo.SR;
|
|
}
|
|
|
|
// ultimo controllo...
|
|
if (!readDone)
|
|
{
|
|
// se valido RILEGGO ultimo B_INPUT
|
|
if (Last_B_Input.ValidUntil > adesso)
|
|
{
|
|
B_input = Last_B_Input.Value;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua reset del contapezzi, NON PERMESSO per EM63 (read only)
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override bool resetContapezziPLC()
|
|
{
|
|
bool answ = false;
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua IMPOSTAZIONE FORZATA del contapezzi, NON PERMESSO per EM63 (read only)
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public override bool setcontapezziPLC(int newPzCount)
|
|
{
|
|
bool answ = false;
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Connessione
|
|
/// </summary>
|
|
public override void tryConnect()
|
|
{
|
|
var nextLevel = Eurom63.ComLevel.IsConnected;
|
|
var connectSession = confE63.ActiveSessions[0];
|
|
processSession(nextLevel, ref connectSession);
|
|
queueInEnabCurr = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Disconnessione
|
|
/// </summary>
|
|
public override void tryDisconnect()
|
|
{
|
|
connectionOk = false;
|
|
queueInEnabCurr = false;
|
|
try
|
|
{
|
|
abortPrevJob();
|
|
cleanupFolder();
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lgError(exc, "Eccezione in tryDisconnect");
|
|
}
|
|
}
|
|
|
|
#endregion Public Methods
|
|
|
|
#region Internal Methods
|
|
|
|
/// <summary>
|
|
/// Metodi preliminari x comunicazione:
|
|
/// - richiesta connessione
|
|
/// - richiesta stato attivo
|
|
/// </summary>
|
|
internal void checkCommStatus()
|
|
{
|
|
// init obj display
|
|
newDisplayData currDispData = new newDisplayData();
|
|
currDispData.semIn = Semaforo.ND;
|
|
|
|
switch (actLevel)
|
|
{
|
|
case Eurom63.ComLevel.None:
|
|
tryConnect();
|
|
currDispData.semIn = Semaforo.SS;
|
|
break;
|
|
|
|
case Eurom63.ComLevel.IsConnected:
|
|
requestInfo();
|
|
currDispData.semIn = Semaforo.SS;
|
|
break;
|
|
|
|
case Eurom63.ComLevel.HasInfo:
|
|
setMachineTime();
|
|
currDispData.semIn = Semaforo.SS;
|
|
break;
|
|
|
|
case Eurom63.ComLevel.TimeSet:
|
|
abortPrevJob();
|
|
currDispData.semIn = Semaforo.SG;
|
|
break;
|
|
|
|
case Eurom63.ComLevel.ChannelOk:
|
|
requestStatusData();
|
|
currDispData.semIn = Semaforo.SG;
|
|
break;
|
|
|
|
case Eurom63.ComLevel.StatusRequested:
|
|
requestProdData();
|
|
currDispData.semIn = Semaforo.SV;
|
|
break;
|
|
|
|
case Eurom63.ComLevel.ProdRequested:
|
|
checkSampling();
|
|
currDispData.semIn = Semaforo.SV;
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
if (utils.CRB("verbose"))
|
|
{
|
|
lgInfo($"DONE checkCommStatus | actLevel {actLevel}");
|
|
}
|
|
raiseRefresh(currDispData);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pulizia preliminare folder comunicazione
|
|
/// </summary>
|
|
internal override void cleanupFolder()
|
|
{
|
|
// elimino OGNI file per tipo configurato
|
|
foreach (var cleanExt in confE63.cleanupExt)
|
|
{
|
|
string[] file2del = Directory.GetFiles(BaseDir, cleanExt);
|
|
foreach (var file in file2del)
|
|
{
|
|
try
|
|
{
|
|
File.Delete(file);
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Pulizia folder dai file RSP della sessione
|
|
/// </summary>
|
|
internal void cleanupResp(string sessionName)
|
|
{
|
|
string[] file2del = Directory.GetFiles(BaseDir, $"{sessionName}.RSP");
|
|
foreach (var file in file2del)
|
|
{
|
|
try
|
|
{
|
|
File.Delete(file);
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Ricarica conf adapter...
|
|
/// </summary>
|
|
internal override void reloadAdapterConf()
|
|
{
|
|
// init obj display
|
|
newDisplayData currDispData = new newDisplayData();
|
|
lgInfo("BEGIN reloadAdapterConf");
|
|
// inizializzo LUT decodifica
|
|
string jsonConf = getOptPar("LUT_CONF");
|
|
if (!string.IsNullOrEmpty(jsonConf))
|
|
{
|
|
string jsonFullPath = $"{Application.StartupPath}/DATA/CONF/{jsonConf}";
|
|
lgInfo($"Apertura file {jsonFullPath}");
|
|
StreamReader reader = new StreamReader(jsonFullPath);
|
|
string jsonData = reader.ReadToEnd();
|
|
if (!string.IsNullOrEmpty(jsonData))
|
|
{
|
|
try
|
|
{
|
|
confE63 = JsonConvert.DeserializeObject<Eurom63.ProtoConf>(jsonData);
|
|
|
|
// salvo baseUri
|
|
BaseDir = confE63.BaseDir;
|
|
lgInfo($"baseDir = {BaseDir}");
|
|
// imposto a zero la bitmap x riavvio!
|
|
B_input = 0;
|
|
// FORZO invio dati...
|
|
accodaSigIN(ref currDispData);
|
|
// loggo!
|
|
lgInfo($"init input bitmap to zero: {B_input}");
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
lgError(exc, "Eccezione in decodifica conf json");
|
|
}
|
|
}
|
|
reader.Dispose();
|
|
}
|
|
lgInfo("DONE reloadAdapterConf");
|
|
raiseRefresh(currDispData);
|
|
}
|
|
|
|
#endregion Internal Methods
|
|
|
|
#region Protected Fields
|
|
|
|
protected static DateTime lastStatusDecr = DateTime.Now;
|
|
|
|
/// <summary>
|
|
/// step di comunicazione attivo
|
|
/// </summary>
|
|
protected Eurom63.ComLevel actLevel = Eurom63.ComLevel.None;
|
|
|
|
/// <summary>
|
|
/// DIrectory eseguibile corrente
|
|
/// </summary>
|
|
protected string appPath = Directory.GetCurrentDirectory();
|
|
|
|
/// <summary>
|
|
/// Moltiplicatore durata cache
|
|
/// </summary>
|
|
protected int cacheMult = 4;
|
|
|
|
/// <summary>
|
|
/// Oggetti decodificati da pagina
|
|
/// </summary>
|
|
protected Eurom63.ProtoConf confE63;
|
|
|
|
/// <summary>
|
|
/// Valore currStatus validato (per gestione "disconnessioni")
|
|
/// </summary>
|
|
protected CachedInt Last_B_Input = new CachedInt() { Value = 0 };
|
|
|
|
/// <summary>
|
|
/// Valore currStatus validato (per gestione "disconnessioni")
|
|
/// </summary>
|
|
protected CachedString Last_CurrStatus = new CachedString() { Value = "00000" };
|
|
|
|
/// <summary>
|
|
/// Massimo delay lettura dati prima di considerarli scaduti (30 sec, ma x test 1 gg)
|
|
/// </summary>
|
|
protected int maxDelaySec = 30;
|
|
|
|
#endregion Protected Fields
|
|
|
|
#region Protected Methods
|
|
|
|
protected void abortPrevJob()
|
|
{
|
|
var nextLevel = Eurom63.ComLevel.ChannelOk;
|
|
var connectSession = confE63.ActiveSessions[3];
|
|
processSession(nextLevel, ref connectSession);
|
|
#if false
|
|
// qui per sicurezza PULISCE TUTTO
|
|
cleanupFolder();
|
|
#endif
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica una sessione configurata (ovvero la comunicazione su TUTTI i file associati)
|
|
/// </summary>
|
|
/// <param name="session"></param>
|
|
/// <returns></returns>
|
|
protected bool checkRequest(Eurom63.Session session)
|
|
{
|
|
bool answ = false;
|
|
string fileName = "";
|
|
if (session != null)
|
|
{
|
|
fileName = $"{BaseDir}\\{session.SessionName}.REQ";
|
|
answ = File.Exists(fileName);
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Verifica se ci sia una risposta POSITIVA
|
|
/// </summary>
|
|
/// <param name="session"></param>
|
|
/// <returns></returns>
|
|
protected bool checkResp(Eurom63.Session session)
|
|
{
|
|
bool answ = false;
|
|
string fileName = "";
|
|
if (session != null)
|
|
{
|
|
fileName = $"{BaseDir}\\{session.SessionName}.RSP";
|
|
if (File.Exists(fileName))
|
|
{
|
|
// verifico contenuto
|
|
//string rawData = File.ReadAllText(fileName);
|
|
string rawData = "";
|
|
// lettura in modo NON esclusivo...
|
|
using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
|
|
using (var textReader = new StreamReader(fileStream))
|
|
{
|
|
rawData = textReader.ReadToEnd();
|
|
}
|
|
// se la stringa session.RespOk contiene | significa ci sono + valori ammessi e
|
|
// li controlla tutti
|
|
if (session.RespOk.Contains("|"))
|
|
{
|
|
// splitto e testo tutti...
|
|
string[] validRespOk = session.RespOk.Split('|');
|
|
foreach (var item in validRespOk)
|
|
{
|
|
answ = answ || rawData.Contains(item);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
answ = rawData.Contains(session.RespOk);
|
|
}
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// verifica periodica dei campionamenti:
|
|
/// - i due jobs devono essere attivi e non scaduti
|
|
/// - non devo aver già resettato...
|
|
/// </summary>
|
|
protected void checkSampling()
|
|
{
|
|
var currSession = confE63.ActiveSessions[4];
|
|
checkSessionActive(currSession, Eurom63.ComLevel.ChannelOk);
|
|
|
|
currSession = confE63.ActiveSessions[5];
|
|
checkSessionActive(currSession, Eurom63.ComLevel.ChannelOk);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Elimina i file della sessione indicata (SE è un task ciclico --> solo RSP)
|
|
/// </summary>
|
|
/// <param name="session"></param>
|
|
/// <returns></returns>
|
|
protected bool cleanupSession(Eurom63.Session session)
|
|
{
|
|
bool answ = false;
|
|
if (session != null)
|
|
{
|
|
// solo se scaduta validità...
|
|
if (session.SessionValidUntil < DateTime.Now)
|
|
{
|
|
string searchPattern = $"{session.SessionName}.*";
|
|
// task ciclico?
|
|
if (session.Cycle)
|
|
{
|
|
// solo risposta!
|
|
searchPattern = $"{session.SessionName}.RSP";
|
|
}
|
|
string[] file2del = Directory.GetFiles(BaseDir, searchPattern);
|
|
foreach (var file in file2del)
|
|
{
|
|
try
|
|
{
|
|
File.Delete(file);
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processa una sessione
|
|
/// - andando a verificare l'esistenza della REQ + se esito positivo pulizia
|
|
/// - andando a richeidere di nuovo risposta
|
|
/// </summary>
|
|
/// <param name="nextLevel"></param>
|
|
/// <param name="connectSession"></param>
|
|
protected void processSession(Eurom63.ComLevel nextLevel, ref Eurom63.Session connectSession)
|
|
{
|
|
if (connectSession != null)
|
|
{
|
|
// controllo esistenza directory --> segno connected...
|
|
connectionOk = Directory.Exists(BaseDir);
|
|
DateTime adesso = DateTime.Now;
|
|
if (connectionOk)
|
|
{
|
|
// verifico se ci sia risp CONNECT
|
|
if (checkResp(connectSession))
|
|
{
|
|
// aggiorno livello
|
|
actLevel = nextLevel;
|
|
parentForm.displayTaskAndLog($"Adp Level: {nextLevel}");
|
|
// elimino file sessione
|
|
cleanupSession(connectSession);
|
|
connectSession.Active = connectSession.Cycle;
|
|
connectSession.Passed = true;
|
|
}
|
|
// verifico SE ci sia la richiesta sennò la chiedo...
|
|
else if (!checkRequest(connectSession))
|
|
{
|
|
copyRequestFiles(connectSession, adesso);
|
|
}
|
|
// richiedo SE non ci fosse i dati CONNECT...
|
|
else
|
|
{
|
|
// evito di richiedere SE non fosse già scaduta richiesta...
|
|
if (adesso > connectSession.RetryVeto || !checkRequest(connectSession))
|
|
{
|
|
// pulisco eventuali risp vecchie
|
|
cleanupResp(connectSession.SessionName);
|
|
copyRequestFiles(connectSession, adesso);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// aspetto prima di riprovare...
|
|
Thread.Sleep(50);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// aspetto prima di riprovare...
|
|
Thread.Sleep(50);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Processa i file della sessione indicata (copy + transform)
|
|
/// </summary>
|
|
/// <param name="session"></param>
|
|
/// <returns></returns>
|
|
protected bool processSessionFile(Eurom63.Session session)
|
|
{
|
|
bool answ = false;
|
|
if (session != null)
|
|
{
|
|
string fileFrom = "";
|
|
string fileTo = "";
|
|
// processo OGNI file sessione x farne copia
|
|
foreach (var file2Proc in session.FileList)
|
|
{
|
|
fileFrom = $"{appPath}\\{file2Proc.Path}";
|
|
fileTo = $"{BaseDir}\\{Path.GetFileName(file2Proc.Path)}";
|
|
string rawData = File.ReadAllText(fileFrom);
|
|
|
|
if (file2Proc.OprReq == Eurom63.FileOpr.Copy)
|
|
{
|
|
// scrivo!
|
|
File.WriteAllText(fileTo, rawData);
|
|
}
|
|
else
|
|
{
|
|
// leggo file originale... e processo sostituzioni
|
|
rawData = rawData.Replace("{DTNow}", DateTime.Now.ToString("HHmmssyyyyMMdd"));
|
|
// ora in posizione definitiva
|
|
File.WriteAllText(fileTo, rawData);
|
|
}
|
|
}
|
|
}
|
|
return answ;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua richiesta info x macchina (validare startup process)
|
|
/// </summary>
|
|
protected void requestInfo()
|
|
{
|
|
var nextLevel = Eurom63.ComLevel.HasInfo;
|
|
var connectSession = confE63.ActiveSessions[1];
|
|
processSession(nextLevel, ref connectSession);
|
|
}
|
|
|
|
protected void requestProdData()
|
|
{
|
|
var nextLevel = Eurom63.ComLevel.ProdRequested;
|
|
var connectSession = confE63.ActiveSessions[5];
|
|
processSession(nextLevel, ref connectSession);
|
|
}
|
|
|
|
protected void requestStatusData()
|
|
{
|
|
var nextLevel = Eurom63.ComLevel.StatusRequested;
|
|
var connectSession = confE63.ActiveSessions[4];
|
|
processSession(nextLevel, ref connectSession);
|
|
}
|
|
|
|
protected void setMachineTime()
|
|
{
|
|
var nextLevel = Eurom63.ComLevel.TimeSet;
|
|
var connectSession = confE63.ActiveSessions[2];
|
|
processSession(nextLevel, ref connectSession);
|
|
}
|
|
|
|
#endregion Protected Methods
|
|
|
|
#region Private Methods
|
|
|
|
/// <summary>
|
|
/// Se la sessione fosse scaduta o non attiva --> torna al livello indicato
|
|
/// </summary>
|
|
/// <param name="currSession"></param>
|
|
private void checkSessionActive(Eurom63.Session currSession, Eurom63.ComLevel nextLevel)
|
|
{
|
|
// SOLO SE ha senso che controllo (sono in sampling...)
|
|
if (actLevel > Eurom63.ComLevel.HasInfo)
|
|
{
|
|
DateTime adesso = DateTime.Now;
|
|
// devono essere ATTIVE le sessioni di campionamento... e NON scadute
|
|
if (!currSession.Active || currSession.SessionValidUntil < adesso)
|
|
{
|
|
// controllo ultimo downgrade status
|
|
if (lastStatusDecr.AddSeconds(3) < adesso)
|
|
{
|
|
// elimino TUTTE le risposte...
|
|
cleanupResp(currSession.SessionName);
|
|
// registro downgrade status...
|
|
lastStatusDecr = adesso;
|
|
// imposto livellotornando indietro di 1 alla volta... senza andare in negativoS
|
|
actLevel = actLevel - 1;
|
|
actLevel = actLevel > 0 ? actLevel : 0;
|
|
lgInfo($"Sessione inattiva, {actLevel + 1} --> {actLevel}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Effettua copia file richeiste + update timing
|
|
/// </summary>
|
|
/// <param name="connectSession"></param>
|
|
/// <param name="adesso"></param>
|
|
private void copyRequestFiles(Eurom63.Session connectSession, DateTime adesso)
|
|
{
|
|
// processo richiesta
|
|
processSessionFile(connectSession);
|
|
if (adesso > connectSession.SessionValidUntil)
|
|
{
|
|
connectSession.Active = !connectSession.Cycle;
|
|
}
|
|
connectSession.Passed = false;
|
|
connectSession.SessionStarted = adesso;
|
|
connectSession.SessionValidUntil = adesso.AddMinutes(connectSession.ValidityMinutes);
|
|
connectSession.RetryVeto = adesso.AddSeconds(connectSession.RetrySec);
|
|
}
|
|
|
|
#endregion Private Methods
|
|
}
|
|
} |