1019 lines
42 KiB
C#
1019 lines
42 KiB
C#
using EgwProxy.Ftp;
|
||
using IOB_UT_NEXT;
|
||
using IOB_UT_NEXT.Config;
|
||
using IOB_UT_NEXT.Config.Mem;
|
||
using IOB_UT_NEXT.Config.Special;
|
||
using IOB_UT_NEXT.Objects;
|
||
using IOB_UT_NEXT.Services.Data;
|
||
using IOB_UT_NEXT.Services.Utility;
|
||
using MapoSDK;
|
||
using Newtonsoft.Json;
|
||
using System;
|
||
using System.Collections.Generic;
|
||
using System.Diagnostics;
|
||
using System.IO;
|
||
using System.Linq;
|
||
using System.Net.NetworkInformation;
|
||
using System.Threading.Tasks;
|
||
|
||
namespace IOB_WIN_FTP.Iob
|
||
{
|
||
/// <summary>
|
||
/// Classe gestione sync via FTP
|
||
/// </summary>
|
||
public class Ftp : Iob.GenericNext
|
||
{
|
||
#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">Form chiamante</param>
|
||
/// <param name="IobConfFull">Configurazione (v 4.x)</param>
|
||
public Ftp(AdapterFormNext caller, IobConfTree IobConfFull) : base(caller, IobConfFull)
|
||
{
|
||
lgInfo("Init IobFtp Client");
|
||
// imposto
|
||
B_input = 0;
|
||
// init datetime counters
|
||
DateTime adesso = DateTime.Now;
|
||
DtHelp.lastPzCountSend = adesso;
|
||
DtHelp.lastWarnODL = adesso;
|
||
vetoCheckStatus = adesso;
|
||
// 2023.09.05 imposto anche primo ping e check disconnected...
|
||
DtHelp.lastPING = adesso;
|
||
DtHelp.lastDisconnCheck = adesso;
|
||
var VETO_PING_SEC = getOptPar("VETO_PING_SEC");
|
||
if (!string.IsNullOrEmpty(VETO_PING_SEC))
|
||
{
|
||
int.TryParse(VETO_PING_SEC, out vetoPingSec);
|
||
}
|
||
var VETO_CHECKDIR_SEC = getOptPar("VETO_CHECKDIR_SEC");
|
||
if (!string.IsNullOrEmpty(VETO_CHECKDIR_SEC))
|
||
{
|
||
int.TryParse(VETO_CHECKDIR_SEC, out vetoCheckDirSec);
|
||
}
|
||
var POWEROFF_TIMEOUT_SEC = getOptPar("POWEROFF_TIMEOUT_SEC");
|
||
if (!string.IsNullOrEmpty(POWEROFF_TIMEOUT_SEC))
|
||
{
|
||
int.TryParse(POWEROFF_TIMEOUT_SEC, out PoweroffTimeoutSec);
|
||
}
|
||
// carico conf specifica steps FTP
|
||
string ftpConfFile = getOptPar("FTP_PARAM");
|
||
if (!string.IsNullOrEmpty(ftpConfFile))
|
||
{
|
||
loadFtpConfFile(ftpConfFile);
|
||
// mi calcolo ed imposto la ftpClientMan + Remote BaseDir...
|
||
string actKey = "RemoteDir";
|
||
if (currFtpTaskList != null && currFtpTaskList.ListTask.Count > 0)
|
||
{
|
||
// prendo i task
|
||
foreach (var fTask in currFtpTaskList.ListTask)
|
||
{
|
||
if (string.IsNullOrEmpty(RemoteBaseDir))
|
||
{
|
||
foreach (var fAct in fTask.StepsList)
|
||
{
|
||
// cerco nei parametri...
|
||
if (fAct.ParamList.ContainsKey(actKey))
|
||
{
|
||
RemoteBaseDir = fAct.ParamList[actKey];
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
if (!ftpClientMan.IsConfigured)
|
||
{
|
||
// setup ftpClientMan!
|
||
ftpClientMan = new Manager(fTask.ServerAddr, fTask.ConnUser, fTask.ConnPasswd, fTask.RawCert, fTask.SkipCert);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
forceMemMap();
|
||
}
|
||
|
||
#endregion Public Constructors
|
||
|
||
#region Public Methods
|
||
|
||
/// <summary>
|
||
/// Processo i task richiesti e li elimino dalla coda
|
||
/// </summary>
|
||
/// <param name="task2exe"></param>
|
||
public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe, string codTav)
|
||
{
|
||
/*---------------------------------------------------------------------------
|
||
* 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
|
||
* - per farlo si creeano degli ActionStep specifici e vengono poi richiamati...
|
||
*---------------------------------------------------------------------------*/
|
||
|
||
// Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti...
|
||
Dictionary<string, string> taskDone = new Dictionary<string, string>();
|
||
GenActConf.ActionConfig currAct = new GenActConf.ActionConfig();
|
||
var currActParam = new Dictionary<string, string>();
|
||
string actKey = "RemoteDir";
|
||
string newDir = "";
|
||
bool taskOk = false;
|
||
string taskVal = "";
|
||
string fNameOdl = "ODL_ATTIVO.txt";
|
||
string basePath = System.Windows.Forms.Application.StartupPath;
|
||
string remFile = "";
|
||
string fileContent = "";
|
||
string locFile = "";
|
||
// cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4
|
||
foreach (var item in task2exe)
|
||
{
|
||
taskOk = false;
|
||
taskVal = "";
|
||
// converto richiesta in enum...
|
||
taskType tName = taskType.nihil;
|
||
Enum.TryParse(item.Key, out tName);
|
||
// controllo sulla KEY...
|
||
switch (tName)
|
||
{
|
||
case taskType.setArt:
|
||
case taskType.setPzComm:
|
||
// L'articolo ed il numPz li salva nei dati di produzione... SE disponibili
|
||
// li indicherà nel file ODL ATTIVA...
|
||
upsertKey(item.Key, item.Value);
|
||
// salvo nei taskVal il valore acquisito...
|
||
taskVal = $"Saved {item.Key} = {item.Value} on ProdData";
|
||
break;
|
||
|
||
case taskType.setComm:
|
||
/*------------------------------------------------------------------
|
||
* La commessa è la cartella DI BASE per poter poi procedere con acquisizione dati...
|
||
* - step 1: check folder
|
||
* - step 2: creazione folder
|
||
* - step 3: salva file ODL_attiva
|
||
* - step 4: salva parametro dell'ODL corrente
|
||
------------------------------------------------------------------*/
|
||
// compongo remDir dai 2 parametri...
|
||
actKey = "RemoteDir";
|
||
newDir = $"{RemoteBaseDir}/{item.Value}";
|
||
currActParam.Add(actKey, newDir);
|
||
currAct = new GenActConf.ActionConfig()
|
||
{
|
||
Id = "01",
|
||
Description = "Verifica esistenza directory",
|
||
Action = GenActConf.ActType.CheckDir,
|
||
ParamList = currActParam
|
||
};
|
||
//eseguo step...
|
||
bool dirOk = doStep(currAct);
|
||
// se la cartella mancasse
|
||
if (!dirOk)
|
||
{
|
||
// nuovo act x crearla!
|
||
currAct = new GenActConf.ActionConfig()
|
||
{
|
||
Id = "02",
|
||
Description = "Creazione directory",
|
||
Action = GenActConf.ActType.CreateDir,
|
||
ParamList = currActParam
|
||
};
|
||
//eseguo step...
|
||
dirOk = doStep(currAct);
|
||
if (dirOk)
|
||
{
|
||
taskVal = $"DIR Created: {item.Key} --> {item.Value}";
|
||
}
|
||
}
|
||
else
|
||
{
|
||
taskVal = $"DIR Already Exists: {item.Key} --> {item.Value}";
|
||
}
|
||
// ora creo il file interno...
|
||
remFile = $"{newDir}/{fNameOdl}";
|
||
// cerco se disponibili info in prodData x art/pezzi
|
||
string setArt = getCurrProdData("setArt", "ND");
|
||
string setPzComm = getCurrProdData("setPzComm", "?");
|
||
fileContent = $"NEW ODL activated | {item.Value} | ART: {setArt} x {setPzComm} pz | {DateTime.Now}";
|
||
locFile = Path.Combine(basePath, "temp", fNameOdl);
|
||
taskOk = SendOdlActFile(locFile, remFile, fileContent);
|
||
if (taskOk)
|
||
{
|
||
taskVal += $"{Environment.NewLine}File uploaded | locFile: {locFile} | remFile: {remFile}";
|
||
}
|
||
else
|
||
{
|
||
lgError($"Error in startSetup | fileUpload | locFile: {locFile} | remFile: {remFile}");
|
||
}
|
||
// salvo in currProd..
|
||
upsertKey(item.Key, item.Value);
|
||
|
||
// salvo dati scambiati
|
||
trackExchData(fileContent.LongCount(), 1024);
|
||
break;
|
||
|
||
case taskType.startSetup:
|
||
case taskType.stopSetup:
|
||
//verifico odl x prima cosa...
|
||
pzCntReload(true);
|
||
// faccio pulizia preliminare della commessa corrente...
|
||
bool cleanDone = RemPlaceholder(RemoteBaseDir, fNameOdl);
|
||
if (cleanDone)
|
||
{
|
||
lgInfo($"Cleaned {fNameOdl} during startSetup | remDir: {RemoteBaseDir}");
|
||
}
|
||
// verifico di avere già un ODL corrente...
|
||
if (currIdxODL == 0)
|
||
{
|
||
lgTrace($"Manca ODL corrente: non procedo con impostazione start/stop setup");
|
||
}
|
||
else
|
||
{
|
||
string odlFolder = $"ODL{currIdxODL:00000000}";
|
||
remFile = $"{RemoteBaseDir}/{odlFolder}/{fNameOdl}";
|
||
fileContent = item.Value;
|
||
// scrivo file ultima richiesta setup
|
||
locFile = Path.Combine(basePath, "temp", fNameOdl);
|
||
taskOk = SendOdlActFile(locFile, remFile, fileContent);
|
||
if (taskOk)
|
||
{
|
||
taskVal = $"File uploaded: {item.Key} --> {item.Value} | locFile: {locFile} | remFile: {remFile}";
|
||
}
|
||
else
|
||
{
|
||
lgError($"Error in startSetup | fileUpload | locFile: {locFile} | remFile: {remFile}");
|
||
}
|
||
}
|
||
// salvo dati scambiati
|
||
trackExchData(fileContent.LongCount(), 1024);
|
||
|
||
break;
|
||
|
||
case taskType.endProd:
|
||
bool okRemove = RemPlaceholder(RemoteBaseDir, fNameOdl);
|
||
if (okRemove)
|
||
{
|
||
taskVal = $"Cleaned CurrOdlFile: {item.Key} --> {item.Value} | remDir: {RemoteBaseDir} | fName: {fNameOdl}";
|
||
}
|
||
else
|
||
{
|
||
lgError($"Error in CurrOdlFile | remDir: {RemoteBaseDir} | fName: {fNameOdl}");
|
||
}
|
||
break;
|
||
|
||
default:
|
||
taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC";
|
||
lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}");
|
||
break;
|
||
}
|
||
// aggiungo task SE svolto!
|
||
if (!string.IsNullOrEmpty(taskVal))
|
||
{
|
||
taskDone.Add(item.Key, taskVal);
|
||
}
|
||
}
|
||
return taskDone;
|
||
}
|
||
|
||
public override async Task InitializeAsync()
|
||
{
|
||
// invio conf macchina all'inizio
|
||
await SendMachineConfAsync();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Effettua processing CUSTOM x FTP:
|
||
/// - prende ogni conf specifica
|
||
/// - esegue step
|
||
/// - registra eventuali DynData da salvare
|
||
/// </summary>
|
||
public override void processCustomTaskLF()
|
||
{
|
||
lgInfo($"Richiesto processCustomTaskLF");
|
||
// verifico di avere compiti da svolgere...
|
||
if (currFtpTaskList != null && currFtpTaskList.ListTask != null && currFtpTaskList.ListTask.Count > 0)
|
||
{
|
||
foreach (var srvFtp in currFtpTaskList.ListTask)
|
||
{
|
||
// verifico eventuale veto all'esecuzione...
|
||
if (ActionEnabled(srvFtp))
|
||
{
|
||
// imposto nuovo veto...
|
||
ActionResetVeto(srvFtp);
|
||
// ora setup server FTP x item...
|
||
ftpClientMan = new Manager(srvFtp.ServerAddr, srvFtp.ConnUser, srvFtp.ConnPasswd, srvFtp.RawCert, srvFtp.SkipCert);
|
||
// test server ok...
|
||
if (ftpClientMan.ServerOk())
|
||
{
|
||
int stepDone = 0;
|
||
string srvType = ftpClientMan.ServerType();
|
||
lgTrace($"Connesso a server {srvType} | {srvFtp.ServerAddr} | inizio processing {srvFtp.StepsList.Count} steps");
|
||
// ciclo tra i vari steps!
|
||
foreach (var step in srvFtp.StepsList)
|
||
{
|
||
bool fatto = doStep(step);
|
||
stepDone += fatto ? 1 : 0;
|
||
}
|
||
lgInfo($"Completata esecuzione steps FTP | {srvFtp.ActionId} | {stepDone}/{srvFtp.StepsList.Count} Done/Req");
|
||
}
|
||
else
|
||
{
|
||
// FixMe ToDo verificare se necessario...
|
||
//connectionOk = false;
|
||
//tryDisconnect();
|
||
lgError($"Impossibile connettersi al server {srvFtp.ServerAddr}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
lgTrace($"Saltata esecuzione {srvFtp.ActionId} | veto attivo");
|
||
}
|
||
}
|
||
}
|
||
DtHelp.lastReadPLC = DateTime.Now;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
|
||
/// aggiornare x display in form</paramref>
|
||
/// </summary>
|
||
public override void readSemafori(ref newDisplayData currDispData)
|
||
{
|
||
DateTime adesso = DateTime.Now;
|
||
// procedo solo se ftp è configurato (altrimenti inutile controllare...)ù
|
||
if (ftpClientMan.IsConfigured)
|
||
{
|
||
// salto se fosse attivo il veto ping...
|
||
if (DtHelp.lastPING.AddSeconds(vetoPingSec) < adesso)
|
||
{
|
||
// lo stato è come ping machine, x ora puntato a IP unico (WiFi?)
|
||
byte[] MemBlock = new byte[2];
|
||
try
|
||
{
|
||
currDispData.semIn = Semaforo.SV;
|
||
// in primis salvo data ping comunque...
|
||
DtHelp.lastPING = adesso;
|
||
|
||
// salvo esito ping
|
||
bool pingOK = testPingMachine == IPStatus.Success;
|
||
addTest(pingOK);
|
||
bool ftpOk = ftpClientMan.ServerOk();
|
||
// se passa il check ping + folder faccio il resto...
|
||
if (pingStatusOk() && ftpOk)
|
||
{
|
||
// salto se fosse attivo il veto controllo folder...
|
||
if (lastCheckDir.AddSeconds(vetoCheckDirSec) < adesso)
|
||
{
|
||
lastCheckDir = adesso;
|
||
// verifico SE HO una folder da ODL in currProdData e se è disponibile...
|
||
string reqFolder = getCurrProdData("setComm", "");
|
||
if (!string.IsNullOrEmpty(reqFolder))
|
||
{
|
||
// verifico se ci sia...
|
||
GenActConf.ActionConfig currAct = new GenActConf.ActionConfig();
|
||
var currActParam = new Dictionary<string, string>();
|
||
// compongo remDir dai 2 parametri...
|
||
currActParam.Add("RemoteDir", $"{RemoteBaseDir}/{reqFolder}");
|
||
currAct = new GenActConf.ActionConfig()
|
||
{
|
||
Id = "01",
|
||
Description = "Verifica esistenza directory",
|
||
Action = GenActConf.ActType.CheckDir,
|
||
ParamList = currActParam
|
||
};
|
||
//eseguo step...
|
||
bool dirOk = doStep(currAct);
|
||
if (dirOk)
|
||
{
|
||
numErroriCheck = numErroriCheck > 0 ? numErroriCheck-- : 0;
|
||
}
|
||
else
|
||
{
|
||
lgInfo($"Rilevata mancanza folder ODL: inizio ripristino tramite task setComm");
|
||
numErroriCheck++;
|
||
// altrimenti eseguo task2exe x crearla...
|
||
Dictionary<string, string> task2ExeSetOdl = new Dictionary<string, string>();
|
||
task2ExeSetOdl.Add($"setComm", reqFolder);
|
||
var res = executeTasks(task2ExeSetOdl, "");
|
||
}
|
||
}
|
||
}
|
||
|
||
// se supero soglia errori lettura --> disconnetto e resetto
|
||
if (numErroriCheck > maxErroriCheck)
|
||
{
|
||
lgError($"numErroriCheck: {numErroriCheck} --> disconnessione adapter con tryDisconnect");
|
||
|
||
numErroriCheck = 0;
|
||
connectionOk = false;
|
||
tryDisconnect();
|
||
}
|
||
else
|
||
{
|
||
connectionOk = true;
|
||
}
|
||
|
||
DtHelp.lastReadPLC = adesso;
|
||
DtHelp.lastWatchDog = adesso;
|
||
}
|
||
else
|
||
{
|
||
connectionOk = false;
|
||
}
|
||
|
||
if (connectionOk)
|
||
{
|
||
B_input = 3;
|
||
// aggiungo NON emergenza...
|
||
B_input += (1 << 7);
|
||
}
|
||
else
|
||
{
|
||
B_input = 0;
|
||
}
|
||
}
|
||
catch
|
||
{
|
||
currDispData.semIn = Semaforo.SR;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
public override void startAdapter(bool resetQueue)
|
||
{
|
||
base.startAdapter(resetQueue);
|
||
// 2023.09.05 imposto anche primo ping e check disconnected...
|
||
DateTime adesso = DateTime.Now;
|
||
DtHelp.lastWatchDog = adesso;
|
||
//DtHelp.lastPING = adesso;
|
||
DtHelp.lastReadPLC = adesso;
|
||
DtHelp.lastDisconnCheck = adesso;
|
||
// faccio un primo check POST ritardo
|
||
tryConnect();
|
||
}
|
||
|
||
/// <summary>
|
||
/// Override connessione
|
||
/// </summary>
|
||
public override void tryConnect()
|
||
{
|
||
bool doLog = (verboseLog || periodicLog);
|
||
lgDebug($"FTP: tryConnect step 01 | connectionOk: {connectionOk}");
|
||
if (!connectionOk)
|
||
{
|
||
// controllo che il ping sia stato tentato almeno pingTestSec fa...
|
||
if (DateTime.Now.Subtract(DtHelp.lastPING).TotalSeconds > vetoPingSec)
|
||
{
|
||
if (doLog)
|
||
{
|
||
lgInfo("FTP: ConnKO - tryConnect");
|
||
}
|
||
lgDebug("FTP: tryConnect step 04");
|
||
|
||
lgDebug("FTP: Reset QueuePing");
|
||
|
||
bool pingOK = testPingMachine == IPStatus.Success;
|
||
addTest(pingOK);
|
||
|
||
// se passa il ping faccio il resto...
|
||
if (pingStatusOk())
|
||
{
|
||
// in primis salvo data ping...
|
||
DtHelp.lastPING = DateTime.Now;
|
||
connectionOk = true;
|
||
queueInEnabCurr = true;
|
||
lgInfo("FTP - ping OK");
|
||
}
|
||
else
|
||
{
|
||
// loggo no risposta ping ...
|
||
lgWarn("FTP - ping KO");
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Override disconnessione
|
||
/// </summary>
|
||
public override void tryDisconnect()
|
||
{
|
||
lgInfo("Richiesta disconnessione adapter FTP!");
|
||
connectionOk = false;
|
||
queueInEnabCurr = false;
|
||
}
|
||
|
||
#endregion Public Methods
|
||
|
||
#region Protected Methods
|
||
|
||
/// <summary>
|
||
/// Imposta la memoria PLC in modo forzato (es x oggetti gestiti da FTP come setComm)
|
||
/// </summary>
|
||
protected override void forceMemMap()
|
||
{
|
||
// simulo setup mappa memoria in scrittura...
|
||
memMap = new plcMemMapExt();
|
||
// area READ
|
||
Dictionary<string, dataConfTSVC> ftpMemRead = new Dictionary<string, dataConfTSVC>();
|
||
ftpMemRead.Add("FtpSync", new dataConfTSVC()
|
||
{
|
||
description = "Last FTP sync",
|
||
name = "FtpSync",
|
||
tipoMem = plcDataType.String,
|
||
displOrdinal = 10
|
||
});
|
||
memMap.mMapRead = ftpMemRead;
|
||
// area WRITE
|
||
Dictionary<string, dataConf> ftpMemWrite = new Dictionary<string, dataConf>();
|
||
ftpMemWrite.Add("setComm", new dataConf()
|
||
{
|
||
description = "Commessa",
|
||
name = "setComm",
|
||
tipoMem = plcDataType.String,
|
||
displOrdinal = 1
|
||
});
|
||
ftpMemWrite.Add("setArt", new dataConf()
|
||
{
|
||
description = "Articolo",
|
||
name = "setArt",
|
||
tipoMem = plcDataType.String,
|
||
displOrdinal = 2
|
||
});
|
||
ftpMemWrite.Add("setPzComm", new dataConf()
|
||
{
|
||
description = "Qta Richiesta",
|
||
name = "setPzComm",
|
||
tipoMem = plcDataType.Int,
|
||
displOrdinal = 3
|
||
});
|
||
memMap.mMapWrite = ftpMemWrite;
|
||
// eseguo setup + invio info configurazione...
|
||
setupMemMap();
|
||
}
|
||
|
||
#endregion Protected Methods
|
||
|
||
#region Private Fields
|
||
|
||
/// <summary>
|
||
/// Ultima verifica presenza dir corrente
|
||
/// </summary>
|
||
private DateTime lastCheckDir = DateTime.Now.AddHours(-1);
|
||
|
||
private int PoweroffTimeoutSec = 100;
|
||
|
||
/// <summary>
|
||
/// Dizionario dei divieti di esecuzione x i vari step
|
||
/// </summary>
|
||
private Dictionary<string, DateTime> StepsVeto = new Dictionary<string, DateTime>();
|
||
|
||
/// <summary>
|
||
/// Periodo veto controllo directory FTP corrente
|
||
/// </summary>
|
||
private int vetoCheckDirSec = 5;
|
||
|
||
/// <summary>
|
||
/// Veto controllo status x log...
|
||
/// </summary>
|
||
private DateTime vetoCheckStatus = DateTime.Now;
|
||
|
||
#endregion Private Fields
|
||
|
||
#region Private Properties
|
||
|
||
/// <summary>
|
||
/// Oggetto configurazione gestione FTP
|
||
/// </summary>
|
||
private FtpTaskList currFtpTaskList { get; set; } = new FtpTaskList();
|
||
|
||
/// <summary>
|
||
/// CLient connessioni FTP
|
||
/// </summary>
|
||
private Manager ftpClientMan { get; set; } = new Manager("", "", "", "", false);
|
||
|
||
/// <summary>
|
||
/// Directpry remota di abse
|
||
/// </summary>
|
||
private string RemoteBaseDir { get; set; } = "";
|
||
|
||
#endregion Private Properties
|
||
|
||
#region Private Methods
|
||
|
||
/// <summary>
|
||
/// Verifica se l'azione sia permessa o in stato veto a tempo
|
||
/// </summary>
|
||
/// <param name="currAct"></param>
|
||
/// <returns></returns>
|
||
private bool ActionEnabled(FtpActConf currAct)
|
||
{
|
||
bool enabled = true;
|
||
// se veto presente
|
||
if (StepsVeto.ContainsKey(currAct.ActionId))
|
||
{
|
||
// controllo scadenza
|
||
enabled = StepsVeto[currAct.ActionId] < DateTime.Now;
|
||
}
|
||
return enabled;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Imposta veto azione corrente
|
||
/// </summary>
|
||
/// <param name="currAct"></param>
|
||
/// <returns></returns>
|
||
private bool ActionResetVeto(FtpActConf currAct)
|
||
{
|
||
bool fatto = false;
|
||
if (StepsVeto.ContainsKey(currAct.ActionId))
|
||
{
|
||
StepsVeto[currAct.ActionId] = DateTime.Now.AddSeconds(currAct.ReExecVeto);
|
||
}
|
||
else
|
||
{
|
||
StepsVeto.Add(currAct.ActionId, DateTime.Now.AddSeconds(currAct.ReExecVeto));
|
||
}
|
||
return fatto;
|
||
}
|
||
|
||
private void addTest(bool pingOk)
|
||
{
|
||
int score = pingOk ? 1 : 0;
|
||
// controllo: se era spenta e risulta ping ok --> reset coda!
|
||
if (B_input == 0 && pingOk)
|
||
{
|
||
B_input = 1;
|
||
QHelp.QueuePing = new DataQueue(IOBConfFull.General.FilenameIOB, "QHelp.QueuePing", false, redisMan);
|
||
lgTrace($"QHelp.QueuePing resetted on addTest");
|
||
}
|
||
QHelp.QueuePing.Enqueue($"{score}");
|
||
while (QHelp.QueuePing.Count > maxQueuePing)
|
||
{
|
||
string res = "";
|
||
QHelp.QueuePing.TryDequeue(out res);
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Esegue l'azione configurata
|
||
/// </summary>
|
||
/// <param name="step"></param>
|
||
/// <returns></returns>
|
||
/// <exception cref="NotImplementedException"></exception>
|
||
private bool doStep(GenActConf.ActionConfig step)
|
||
{
|
||
bool fatto = false;
|
||
string remoteVal = "";
|
||
string localVal = "";
|
||
string sVal = "";
|
||
string actKey = "";
|
||
string actVal = "";
|
||
// faccio switch in base al tipo di azione da eseguire...
|
||
switch (step.Action)
|
||
{
|
||
case GenActConf.ActType.CheckDir:
|
||
if (step.ParamList != null && step.ParamList.Count > 0)
|
||
{
|
||
sw.Restart();
|
||
remoteVal = step.ParamList["RemoteDir"] ?? "";
|
||
//verifico dir remota
|
||
fatto = ftpClientMan.DirExists(remoteVal);
|
||
}
|
||
else
|
||
{
|
||
lgError("Error: missing parameters!");
|
||
}
|
||
sw.Stop();
|
||
if (fatto)
|
||
{
|
||
lgInfo($"Check RemDir: {remoteVal} | {sw.ElapsedMilliseconds:N1} ms");
|
||
}
|
||
break;
|
||
|
||
case GenActConf.ActType.CheckFile:
|
||
break;
|
||
|
||
case GenActConf.ActType.CreateDir:
|
||
if (step.ParamList != null && step.ParamList.Count > 0)
|
||
{
|
||
sw.Restart();
|
||
remoteVal = step.ParamList["RemoteDir"] ?? "";
|
||
//verifico dir remota
|
||
bool dirExist = ftpClientMan.DirExists(remoteVal);
|
||
if (dirExist)
|
||
{
|
||
lgTrace("Error: Folder already exists!");
|
||
}
|
||
else
|
||
{
|
||
fatto = ftpClientMan.CreateDir(remoteVal);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
lgError("Error: missing parameters!");
|
||
}
|
||
sw.Stop();
|
||
if (fatto)
|
||
{
|
||
lgInfo($"Directory {remoteVal} created!| {sw.ElapsedMilliseconds:N1} ms");
|
||
}
|
||
break;
|
||
|
||
case GenActConf.ActType.DelDir:
|
||
break;
|
||
|
||
case GenActConf.ActType.DelFile:
|
||
break;
|
||
|
||
case GenActConf.ActType.DownloadDir:
|
||
|
||
break;
|
||
|
||
case GenActConf.ActType.DownloadFile:
|
||
break;
|
||
|
||
case GenActConf.ActType.GenRandomDir:
|
||
break;
|
||
|
||
case GenActConf.ActType.ListContent:
|
||
break;
|
||
|
||
case GenActConf.ActType.MirrorDirL2R:
|
||
break;
|
||
|
||
case GenActConf.ActType.MirrorDirR2L:
|
||
// eseguo mirroring directory
|
||
actKey = "FtpSync";
|
||
actVal = "SRC --> DEST | Size";
|
||
long fullSize = 0;
|
||
if (step.ParamList != null && step.ParamList.Count > 1)
|
||
{
|
||
sw.Restart();
|
||
remoteVal = step.ParamList["RemoteDir"] ?? "";
|
||
localVal = step.ParamList["LocalDir"] ?? "";
|
||
// verifico esistenza dir locale...
|
||
if (!Directory.Exists(localVal))
|
||
{
|
||
Directory.CreateDirectory(localVal);
|
||
}
|
||
//verifico dir remota
|
||
var preTest = ftpClientMan.DirExists(remoteVal);
|
||
if (preTest)
|
||
{
|
||
// chiamo metodo MIRROR x calcolare esattamente se ci siano stati
|
||
// download di sync...
|
||
var mirResult = ftpClientMan.MirrorRemoteDir(localVal, remoteVal, FluentFTP.FtpFolderSyncMode.Mirror);
|
||
// ciclo cercando eventuali info da emttere in DynData...
|
||
foreach (var result in mirResult)
|
||
{
|
||
// processo solo se size > 0...
|
||
if (result.Size > 0 && result.IsDownload && result.IsSuccess && !result.IsSkipped)
|
||
{
|
||
string objSize = MeasureUtils.SizeSuffix(result.Size, 3);
|
||
actVal = $"Rem2Loc | {result.Name} | {objSize} | {result.RemotePath}";
|
||
sVal = $"{actKey} | {actVal}";
|
||
bool sent = accodaFLog(actKey, sVal, qEncodeFLog(actKey, actVal));
|
||
if (sent)
|
||
{
|
||
trackDynData(actKey, actVal);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
lgTrace($"Skipped sync | {actVal}");
|
||
}
|
||
// traccio dimensione
|
||
fullSize += result.Size;
|
||
}
|
||
// risultato sintetico come successi...
|
||
fatto = mirResult != null && mirResult.Where(x => !x.IsSuccess).Count() == 0;
|
||
// salvo dati ricevuti
|
||
trackExchData(fullSize, 1024);
|
||
|
||
if (!fatto)
|
||
{
|
||
lgError($"Error: {remoteVal} NOT mirrored!");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
lgError($"Dir remota non trovata! RemDir: {remoteVal}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
lgError("Error: missing parameters!");
|
||
}
|
||
sw.Stop();
|
||
if (fatto)
|
||
{
|
||
lgInfo($"Mirror Rem2Loc | RemDir: {remoteVal} | {sw.ElapsedMilliseconds:N1} ms");
|
||
}
|
||
|
||
break;
|
||
|
||
case GenActConf.ActType.PingServer:
|
||
break;
|
||
|
||
case GenActConf.ActType.RemoveFileByName:
|
||
string fName2Del = "";
|
||
int numRem = 0;
|
||
if (step.ParamList != null && step.ParamList.Count > 1)
|
||
{
|
||
sw.Restart();
|
||
remoteVal = step.ParamList["RemoteDir"] ?? "";
|
||
fName2Del = step.ParamList["FileName2Del"] ?? "";
|
||
//verifico dir remota
|
||
fatto = ftpClientMan.DirExists(remoteVal);
|
||
if (fatto)
|
||
{
|
||
// recupero elenco di TUTTI i file presenti
|
||
List<FluentFTP.FtpListItem> resList = ftpClientMan.GetRemoteList(remoteVal, true);
|
||
List<FluentFTP.FtpListItem> list2del = new List<FluentFTP.FtpListItem>();
|
||
// cerco tutti i file che indicano ODL attivo e li elimino
|
||
foreach (var flItem in resList)
|
||
{
|
||
if (flItem.Type == FluentFTP.FtpObjectType.File && flItem.Name.EndsWith(fName2Del))
|
||
{
|
||
list2del.Add(flItem);
|
||
}
|
||
}
|
||
// elimino quelli trovati
|
||
if (list2del.Count > 0)
|
||
{
|
||
var fList = list2del.Select(x => x.FullName).ToList();
|
||
numRem = ftpClientMan.DeleteFileList(fList);
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
lgError("Error: missing parameters!");
|
||
}
|
||
sw.Stop();
|
||
if (fatto)
|
||
{
|
||
lgInfo($"RemoveFileByName | path: {remoteVal} | name: {fName2Del} | # del: {numRem} | {sw.ElapsedMilliseconds:N1} ms");
|
||
}
|
||
|
||
break;
|
||
|
||
case GenActConf.ActType.UploadDir:
|
||
break;
|
||
|
||
case GenActConf.ActType.UploadFile:
|
||
if (step.ParamList != null && step.ParamList.Count > 1)
|
||
{
|
||
sw.Restart();
|
||
localVal = step.ParamList["LocalFile"] ?? "";
|
||
remoteVal = step.ParamList["RemoteFile"] ?? "";
|
||
|
||
//verifico dir remota
|
||
string remoteDir = remoteVal.Substring(0, remoteVal.LastIndexOf("/"));
|
||
bool dirExist = ftpClientMan.DirExists(remoteDir);
|
||
if (!dirExist)
|
||
{
|
||
fatto = ftpClientMan.CreateDir(remoteDir);
|
||
}
|
||
|
||
fatto = ftpClientMan.SendFile(localVal, remoteVal);
|
||
if (!fatto)
|
||
{
|
||
lgError($"Error: {localVal} NOT uploaded!");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
lgError("Error: missing parameters!");
|
||
}
|
||
sw.Stop();
|
||
if (fatto)
|
||
{
|
||
lgInfo($"Upload File: {remoteVal} | {sw.ElapsedMilliseconds:N1} ms");
|
||
}
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
return fatto;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Effettuo lettura file di conf
|
||
/// </summary>
|
||
/// <param name="fileName"></param>
|
||
private void loadFtpConfFile(string fileName)
|
||
{
|
||
string jsonFullPath = Path.Combine(System.Windows.Forms.Application.StartupPath, "DATA", "CONF", fileName);
|
||
lgInfo($"Apertura file {jsonFullPath}");
|
||
using (StreamReader reader = new StreamReader(jsonFullPath))
|
||
{
|
||
string jsonData = reader.ReadToEnd().Replace("\n", "").Replace("\r", "");
|
||
if (!string.IsNullOrEmpty(jsonData))
|
||
{
|
||
lgDebug($"File json composto da {jsonData.Length} caratteri");
|
||
try
|
||
{
|
||
currFtpTaskList = JsonConvert.DeserializeObject<FtpTaskList>(jsonData);
|
||
lgDebug($"Decodifica aree FtpTaskList: trovati {currFtpTaskList.ListTask.Count} gruppi di task FTP");
|
||
}
|
||
catch (Exception exc)
|
||
{
|
||
lgError($"Eccezione in decodifica conf json FTP:{Environment.NewLine}{exc}");
|
||
}
|
||
}
|
||
else
|
||
{
|
||
lgError("Errore in loadFtpConfFile: file json vuoto!");
|
||
}
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// Calcola status ping:
|
||
/// - se ha ‹ 50% coda richiesta --› true
|
||
/// - se ha › 50% coda richiesta --› true se è maggior parte a 1 (true)
|
||
/// </summary>
|
||
/// <returns></returns>
|
||
private bool pingStatusOk()
|
||
{
|
||
bool answ = false;
|
||
long numVal = QHelp.QueuePing.Count;
|
||
if (numVal > maxQueuePing / 2)
|
||
{
|
||
var listaValori = QHelp.QueuePing.ToList();
|
||
long numOk = listaValori.Where(x => x == "1").Count();
|
||
long numKo = numVal - numOk;
|
||
answ = numOk >= numKo;
|
||
lgTrace($"PING ok per: {numOk} > {numKo}");
|
||
}
|
||
else
|
||
{
|
||
lgTrace($"PING check: {answ} per mancanza dati minimi test");
|
||
}
|
||
return answ;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Rimuove eventuali file placeholder di ODL corrente preesistenti
|
||
/// </summary>
|
||
/// <param name="remDir"></param>
|
||
/// <param name="fNameOdl"></param>
|
||
private bool RemPlaceholder(string remDir, string fNameOdl)
|
||
{
|
||
bool fatto = false;
|
||
try
|
||
{
|
||
Dictionary<string, string> currActParam = new Dictionary<string, string>();
|
||
currActParam.Add("RemoteDir", remDir);
|
||
currActParam.Add("FileName2Del", fNameOdl);
|
||
GenActConf.ActionConfig currAct = new GenActConf.ActionConfig()
|
||
{
|
||
Id = "01",
|
||
Description = "Clean Curr ODL Files",
|
||
Action = GenActConf.ActType.RemoveFileByName,
|
||
ParamList = currActParam
|
||
};
|
||
// eseguo step...
|
||
fatto = doStep(currAct);
|
||
}
|
||
catch (Exception exc)
|
||
{
|
||
lgError($"Eccezione in RemPlaceholder{Environment.NewLine}{exc}");
|
||
}
|
||
return fatto;
|
||
}
|
||
|
||
/// <summary>
|
||
/// Invia il file dell'ODL attivo
|
||
/// </summary>
|
||
/// <param name="locFile"></param>
|
||
/// <param name="remFile"></param>
|
||
/// <param name="fileContent"></param>
|
||
private bool SendOdlActFile(string locFile, string remFile, string fileContent)
|
||
{
|
||
bool taskOk = false;
|
||
Dictionary<string, string> currActParam = new Dictionary<string, string>();
|
||
// creo file locale
|
||
File.WriteAllText(locFile, fileContent);
|
||
// invio file x ODL attivo
|
||
currActParam.Add("LocalFile", locFile);
|
||
currActParam.Add("RemoteFile", remFile);
|
||
GenActConf.ActionConfig currAct = new GenActConf.ActionConfig()
|
||
{
|
||
Id = "01",
|
||
Description = "Upload File",
|
||
Action = GenActConf.ActType.UploadFile,
|
||
ParamList = currActParam
|
||
};
|
||
// eseguo step...
|
||
taskOk = doStep(currAct);
|
||
return taskOk;
|
||
}
|
||
|
||
#endregion Private Methods
|
||
}
|
||
} |