Files
Mapo-IOB-WIN/IOB-WIN-NEXT/IobNet/Ftp.cs
T
Samuele Locatelli c4a103ddc5 IOB-WIN-NEXT
Bozza struttura file x IobFTP (Sonatest)
2024-10-04 19:00:48 +02:00

338 lines
14 KiB
C#

using MapoSDK;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading.Tasks;
namespace IOB_WIN_NEXT.IobNet
{
/// <summary>
/// Classe gestione sync via FTP
/// </summary>
public class Ftp : Iob.Generic
{
#region Public Constructors
/// <summary>
/// Estende l'init della classe base, impiegando il pacchetto EgwCoreLib.Ftp
/// - gestione dei task da svolgere da configurazione json specifica
/// - specializzazione da conf e non da codice
/// </summary>
/// <param name="caller"></param>
/// <param name="IOBConf"></param>
public Ftp(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf)
{
lgInfo("Init IobFtp Client");
sendKeyRichiesta = true;
}
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Processo i task richiesti e li elimino dalla coda 2:2
/// </summary>
/// <param name="task2exe"></param>
public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe)
{
// uso metodo base x salvare esito scrittura
var writeResult = base.executeTasks(task2exe);
/*---------------------------------------------------------------------------
* va creata una folder x ogni ODL (una volta LANCIATO da tablet) APERTO
* - nella folder scriviamo un file con articolo, qta, commessa
* - la folder sarà usata x salvare OGNI file necessario e di rilevazione
*---------------------------------------------------------------------------*/
// aggiungo comportamento custom: se ho impostato nome ricetta (programma) --> imposto
// richiesta caricamento se ho richiesto reset o fine lavoro --> imposto azzeramento
// esco restituendo risutlato scrittura iniziali
if (task2exe != null)
{
// controllo se memMap != null...
if (memMap != null)
{
bool taskOk = false;
string taskVal = "";
// cerco task specifici x OMP
foreach (var item in task2exe)
{
taskOk = false;
taskVal = "";
// converto richiesta in enum...
taskType tName = taskType.nihil;
Enum.TryParse(item.Key, out tName);
// controllo sulla KEY...
switch (tName)
{
#if false
case taskType.setProg:
// recupero dati da memMap...
if (memMap != null && memMap.mMapWrite != null)
{
if (memMap.mMapWrite.ContainsKey(item.Key))
{
dataConf currMem = memMap.mMapWrite[item.Key];
string addr = currMem.memAddr;
taskVal = $"SET task: {item.Key} --> {item.Value} | mem: {currMem.memAddr} - {currMem.size} byte";
// salvo il nuovo valore nella memoria... così prox invio lo trasmetterà
memMap.mMapWrite[item.Key].value = item.Value;
}
else
{
taskVal = $"NO DATA MEM, SET task: {item.Key} --> {item.Value}";
}
}
else
{
taskVal = $"NO MemMap found, SET task: {item.Key} --> {item.Value}";
}
// salvo in currProd..
saveProdData(new KeyValuePair<string, string>(item.Key, item.Value));
break;
case taskType.startSetup:
setFineLotto();
break;
case taskType.stopSetup:
setInizioProd();
break;
case taskType.syncDbData:
processDataSync();
break;
#endif
default:
taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC";
lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}");
break;
}
}
}
else
{
lgError($"Attenzione! memMap è nullo, non posso eseguire task2exe!");
}
}
return writeResult;
}
#endregion Public Methods
#region Protected Methods
/// <summary>
/// Effettua decodifica aree memoria alla bitmap usata x MAPO
/// </summary>
protected virtual void decodeToBaseBitmap()
{
DateTime adesso = DateTime.Now;
// init a zero...
B_input = 0;
/* -----------------------------------------------------
* STATE MACHINE 60 STD / SIMULA
*------------------------------------------------------
* bitmap MAPO
* B0: POWER_ON
* B1: RUN
* B2: pzCount
* B3: allarme
* B4: manuale
* B5: SlowTC (NON gestito qui)
* B6: warm-up / cool-down / setup
* B7: emergenza ARMATA (1=ok, 0 = premuta)
---------------------------------------------------- */
// lo stato è semplicemente
// - usiamo RunIP (es wifi x Sonatest) x pingare quando accesa --> green se NON risponde
// ai ping --> GRIGIA nessun altro stato
#if false
// se valido il check ping lo eseguo... altrimenti lo do x buono
bool checkPing = !opcUaParams.pingAsPowerOn;
string currRun = "N.A.";
if (!checkPing)
{
checkPing = (testPingMachine == IPStatus.Success);
}
// bit 0 (poweron) imposto a 1 SE pingo + PowerOn=="ON"...
bool powerOnOk = checkPing && hasPowerOn;
// procedo SOLO SE mi da ping OK...
if (checkPing)
{
B_input = powerOnOk ? 1 : 0;
procRunMode(ref currRun);
/* -----------------------------------------------------
* CIMOLAI CUSTOM
*------------------------------------------------------
* AUX = 2 --> emergenza armata
* AUX <> 2 --> emergenza premuta
* Aux = 2 + InCorso = 0 --> pronto
* Aux = 2 + LastAct in (2,4,6,8) --> LAVORA
*
*
* PLC/DB231/Attivita
* 0: Emergenza
* 1: Avvio registrazione ricetta
* 2: Inizio comando traslazione
* 3: Termine comando traslazione
* 4: Inizio comando di sterzatura
* 5: Termine comando di sterzatura
* 6: Inizio comando movimento carrelli
* 7: Termine comando movimento carrelli
* 8: Inizio comando sollevamento
* 9: Termine comando sollevamento
* 10: richiesta snapshot parametri
*
*------------------------------------------------------
* SEMPLIFICAZIONE POST CERTIFICAZIONE
*------------------------------------------------------
*
* Visto che la rete potrebbe saltare ad intermittenza, conviene gestire in modo semplificato il lavora
* torno a condizione work base: AUX = 2, marcia = in corso
*
*
---------------------------------------------------- */
// controllo emergenza... se zero --> emergenza!
if (hasEStopArmed)
{
B_input += (1 << 7);
}
else
{
// resetto last act...
lastAct = 0;
}
// verifico se aggiornare stato LAST ACTION
if (lastAct != currRunMode && currRunMode != 0)
{
// registro solo azioni > 1 e < 10
if (currRunMode > 1 && currRunMode < 10)
{
// escludo le azioni 4 e 5 (che sono anche in concomitanza con 2-3)
if (currRunMode < 4 || currRunMode > 5)
{
lastAct = currRunMode;
}
}
}
// Gestione ODL automatica: se abilitata --> qui con start/stop da impianto...
if (doProcOdl)
{
lgTrace($"inizio process verifica presa in carico PODL | isInCorso: {isInCorso} | lastIsInCorso: {lastIsInCorso} | currProgName {currProgName}");
// se rilevo variazione exe (curr/last)
// --> registro richiesta attreazzaggio PODL da info commessa
if (lastIsInCorso != isInCorso)
{
// se 0 --> 1 --> registro
if (isInCorso)
{
lgInfo("--------------------------------------------");
// prendo senza stringa PODL
string sPODL = currProgName.Replace("PODL", "");
int idxPODL = 0;
int.TryParse(sPODL, out idxPODL);
// chiamo richiesta setup PODL...
lgInfo($"Inizio trySetupPODL per {idxPODL}");
trySetupPODL(idxPODL);
lgInfo("--------------------------------------------");
}
else
{
lgInfo("--------------------------------------------");
lgInfo("Inizio tryCloseODL");
// registro chiusura ODL..
tryCloseCurrODL();
lgInfo("--------------------------------------------");
}
// registro exe mode
lastIsInCorso = isInCorso;
}
}
// salvo running come = working...
isRunning = isWorkingCimolai;
// se ho setup
if (isWarmUpCoolDown)
{
B_input += (1 << 6);
}
// se ho almeno 1 allarme E NON SONO IN AUTO --> ALARM!
if (hasError)
{
B_input += (1 << 3);
}
if (isWorkingCimolai || isWorking || isInCorso)
{
// RUN = LAVORA!
B_input += (1 << 1);
}
else
{
if (!isReady || isManualCimolai || isManual)
{
// se NON ready --> manual
B_input += (1 << 4);
}
}
}
// controllo se non ho dati buoni da > lastCurrentMaxElapsed sec --> disconnetto
if (adesso.Subtract(lastCurrent).TotalSeconds > lastCurrentMaxElapsed)
{
lgInfo($"Timeout per mancata comunicazione da oltre {lastCurrentMaxElapsed} sec --> disconnessione adapter OpcUa!");
tryDisconnect();
}
// solo se non ho veto check
int vFactor = 2;
if (vetoCheckStatus < adesso)
{
lgDebug($"Stato variabili checkPing: {testPingMachine}");
// imposto veto per vetoSeconds...
vetoCheckStatus = adesso.AddSeconds(vetoSeconds * vFactor);
}
// log opzionale!
if (verboseLog)
{
lgDebug($"Trasformazione checkPing: {checkPing} | hasPowerOn: {hasPowerOn} | B_input: {B_input} | currRun = {currRun}");
}
#endif
}
/// <summary>
/// Effettua sync dati
/// </summary>
protected override void processDataSync()
{
lgInfo("--------------------------------------------");
lgInfo($"executeTasks --> syncDbData --> processDataSync");
lgInfo("--------------------------------------------");
// effettua sync... recupera cartella MAIN da FTP e replica in locale su folder apposita
// (in rete?)
#if false
var taskGet = iobGetDataFromServer();
var taskWrite = iobWriteLocalCSV();
var taskSend = iobSendFTP("");
#endif
}
#endregion Protected Methods
}
}