Files
Mapo-IOB-WIN/IOB-WIN-FTP/Iob/Ftp.cs
T
2026-05-23 22:32:21 +02:00

1019 lines
42 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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
}
}