Merge branch 'release/FixFimatExport01'

This commit is contained in:
Samuele Locatelli
2023-04-06 12:59:15 +02:00
15 changed files with 428 additions and 380 deletions
+1
View File
@@ -116,6 +116,7 @@ namespace IOB_UT_NEXT
public string Note { get; set; } = "";
public string CodCli { get; set; } = "";
public DateTime InsertDate { get; set; } = DateTime.Now;
public string Recipe { get; set; } = "";
public string CodFase
{
+16 -4
View File
@@ -720,10 +720,7 @@ namespace IOB_UT_NEXT
{
string dirPath = file.Substring(0, file.LastIndexOf('\\'));
// verifico directory
if (!Directory.Exists(dirPath))
{
Directory.CreateDirectory(dirPath);
}
checkDir(dirPath);
string[] lines = dictionary.OrderBy(i => i.Key).Select(kvp => kvp.Key + ":" + kvp.Value).ToArray();
try
{
@@ -735,6 +732,21 @@ namespace IOB_UT_NEXT
}
}
/// <summary>
/// Test esistenza/creazione directory
/// </summary>
/// <param name="dirPath"></param>
public static void checkDir(string dirPath)
{
if (!Directory.Exists(dirPath))
{
lg.Info($"Dir not found: {dirPath}");
Directory.CreateDirectory(dirPath);
lg.Info($"reated local dir {dirPath}");
}
}
#endregion Public Methods
#region Protected Properties
+3 -11
View File
@@ -240,10 +240,7 @@ namespace IOB_UT_NEXT
else if (theEntry.IsDirectory)
{
string strNewDirectory = @"" + baseDirectory + @"\" + theEntry.Name;
if (!Directory.Exists(strNewDirectory))
{
Directory.CreateDirectory(strNewDirectory);
}
baseUtils.checkDir(strNewDirectory);
}
}
ZipStream.Close();
@@ -309,13 +306,8 @@ namespace IOB_UT_NEXT
}
else if (theEntry.IsDirectory)
{
string strNewDirectory = @"" + baseDirectory + @"\" +
theEntry.Name;
if (!Directory.Exists(strNewDirectory))
{
Directory.CreateDirectory(strNewDirectory);
}
string strNewDirectory = @"" + baseDirectory + @"\" + theEntry.Name;
baseUtils.checkDir(strNewDirectory);
}
}
ZipStream.Close();
+2 -2
View File
@@ -18,9 +18,9 @@ namespace IOB_UT_NEXT
/// </summary>
public Dictionary<string, int> fileDecod { get; set; } = new Dictionary<string, int>();
/// <summary>
/// Lista dei percorsi filepath attivi x gestioni IN/OUT varie
/// Lista ulteriori configurazioni KeyValuePair
/// </summary>
public Dictionary<string, string> actPath { get; set; } = new Dictionary<string, string>();
public Dictionary<string, string> optKVP { get; set; } = new Dictionary<string, string>();
}
}
+1 -1
View File
@@ -1602,7 +1602,7 @@ namespace IOB_WIN_NEXT
string dirPath = $"{path}\\DATA\\{IOBConf.serverData.ClientInstall}";
string fullPath = $"{dirPath}\\{fileName}";
// verifica directory
Directory.CreateDirectory(dirPath);
baseUtils.checkDir(dirPath);
// salvataggio
File.WriteAllText(fullPath, confJson);
@@ -58,7 +58,7 @@ ENABLE_DYN_DATA=FALSE
FORCE_DYN_DATA=TRUE
ENABLE_DATA_FILTER=TRUE
ENABLE_CLI_RESTART=TRUE
MAX_ELAPSED_TIME_SEC=120
MAX_ELAPSED_TIME_SEC=60
MAX_TRY_PING=3
DISABLE_SEND_WDST=TRUE
FTP_SERVER=192.168.60.234
+2 -2
View File
@@ -45,13 +45,13 @@ CLI_INST=SteamWareSim
;STARTLIST=BAGLIETTO_CIMOLAI_01
;STARTLIST=SIMUL_01
;STARTLIST=GIACO_SAIM_003
;STARTLIST=SIMUL_01
;STARTLIST=PIZ09
;STARTLIST=IMI_RIMOR_SAB_01
;STARTLIST=IMI_RIMOR_SAB_02
;STARTLIST=IMI_RIMOR_VER_01
;STARTLIST=IMI_RIMOR_VER_02
;STARTLIST=IMI_PAMA_392
STARTLIST=IMI_PAMA_392
;STARTLIST=Tend_FIMAT_01
STARTLIST=SIMUL_02
MAXCNC=10
-1
View File
@@ -80,7 +80,6 @@ TC_MAX_INCR=5
MAX_PZ_INCR_PERC=1000
; conf parametri memoria READ/WRITE
PARAM_CONF=SIMUL_02.json
;conf test FTP
FTP_SERVER=ftp.steamware.net
FTP_USER=testftpuser
+15
View File
@@ -95,5 +95,20 @@
"NumPed": 11,
"PackPed": 12,
"PesoPack": 13
},
"optKVP": {
"hasRecipe": true,
"maxPodlQty": 530,
"useLocalRecipe": true,
"path-locBase": "C:\\MesData\\Local",
"path-remBase": "C:\\MesData\\Remote",
"path-00-Arch": "ArchivioRicette\\FIMAT",
"path-01-Temp": "01-Temp\\FIMAT",
"path-02-Sent": "02-Inviate\\FIMAT",
"path-03-Recv": "03-Ricevute\\FIMAT",
"path-04-remW": "C:\\MesData\\Remote\\Queue2",
"path-05-remR": "C:\\MesData\\Remote\\Dosed",
"replace-<Variant>": "<Variant>{{PODL}}",
"replace-<Info1>": "<Info1>Kg{{Qty}} | {{Note}}"
}
}
+1 -4
View File
@@ -63,21 +63,18 @@ ENABLE_DYN_DATA=TRUE
FORCE_DYN_DATA=TRUE
; gestione delta minimo accettabile tra min/MAX
DELTA_VAL=0.1
; clock base (da 10ms)
timerIntMs=10
; conf parametri memoria READ/WRITE
PARAM_CONF=Tend_FIMAT_01.json
NO_PING=FALSE
; conf blocchi memoria x READ
MEM_BLOCK=Tend_FIMAT_01_MBlock.json
; conf aree allarme
ALARM_CONF=Tend_FIMAT_01_alarm.json
; rimozione check limiti min/max dynData
disDynDataRangeCheck=true
[BRANCH]
NAME=master
+16 -8
View File
@@ -301,15 +301,23 @@
"ManualBitCond": "40002.1=1",
"EStopBitCond": "40002.0=1",
"WorkIntCond": "40000|1=3",
"VarInt2Translate": "40001,40007",
"VarBit2Translate": "40003"
//"VarInt2Translate": "40001,40007",
//"VarBit2Translate": "40003"
},
"actPath": {
"recTempPath": "DATA/CONF/RECIPE/FIMAT",
"recSentPath": "DATA/SENT",
"recDestPath": "y:/",
"ordExecPath": "Z:/",
"ordArchPath": "DATA/RETURN"
"optKVP": {
"hasRecipe": true,
"maxPodlQty": 530,
"useLocalRecipe": true,
"path-locBase": "E:\\MesData\\",
"path-remBase": "C:\\MesData\\Remote",
"path-00-Arch": "ArchivioRicette\\FIMAT",
"path-01-Temp": "01-Temp\\FIMAT",
"path-02-Sent": "02-Inviate\\FIMAT",
"path-03-Recv": "03-Ricevute\\FIMAT",
"path-04-remW": "Y:\\",
"path-05-remR": "Z:\\",
"replace-<Variant>": "<Variant>{{PODL}}",
"replace-<Info1>": "<Info1>Kg{{Qty}} | {{Note}}"
},
"itemTranslation": {
"40001_0": "Stato non aggiornato per mancanza comunicazione da computer",
+6 -2
View File
@@ -886,7 +886,9 @@
<None Include="DATA\CONF\VL24.json" />
<None Include="DATA\CONF\SIMUL_04.json" />
<None Include="DATA\CONF\SIMUL_03.json" />
<None Include="DATA\CONF\SIMUL_02.json" />
<None Include="DATA\CONF\SIMUL_02.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="DATA\CONF\SIMUL_01.json" />
<None Include="DATA\CONF\INTERCL_02.json" />
<None Include="DATA\CONF\INTERCL_01.json" />
@@ -912,7 +914,9 @@
<None Include="DATA\CONF\SIM_DP_02.ini" />
<None Include="DATA\CONF\SIM_DP_01.ini" />
<None Include="DATA\CONF\SIMUL_01.ini" />
<None Include="DATA\CONF\SIMUL_02.ini" />
<None Include="DATA\CONF\SIMUL_02.ini">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="DATA\CONF\3006.ini" />
<None Include="DATA\CONF\3007.ini" />
<None Include="DATA\CONF\3010.ini" />
+281 -31
View File
@@ -2133,6 +2133,8 @@ namespace IOB_WIN_NEXT
processAutoOdl();
// verifico se devo gestire auto generazione dossier quotidiana
processAutoDossier();
// effettua gestione import file se configurato...
processFileImport();
}
else if (ciclo == gatherCycle.VLF)
{
@@ -2280,6 +2282,22 @@ namespace IOB_WIN_NEXT
return outVal;
}
/// <summary>
/// Cerca se esiste il parametro opzionale nei KVP (JSON) e lo restituisce
/// </summary>
/// <param name="key"></param>
/// <returns></returns>
public string getOptJsonKVP(string key)
{
string answ = "";
// controllo SE HO il parametro
if (memMap.optKVP.ContainsKey(key))
{
answ = memMap.optKVP[key];
}
return answ;
}
/// <summary>
/// Cerca se esiste il parametro opzionale e lo restituisce
/// </summary>
@@ -4277,6 +4295,11 @@ namespace IOB_WIN_NEXT
/// </summary>
protected DateTime forcePzResetUntil = DateTime.Now.AddMinutes(-1);
/// <summary>
/// Determina se siano gestite le ricette
/// </summary>
protected bool hasRecipe = false;
/// <summary>
/// Array dei contatori x segnali blinking
/// </summary>
@@ -4337,6 +4360,11 @@ namespace IOB_WIN_NEXT
/// </summary>
protected int maxErroriCheck = utils.CRI("maxErroriCheck");
/// <summary>
/// Quantità massima per singola ricetta (per determinare num ricette da inviare)
/// </summary>
protected int maxQtyPerFile = 0;
/// <summary>
/// Num massimo di errori di rete read (dal PLC)
/// </summary>
@@ -4382,6 +4410,11 @@ namespace IOB_WIN_NEXT
/// </summary>
protected Dictionary<string, VCData> TSVC_Data = new Dictionary<string, VCData>();
/// <summary>
/// Indica se usare archivio locale ricette vs scarico http/REST
/// </summary>
protected bool useLocalRecipe = true;
/// <summary>
/// Dizionario di VARIABILI da trattare come eventi (da inviare quando cambiano oppure a
/// scadenza periodo...)
@@ -4547,13 +4580,58 @@ namespace IOB_WIN_NEXT
/// Elenco di valori da tradurre da valori BIT (es ModBus TCP FIMAT)
/// NB: potrebbero essere contemporaneamente attivi + valori e + traduzioni
/// </summary>
protected Dictionary<string,string> OptVar2TranslBit { get; set; } = new Dictionary<string, string>();
protected Dictionary<string, string> OptVar2TranslBit { get; set; } = new Dictionary<string, string>();
/// <summary>
/// Elenco di valori da tradurre da valori INT esclusivi (es ModBus TCP FIMAT)
/// </summary>
protected Dictionary<string, string> OptVar2TranslInt { get; set; } = new Dictionary<string, string>();
/// <summary>
/// Elenco dei path utili x processing
/// </summary>
protected Dictionary<string, string> pathList { get; set; } = new Dictionary<string, string>();
/// <summary>
/// Gestione archivio serializzato PODL inviati (tramite file temp locale/REDIS)
/// </summary>
protected Dictionary<int, PODLModel> POdlSentFileArch
{
get
{
Dictionary<int, PODLModel> answ = new Dictionary<int, PODLModel>();
string redKey = redisMan.redHash($"IOB:Cache:{cIobConf.codIOB}:POdlSent");
string rawData = redisMan.getRSV(redKey);
if (!string.IsNullOrEmpty(rawData))
{
try
{
answ = JsonConvert.DeserializeObject<Dictionary<int, PODLModel>>(rawData);
lgInfo($"Rilettura status POdlSentFileArch: trovati {answ.Count} record");
}
catch (Exception exc)
{
lgError($"Errore in deserializzazione POdlSentFileArch{Environment.NewLine}{exc}");
}
}
return answ;
}
set
{
string rawVal = JsonConvert.SerializeObject(value);
string redKey = redisMan.redHash($"IOB:Cache:{cIobConf.codIOB}:POdlSent");
redisMan.setRSV(redKey, rawVal);
lgDebug($"Salvataggio status POdlSentFileArch | {value.Count} record");
}
}
/// <summary>
/// Elenco corrente (in memory) PODL inviati all'impianto
/// chiave: idxPODL
/// valore: record PODL
/// </summary>
protected Dictionary<int, PODLModel> POdlSentList { get; set; } = new Dictionary<int, PODLModel>();
/// <summary>
/// Indica se sia stato resettato un contapezzi
/// </summary>
@@ -4577,6 +4655,11 @@ namespace IOB_WIN_NEXT
}
}
/// <summary>
/// Definizioni x replace in file ricette
/// </summary>
protected Dictionary<string, string> RecipeReplRules { get; set; } = new Dictionary<string, string>();
/// <summary>
/// Indica se vada inviata la key richiesta con lo split/autoODL
/// </summary>
@@ -5103,15 +5186,9 @@ namespace IOB_WIN_NEXT
// se ok --> sposto invio
DateTime adesso = DateTime.Now;
string archBasePath = Path.Combine(basePath, "DATA", "HIST", $"{adesso:yyyy}");
if (!Directory.Exists(archBasePath))
{
Directory.CreateDirectory(archBasePath);
}
baseUtils.checkDir(archBasePath);
string archPath = Path.Combine(archBasePath, $"{adesso:MMddHHmmss}");
if (!Directory.Exists(archPath))
{
Directory.CreateDirectory(archPath);
}
baseUtils.checkDir(archPath);
lgInfo($"Richiesta Dir Move | {localPath} | {archPath}");
foreach (var item in fileList)
{
@@ -5143,12 +5220,7 @@ namespace IOB_WIN_NEXT
string basePath = Application.StartupPath;
string tempDir = Path.Combine(basePath, locDir);
lgInfo($"iobWriteLocalCSV | locDir: {locDir} | sAddHeader: {sAddHeader} | tempDir: {tempDir}");
if (!Directory.Exists(tempDir))
{
lgInfo("CSV: tempDir not found");
Directory.CreateDirectory(tempDir);
lgInfo($"CSV: created local dir {tempDir}");
}
baseUtils.checkDir(tempDir);
string filePath = Path.Combine(tempDir, "articoli.csv");
answ = DataExport.SaveToCsv(ListaArticoli, filePath, addHeader);
if (answ)
@@ -5196,9 +5268,10 @@ namespace IOB_WIN_NEXT
}
return answ;
}
/// <summary>
/// Effettua traduzione ITEM da LUT parametrica (key: lemma) del file di conf, se non
/// trovo uso key
/// Effettua traduzione ITEM da LUT parametrica (key: lemma) del file di conf, se non trovo
/// uso key
/// </summary>
/// <param name="lemma"></param>
/// <returns></returns>
@@ -5622,6 +5695,7 @@ namespace IOB_WIN_NEXT
setupMemMap();
setupOptMemPar();
setupFileDecod();
setupSpecialParams();
}
catch (Exception exc)
{
@@ -5726,15 +5800,9 @@ namespace IOB_WIN_NEXT
string errore = "";
// verifico archivio
string dirArchive = Path.Combine(fileImportFolder, "archive");
if (!Directory.Exists(dirArchive))
{
Directory.CreateDirectory(dirArchive);
}
baseUtils.checkDir(dirArchive);
string dirConvert = Path.Combine(fileImportFolder, "converted");
if (!Directory.Exists(dirConvert))
{
Directory.CreateDirectory(dirConvert);
}
baseUtils.checkDir(dirConvert);
Dictionary<string, TimeSpan> statsColl = new Dictionary<string, TimeSpan>();
// cerco files da convertire
var listFiles2Conv = Directory.GetFiles(fileImportFolder, fileImportType);
@@ -5800,10 +5868,7 @@ namespace IOB_WIN_NEXT
if (!answ)
{
string dirError = $"{fileImportFolder}/errors";
if (!Directory.Exists(dirError))
{
Directory.CreateDirectory(dirError);
}
baseUtils.checkDir(dirError);
// sposto file...
File.Move(fileItem, $"{dirError}/{Path.GetFileName(fileItem)}");
// segno errore!
@@ -5892,6 +5957,158 @@ namespace IOB_WIN_NEXT
}
}
/// <summary>
/// Prepara la ricetta indicata partendo dai dati della ricetta template + dati ODL di riferimento
/// </summary>
/// <param name="recFilePath">Path del file template della ricetta</param>
/// <param name="podlReq">Record del PODL da inviare</param>
/// <returns>Path della ricetta da inviare</returns>
protected virtual bool RecipePrepare(string tempPath, string recFilePath, PODLModel podlReq)
{
bool fatto = false;
// leggo il file template ricetta
var rawData = File.ReadAllText(recFilePath);
string fixContent = rawData;
// eseguo sostituzioni
foreach (var rule in RecipeReplRules)
{
string replVal = rule.Value;
// calcolo la sostituzione per i valori SPECIFICI...
if (replVal.Contains("{{PODL}}"))
{
replVal = replVal.Replace("{{PODL}}", $"PODL{podlReq.IdxPromessa:00000000}");
}
if (replVal.Contains("{{Qty}}"))
{
replVal = replVal.Replace("{{Qty}}", $"{podlReq.NumPezzi}");
}
if (replVal.Contains("{{Note}}"))
{
replVal = replVal.Replace("{{Note}}", $"{podlReq.Note}");
}
fixContent = fixContent.Replace(rule.Key, replVal);
}
// scrivo file (secondo quantità...)!
string destPath = Path.Combine(tempPath, $"PODL{podlReq.IdxPromessa:00000000}.xml");
if (podlReq.NumPezzi <= maxQtyPerFile)
{
File.WriteAllText(destPath, fixContent);
fatto = true;
}
else
{
int numReq = (int)Math.Ceiling((double)podlReq.NumPezzi / maxQtyPerFile);
// splitto e scrivo...
for (int i = 1; i <= numReq; i++)
{
destPath = Path.Combine(tempPath, $"PODL{podlReq.IdxPromessa:00000000}-{i}.xml");
File.WriteAllText(destPath, fixContent);
}
fatto = true;
}
return fatto;
}
/// <summary>
/// Prepara le ricette dato path temp scaricando elenco PODL
/// </summary>
/// <param name="tempPath">
/// Percorso temp di appoggio x preparare ricette (compreso nome macchina)
/// </param>
/// <param name="useLocal">
/// Indica se usare le copie locali delle ricette oppure richiedere da remoto (REST get)
/// </param>
/// <returns></returns>
protected virtual bool RecipeReqWriteLocal(string tempPath, bool useLocal)
{
bool fatto = false;
List<PODLModel> reqPOdlList = new List<PODLModel>();
// per prima cosa recupero elenco PODL da gestire....
var rawListPODL = callUrl(urlGetCurrPODL, false);
if (!string.IsNullOrEmpty(rawListPODL))
{
try
{
reqPOdlList = JsonConvert.DeserializeObject<List<PODLModel>>(rawListPODL);
}
catch (Exception exc)
{
lg.Error($"Errore: chiamata elenco PODL ha restituito errore{Environment.NewLine}{exc}");
}
}
else
{
lg.Error($"Errore: chiamata elenco PODL ({urlGetCurrPODL}) ha restituito valore vuoto");
}
// proseguo se ne ho trovati...
if (reqPOdlList.Count > 0)
{
// in questo elenco devo considerare solo PODL ATTIVI...
List<PODLModel> actPOdlList = reqPOdlList.Where(x => x.Attivabile).ToList();
// da questo elenco,se è rimasto qualcosa, ciclo x ricette da inviare
foreach (var actPodlReq in actPOdlList)
{
// devo escludere i PODL già gestiti
if (!POdlSentList.ContainsKey(actPodlReq.IdxPromessa))
{
string recFilePath = "";
try
{
// calcolo path ricetta...
recFilePath = Path.Combine(pathList["path-locBase"], pathList["path-00-Arch"], actPodlReq.Recipe);
// preparo file ricetta x PODL
bool fileOk = RecipePrepare(tempPath, recFilePath, actPodlReq);
if (fileOk)
{
// aggiungo PODL ad elenco dei processati
POdlSentList.Add(actPodlReq.IdxPromessa, actPodlReq);
// indico fatto (almeno per 1 è ok...)
fatto = true;
}
}
catch (Exception exc)
{
lgError($"recipeReqWriteLocal | Errore durante ciclo verifica ricetta | idxPODL {actPodlReq.IdxPromessa} | recFilePath {recFilePath}{Environment.NewLine}{exc}");
}
}
}
// salvo su file elenco PODL gestiti/inviati
POdlSentFileArch = POdlSentList;
}
return fatto;
}
/// <summary>
/// Effettua invio delle ricette alla macchina
/// </summary>
/// <param name="localPath">Area dove si trovano i fiel da trasmettere</param>
/// <param name="localArch">Area archivio</param>
/// <param name="remotePath">Area remota dove inviare files</param>
/// <returns></returns>
protected bool RecipeSend(string localPath, string localArch, string remotePath)
{
bool fatto = false;
// recupero elenco files...
var fileList = Directory.GetFiles(localPath);
string srcName = "";
string archName = "";
string destName = "";
if (fileList != null && fileList.Count() > 0)
{
foreach (var file in fileList)
{
srcName = Path.Combine(localPath, file);
archName = Path.Combine(localArch, file);
destName = Path.Combine(remotePath, file);
File.Copy(srcName, destName, true);
File.Move(srcName, archName);
}
fatto = true;
}
return fatto;
}
/// <summary>
/// Cancella dal server i task eseguiti
/// </summary>
@@ -6225,6 +6442,39 @@ namespace IOB_WIN_NEXT
}
}
/// <summary>
/// Init parametri speciali, tipicamente KVP opzionali da json
/// </summary>
protected virtual void setupSpecialParams()
{
string sCond = "";
// per prima cosa inizializzo lista PODL inviati
POdlSentList = POdlSentFileArch;
// check modalità ricetta attiva
bool.TryParse(getOptJsonKVP("hasRecipe"), out hasRecipe);
// verifico se usare ricette locali/http...
bool.TryParse(getOptJsonKVP("useLocalRecipe"), out useLocalRecipe);
// recupero quantitativo massimo KG x PODL
int.TryParse(getOptJsonKVP("maxPodlQty"), out maxQtyPerFile);
// recupero le folder specifiche x IN/OUT ricette filtrando direttamente l'area di memoria...
sCond = "path";
var dirList = memMap.optKVP
.Where(x => x.Key.StartsWith(sCond))
.ToList();
pathList = dirList.ToDictionary(x => x.Key, x => x.Value);
// gestione replace in file ricette...
sCond = "replace-";
var ruleList = memMap.optKVP
.Where(x => x.Key.StartsWith(sCond))
.ToList();
RecipeReplRules = ruleList.ToDictionary(x => x.Key.Replace(sCond, ""), x => x.Value);
}
/// <summary>
/// Cleanup stringa x impiego tipo ident da char dubbi
/// </summary>
@@ -6675,7 +6925,7 @@ namespace IOB_WIN_NEXT
if (!OptVar2TranslBit.ContainsKey(memKey))
{
// init traduzione vuota
OptVar2TranslBit.Add(memKey,"");
OptVar2TranslBit.Add(memKey, "");
}
}
}
@@ -6693,7 +6943,7 @@ namespace IOB_WIN_NEXT
if (!OptVar2TranslInt.ContainsKey(memKey))
{
// init traduzione vuota
OptVar2TranslInt.Add(memKey,"");
OptVar2TranslInt.Add(memKey, "");
}
}
}
+62 -308
View File
@@ -1,6 +1,8 @@
using System;
using IOB_UT_NEXT;
using System;
using System.Collections.Generic;
using System.Xml.Serialization;
using System.IO;
using System.Linq;
using static IOB_UT_NEXT.CustomObj;
namespace IOB_WIN_NEXT
@@ -28,6 +30,7 @@ namespace IOB_WIN_NEXT
{
lgInfo("NEW IOB ModBus TCP FIMAT");
setupSpecialParams();
// provo lettura una prima volta i dati DYN
if (currPLC != null && currPLC.Connected)
{
@@ -36,7 +39,6 @@ namespace IOB_WIN_NEXT
processDynData();
if (EnableTest)
{
processDataSync();
testReadExt();
}
}
@@ -45,312 +47,22 @@ namespace IOB_WIN_NEXT
lgError($"Eccezione in processDynData iniziale x ModBus TCP FIMAT:{Environment.NewLine}{exc}");
}
}
}
/// <summary>
/// Elenco dei path validi x processing, tra cui
/// - archivio template ricette
/// - archivio PODL ricette inviate
/// - path remota invio PODL
/// - path remota lettura tasl ([P]ODL) svolti
/// - archivio task ([P]ODL) recuperati
/// </summary>
protected List<string> pathlist { get; set; } = new List<string>();
/// <summary>
/// Prepara la ricetta indicata partendo dai dati della ricetta template + dati ODL di riferimento
/// </summary>
/// <param name="recTemplatePath">Path del template della ricetta</param>
/// <param name="podlReq">Record del PODL da inviare</param>
/// <returns>Path della ricetta da inviare</returns>
protected string prepareRecipe(string recTemplatePath, PODLModel podlReq)
{
string recFilePath = "";
// leggo il file template ricetta
return recFilePath;
}
/// <summary>
/// Effettua invio XML del PODL dato il suo path verso la macchina
/// </summary>
/// <param name="odlRecipePath"></param>
/// <returns></returns>
protected bool sendRecipe(string odlRecipePath)
{
bool fatto = false;
return fatto;
}
/// <summary>
/// Verifica l'elenco dei PODL (Attivi) per la macchina e verifica se vadano inviati (controllando archivio PODL inviati
/// </summary>
/// <param name="actPOdlList"></param>
/// <returns></returns>
protected bool trySendPOdl(List<PODLModel> actPOdlList)
{
bool answ = false;
foreach (var item in actPOdlList)
if (EnableTest)
{
// verifico se sia nella folder di quelli inviati
// se non presente preparo, leggendo conf del NUMERO ricetta (e configurandola come 10'000+num???)
// infine invio
processDataSync();
}
return answ;
}
#endregion Public Constructors
#region Public Classes
#region Protected Fields
[XmlRoot(ElementName = "A_Recipe")]
public class ARecipe
{
#region Public Properties
/// <summary>
/// Quantità massima PODL prima di fare split ordine (default 999'999)
/// </summary>
protected int maxPodlQty = 999999;
[XmlElement(ElementName = "ColRecipe")]
public List<ColRecipe> ColRecipe { get; set; }
[XmlElement(ElementName = "DesRecipe")]
public DesRecipe DesRecipe { get; set; }
[XmlAttribute(AttributeName = "xsi", Namespace = "http://www.w3.org/2000/xmlns/")]
public string Xsi { get; set; }
[XmlAttribute(AttributeName = "noNamespaceSchemaLocation", Namespace = "http://www.w3.org/2001/XMLSchema-instance")]
public string NoNamespaceSchemaLocation { get; set; }
#endregion Public Properties
}
[XmlRoot(ElementName = "ColData")]
public class ColData
{
#region Public Properties
[XmlElement(ElementName = "ColourCode")]
public string ColourCode { get; set; }
[XmlElement(ElementName = "CompNumber")]
public int CompNumber { get; set; }
[XmlElement(ElementName = "Cost")]
public double Cost { get; set; }
[XmlElement(ElementName = "Date")]
public DateTime Date { get; set; }
[XmlElement(ElementName = "Description")]
public string Description { get; set; }
[XmlElement(ElementName = "DosDuration")]
public int DosDuration { get; set; }
[XmlElement(ElementName = "DosError")]
public string DosError { get; set; }
[XmlElement(ElementName = "DosNote")]
public object DosNote { get; set; }
[XmlElement(ElementName = "Origin")]
public string Origin { get; set; }
[XmlElement(ElementName = "PartsPerc")]
public double PartsPerc { get; set; }
[XmlElement(ElementName = "PartsWeight")]
public double PartsWeight { get; set; }
[XmlElement(ElementName = "TypComp")]
public string TypComp { get; set; }
[XmlElement(ElementName = "Weight-gr")]
public double Weightgr { get; set; }
[XmlElement(ElementName = "Weight-gr-dosed")]
public double Weightgrdosed { get; set; }
[XmlElement(ElementName = "Weight-gr-prev")]
public double Weightgrprev { get; set; }
[XmlElement(ElementName = "Weight-gr-total")]
public double Weightgrtotal { get; set; }
#endregion Public Properties
}
[XmlRoot(ElementName = "ColRecipe")]
public class ColRecipe
{
#region Public Properties
[XmlElement(ElementName = "ColData")]
public ColData ColData { get; set; }
#endregion Public Properties
}
[XmlRoot(ElementName = "DesData")]
public class DesData
{
#region Public Properties
[XmlElement(ElementName = "Article")]
public string Article { get; set; }
[XmlElement(ElementName = "CustDrumCode")]
public object CustDrumCode { get; set; }
[XmlElement(ElementName = "Customer")]
public object Customer { get; set; }
[XmlElement(ElementName = "Date")]
public DateTime Date { get; set; }
[XmlElement(ElementName = "Design")]
public int Design { get; set; }
[XmlElement(ElementName = "DosDuration")]
public int DosDuration { get; set; }
[XmlElement(ElementName = "DosedLine")]
public int DosedLine { get; set; }
[XmlElement(ElementName = "DosType")]
public string DosType { get; set; }
[XmlElement(ElementName = "DrumCode")]
public double DrumCode { get; set; }
[XmlElement(ElementName = "DrumInitialWeightKG")]
public double DrumInitialWeightKG { get; set; }
[XmlElement(ElementName = "DrumTag")]
public int DrumTag { get; set; }
[XmlElement(ElementName = "DrumType")]
public int DrumType { get; set; }
[XmlElement(ElementName = "Info1")]
public object Info1 { get; set; }
[XmlElement(ElementName = "Info2")]
public object Info2 { get; set; }
[XmlElement(ElementName = "Info3")]
public object Info3 { get; set; }
[XmlElement(ElementName = "Info4")]
public object Info4 { get; set; }
[XmlElement(ElementName = "Info5")]
public object Info5 { get; set; }
[XmlElement(ElementName = "Info6")]
public object Info6 { get; set; }
[XmlElement(ElementName = "Info7")]
public object Info7 { get; set; }
[XmlElement(ElementName = "Info8")]
public object Info8 { get; set; }
[XmlElement(ElementName = "Info9")]
public object Info9 { get; set; }
[XmlElement(ElementName = "LotID")]
public object LotID { get; set; }
[XmlElement(ElementName = "Note1")]
public string Note1 { get; set; }
[XmlElement(ElementName = "Note2")]
public object Note2 { get; set; }
[XmlElement(ElementName = "OrderCode")]
public string OrderCode { get; set; }
[XmlElement(ElementName = "Prio")]
public string Prio { get; set; }
[XmlElement(ElementName = "Quantity-kg")]
public double Quantitykg { get; set; }
[XmlElement(ElementName = "Quantity-kg-dosed")]
public double Quantitykgdosed { get; set; }
[XmlElement(ElementName = "RecipeStatus")]
public string RecipeStatus { get; set; }
[XmlElement(ElementName = "RecipeType")]
public string RecipeType { get; set; }
[XmlElement(ElementName = "RecName")]
public int RecName { get; set; }
[XmlElement(ElementName = "ReqType")]
public string ReqType { get; set; }
[XmlElement(ElementName = "Screen")]
public object Screen { get; set; }
[XmlElement(ElementName = "Sequence")]
public int Sequence { get; set; }
[XmlElement(ElementName = "SequenceTot")]
public int SequenceTot { get; set; }
[XmlElement(ElementName = "Series")]
public int Series { get; set; }
[XmlElement(ElementName = "ServiceType")]
public string ServiceType { get; set; }
[XmlElement(ElementName = "SplitCurrent")]
public int SplitCurrent { get; set; }
[XmlElement(ElementName = "SplitTotal")]
public int SplitTotal { get; set; }
[XmlElement(ElementName = "Taglio-D")]
public double TaglioD { get; set; }
[XmlElement(ElementName = "Taglio-N")]
public double TaglioN { get; set; }
[XmlElement(ElementName = "UM")]
public int UM { get; set; }
[XmlElement(ElementName = "Variant")]
public object Variant { get; set; }
[XmlElement(ElementName = "ViscoName")]
public object ViscoName { get; set; }
[XmlElement(ElementName = "ViscoValue")]
public double ViscoValue { get; set; }
#endregion Public Properties
}
// using System.Xml.Serialization; XmlSerializer serializer = new
// XmlSerializer(typeof(ARecipe)); using (StringReader reader = new StringReader(xml)) { var
// test = (ARecipe)serializer.Deserialize(reader); }
[XmlRoot(ElementName = "DesRecipe")]
public class DesRecipe
{
#region Public Properties
[XmlElement(ElementName = "DesData")]
public DesData DesData { get; set; }
#endregion Public Properties
}
#endregion Public Classes
#endregion Protected Fields
#region Protected Properties
@@ -466,17 +178,59 @@ namespace IOB_WIN_NEXT
B_input = byteSignals;
}
/// <summary>
/// Effettua sync dati
/// Effettua sync dati x PODL attivi
/// </summary>
protected override void processDataSync()
{
// richiesta check autoODL
processAutoOdl();
// richiesta generazione quotidiana dossiers
processAutoDossier();
// effettua gestione import file...
processFileImport();
DateTime adesso = DateTime.Now;
string tempPath = Path.Combine(pathList["path-locBase"], pathList["path-01-Temp"]);
string archPath = Path.Combine(pathList["path-locBase"], pathList["path-02-Sent"], $"{adesso:yyyy}", $"{adesso:MM}");
string remoPath = Path.Combine(pathList["path-locBase"], pathList["path-04-remW"]);
baseUtils.checkDir(tempPath);
baseUtils.checkDir(archPath);
// recupero elenco PODL da processare, check PODL già inviati, save locale
bool create = RecipeReqWriteLocal(tempPath, useLocalRecipe);
// invio ricette a impianto
bool trasmitted = RecipeSend(tempPath, archPath, remoPath);
}
/// <summary>
/// Cerca di recuperare i file generati dall'impianto in merito al processing degli ordini
/// </summary>
/// <returns></returns>
protected override bool processFileImport()
{
bool fatto = false;
// cerca e sposta i NUOVI file
// per ogni file ricevuto controlla se sia corrispondente ad un file inviato (cerca PODL)
// se trova PODL prova ad avviare/chiudere PODL relativo (eventualmente duplicandolo)
return fatto;
}
/// <summary>
/// Verifica l'elenco dei PODL (Attivi) per la macchina e verifica se vadano inviati
/// (controllando archivio PODL inviati)
/// </summary>
/// <param name="actPOdlList"></param>
/// <returns></returns>
protected bool trySendPOdl(List<PODLModel> actPOdlList)
{
bool answ = false;
foreach (var item in actPOdlList)
{
// verifico se sia nella folder di quelli inviati
// se non presente preparo, leggendo conf del NUMERO ricetta (e configurandola come 10'000+num???)
// infine invio
}
return answ;
}
#endregion Protected Methods
+21 -5
View File
@@ -3,6 +3,7 @@ using MapoSDK;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using static IOB_UT_NEXT.CustomObj;
@@ -79,6 +80,7 @@ namespace IOB_WIN_NEXT
simDich = setupSimPar("SIM_DICH");
int.TryParse(getOptPar("SIM_MATR_OPR"), out matrOpr);
}
// riesegue setup PLC
setParamPlc();
// ricarico da server i dati dei pezzi fatti...
lgInfo("Init contapezzi SIMULA: pzCntReload(true)");
@@ -93,17 +95,31 @@ namespace IOB_WIN_NEXT
// parto processando dynData
processDynData();
// test gestione fileImport...
if (!string.IsNullOrEmpty(fileImportFolder))
{
processFileImport();
}
if (!string.IsNullOrEmpty(getOptPar("FTP_AT_START")))
{
// simulazione processo FTP (Cimolai) - FIXME TODO DeleteME
processDataSync();
}
// test ricetta
if (hasRecipe)
{
string tempPath = Path.Combine(pathList["path-locBase"], pathList["path-01-Temp"]);
string archPath = Path.Combine(pathList["path-locBase"], pathList["path-02-Sent"], $"{adesso:yyyy}", $"{adesso:MM}");
string remoPath = Path.Combine(pathList["path-locBase"], pathList["path-04-remW"]);
baseUtils.checkDir(tempPath);
baseUtils.checkDir(archPath);
// recupero elenco PODL da processare, check PODL già inviati, save locale
bool create = RecipeReqWriteLocal(tempPath, useLocalRecipe);
// invio ricette a impianto
bool trasmitted = RecipeSend(tempPath, archPath, remoPath);
}
// test gestione fileImport...
if (!string.IsNullOrEmpty(fileImportFolder))
{
processFileImport();
}
}
#endregion Public Constructors