Files
2025-09-17 16:23:56 +02:00

4956 lines
221 KiB
C#

using MapoSDK;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using SteamWare;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Threading;
namespace MapoDb
{
/// <summary>
/// classe gestione operazioni su DB tramite MapoDb
/// </summary>
public class DataLayer
{
#region Public Fields
/// <summary>
/// Valori config da tabella corrente
/// </summary>
public DS_Utility.ConfigDataTable ListConfig = new DS_Utility.ConfigDataTable();
/// <summary>
/// Oggetto MapoDb impiegato da DataLayer x i suoi accessi ai dati
/// </summary>
public MapoDb MapoDbObj = new MapoDb();
// Table adapter vari...
public DS_applicazioneTableAdapters.AnagraficaGruppiTableAdapter taAG;
public DS_applicazioneTableAdapters.AlarmLogTableAdapter taAlarmLog;
public DS_ProdTempiTableAdapters.AnagArticoliTableAdapter taAnagArt;
public DS_applicazioneTableAdapters.AnagraficaEventiTableAdapter taAnagEventi;
public DS_applicazioneTableAdapters.AnagraficaStatiTableAdapter taAnagStati;
public DS_applicazioneTableAdapters.AnagTagsTableAdapter taAnagTags;
public DS_ArcaTableAdapters.GiacenzeTableAdapter taArcaGiac;
public DS_IntServTableAdapters.ProduzioneAs400TableAdapter taAs400;
public DS_ProdTempiTableAdapters.CalendFesteFerieTableAdapter taCalFF;
public DS_UtilityTableAdapters.CommentiTableAdapter taComm;
public DS_DossParTableAdapters.ConfFluxTableAdapter taConfFlux;
public DS_UtilityTableAdapters.ConfigTableAdapter taConfig;
public DS_ProdTempiTableAdapters.DatiConfermatiTableAdapter taDatiConf;
public DS_ProdTempiTableAdapters.DatiMacchineTableAdapter taDatiMacchine;
public DS_ProdTempiTableAdapters.DatiProduzioneTableAdapter taDatiProd;
public DS_ProdTempiTableAdapters.stp_repDonati_getDatiProdMacchinaTableAdapter taDatiProdMacch;
public DS_ProdTempiTableAdapters.stp_repDonati_getDatiProdMacchinaPeriodoTableAdapter taDatiProdMacchPer;
public DS_ProdTempiTableAdapters.stp_repDonati_getLastStatoDurataMacchinaTableAdapter taDatiStatoMacch;
public DS_applicazioneTableAdapters.DecNumArticoliTableAdapter taDecNA;
public DS_applicazioneTableAdapters.DiarioDichiarazioniTableAdapter taDiarioDich;
public DS_DossParTableAdapters.DossiersTableAdapter taDOSS;
public DS_applicazioneTableAdapters.EventListTableAdapter taEventi;
public DS_applicazioneTableAdapters.FluxLogTableAdapter taFL;
public DS_IntServTableAdapters.TransitoDatiTableAdapter taIS_TrDati;
public DS_IntServTableAdapters.IstanzeKITTableAdapter taIstK;
public DS_applicazioneTableAdapters.KeepAliveTableAdapter taKeepAlive;
public DS_UtilityTableAdapters.v_selListValTableAdapter taListVal;
public DS_ProdTempiTableAdapters.Macchine2SlaveTableAdapter taM2S;
public DS_applicazioneTableAdapters.MacchineTableAdapter taMacchine;
public DS_PlanTableAdapters.MachineParamsTableAdapter taMacParams;
public DS_MAGTableAdapters.ElencoLottiTableAdapter taMagELotti;
public DS_ProdTempiTableAdapters.MappaStatoExplTableAdapter taMSE;
public DS_ProdTempiTableAdapters.ODLTableAdapter taODL;
public DS_applicazioneTableAdapters.AnagraficaOperatoriTableAdapter taOp;
public DS_applicazioneTableAdapters.AnagraficaOperatori2insTableAdapter taOp2ins;
public DS_PlanTableAdapters.CalDispTableAdapter taPlanCalDisp;
public DS_PlanTableAdapters.CalStopTableAdapter taPlanCalStop;
public DS_PlanTableAdapters.RichiesteTableAdapter taPlanRichieste;
public DS_ProdTempiTableAdapters.PromesseODLTableAdapter taPODL;
public DS_ProdTempiTableAdapters.PostazioniMapoTableAdapter taPostazioni;
public DS_PlanTableAdapters.PromesseINTableAdapter taPromIn;
public DS_PlanTableAdapters.PromesseOUTTableAdapter taPromOut;
public DS_ProdTempiTableAdapters.stp_PzProd_getByMacchinaTableAdapter taPzProd2conf;
public DS_ProdTempiTableAdapters.RegistroControlliTableAdapter taRC;
public DS_applicazioneTableAdapters.RemoteRebootLogTableAdapter taRemReb;
public DS_ProdTempiTableAdapters.RegistroScartiTableAdapter taRS;
public DS_UtilityTableAdapters.v_selArticoliTableAdapter taSelArt;
public DS_UtilityTableAdapters.v_selMacchineTableAdapter taSelMacc;
public DS_UtilityTableAdapters.v_selODLTableAdapter taSelOdlFree;
public DS_applicazioneTableAdapters.SignalLogTableAdapter taSigLog;
public DS_SheetTechTableAdapters.ST_ActualTableAdapter taSTA;
public DS_SheetTechTableAdapters.ST_ActualRowTableAdapter taSTAR;
public DS_applicazioneTableAdapters.DiarioDiBordoTableAdapter taStati;
public DS_applicazioneTableAdapters.StatoMacchineTableAdapter taStatoMacchine;
public DS_ProdTempiTableAdapters.StatoProdTableAdapter taStatoProd;
public DS_SheetTechTableAdapters.ST_CheckTableAdapter taSTChk;
public DS_ProdTempiTableAdapters.TempiCicloRilevatiTableAdapter taTempiCicloRilevati;
public DS_ProdTempiTableAdapters.stp_TempoByIdxMaccPeriodClassTableAdapter taTempoByClass;
public DS_IntServTableAdapters.TKS_SearchTableAdapter taTKS;
public DS_applicazioneTableAdapters.TransizioneIngressiTableAdapter taTranIngr;
public DS_ProdTempiTableAdapters.TurniMacchinaTableAdapter taTurniMacc;
public DS_IntServTableAdapters.WipSetupKitTableAdapter taWKS;
#endregion Public Fields
#region Public Constructors
/// <summary>
/// Init classe
/// </summary>
public DataLayer()
{
initTA();
setupConnectionStringBase();
// aggiunta x gestione timeout esteso (ove necessario)!
fixCommandTimeout();
// init oggetto MapoDb
MapoDbObj = new MapoDb();
// init config..
ListConfig = taConfig.GetData();
// altri init
setupConf();
}
/// <summary>
/// Init class
/// </summary>
/// <param name="enableRedisMsg">Abilitazione ch messaggi broadcast redis</param>
public DataLayer(bool enableRedisMsg)
{
initTA();
setupConnectionStringBase();
// aggiunta x gestione timeout esteso (ove necessario)!
fixCommandTimeout();
// init oggetto MapoDb
MapoDbObj = new MapoDb();
if (enableRedisMsg)
{
// init message channel...
BroadastMsgPipe = new MessagePipe(connRedis, Constants.BROADCAST_M_PIPE);
}
}
#endregion Public Constructors
#region Public Properties
/// <summary>
/// Hash dati MSE
/// </summary>
/// <returns></returns>
public static string hMSE
{
get => mHash("hMSE_DATA");
}
public static string redKeyArtUsed
{
get => mHash($"CACHE:CheckArtUsed");
}
public static string redKeyRawTransfData
{
get => mHash($"RAW:TRANSFER");
}
public static string redKeyTabCheckArt
{
get => mHash($"CACHE:TabCheckArt");
}
public MessagePipe BroadastMsgPipe { get; set; } = null;
/// <summary>
/// Cognome Nome da MatrOpr in sessione
/// </summary>
public string CognomeNomeOpr
{
get
{
// cerco operatore...
string answ = "";
try
{
DS_applicazione.AnagraficaOperatoriRow oper = taOp.getByMatrOpr(MatrOpr)[0];
answ = string.Format("{0} {1}", oper.Cognome, oper.Nome);
}
catch { }
return answ;
}
}
/// <summary>
/// Oggetto statico connessione redis
/// </summary>
public ConnectionMultiplexer connRedis
{
get
{
return lazyConnection.Value;
}
}
/// <summary>
/// Dati MSE serializzati in REDIS (get/set)
/// </summary>
public string currMSE
{
get
{
string answ = "";
Log.Info("Richiesta MSE da REDIS");
answ = cMemLayer.getRSV(hMSE);
return answ;
}
set
{
int MSE_cacheDuration = cMemLayer.CRI("MSE_cacheDuration");
cMemLayer.setRSV(hMSE, value, MSE_cacheDuration);
}
}
/// <summary>
/// Dati RawTransfer serializzati in REDIS (get/set)
/// </summary>
public string lastRawTrasfData
{
get
{
string answ = "";
Log.Info("Richiesta rawTransfData da REDIS");
answ = cMemLayer.getRSV(redKeyRawTransfData);
return answ;
}
set
{
cMemLayer.setRSV(redKeyRawTransfData, value);
}
}
/// <summary>
/// MatrOpr in sessione
/// </summary>
public int MatrOpr
{
get
{
int idx = 0;
try
{
idx = cMemLayer.IntSessionObj("MatrOpr");
}
catch { }
return idx;
}
set
{
cMemLayer.setSessionVal("MatrOpr", value);
}
}
#endregion Public Properties
#region Public Methods
/// <summary>
/// Hash dati ConfFlux x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string confFluxMaccHash(string idxMacchina)
{
return mHash($"MachineConfFlux:{idxMacchina}");
}
/// <summary>
/// Hash dati di configurazione IOB in formato YAML x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string ConfYamlHash(string idxMacchina)
{
return mHash($"IOB:{idxMacchina}:ConfYaml");
}
/// <summary>
/// Hash dati tabella AnagStati macchina
/// </summary>
/// <returns></returns>
public static string currAnagStatiMacc()
{
return mHash(string.Format("Anag:StatiMacc"));
}
/// <summary>
/// Hash dati Current ODL x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string currODLHash(string idxMacchina)
{
return mHash(string.Format("CurrODL:{0}", idxMacchina));
}
/// <summary>
/// Hash dati Current ODL ROW x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string currOdlRowHash(string idxMacchina)
{
return mHash($"CurrOdlRow:{idxMacchina}");
}
/// <summary>
/// Hash dati CurrentParameters x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string currParametersHash(string idxMacchina)
{
return mHash(string.Format("CurrentParameters:{0}", idxMacchina));
}
/// <summary>
/// Hash dati Current StatoMacchina x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string currStatoMaccHash(string idxMacchina)
{
return mHash($"CurrStatoMacc:{idxMacchina}");
}
public static List<T> DataTableToList<T>(DataTable dt) where T : class, new()
{
List<T> lstItems = new List<T>();
if (dt != null && dt.Rows.Count > 0)
foreach (DataRow row in dt.Rows)
lstItems.Add(ConvertDataRowToGenericType<T>(row));
else
lstItems = null;
return lstItems;
}
/// <summary>
/// Hash dati Dossier (last) x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string dossLastMaccHash(string idxMacchina)
{
return mHash($"MachineDossierLast:{idxMacchina}");
}
/// <summary>
/// Hash dati STATUS x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string dtMaccHash(string idxMacchina)
{
return mHash(string.Format("DtMac:{0}", idxMacchina));
}
/// <summary>
/// Hash dati EXE TASK x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string exeTaskHash(string idxMacchina)
{
return mHash(string.Format("ExeTask:{0}", idxMacchina));
}
/// <summary>
/// Hash dati FluxLog (iniziale) x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string fluxLogFirstMaccHash(string idxMacchina)
{
return mHash($"MachineFluxLogFirst:{idxMacchina}");
}
/// <summary>
/// Hash dati PODL ROW x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string getPOdlRowHash(int idxPODL)
{
return mHash($"PODLRow:{idxPODL}");
}
/// <summary> Hash dati relativi all'associazione macchina <--> IOB </summary> <param
/// name="IdxMacchina">Macchina</param> <returns></returns>
public static string hIobDict(string IdxMacchina)
{
return mHash($"IOB:{IdxMacchina}:CurrInfo");
}
/// <summary> Hash dati relativi all'associazione macchina <--> IOB </summary> <param
/// name="IdxMacchina">Macchina PRINCIPALE</param> <returns></returns>
public static string hM2IOB(string IdxMacchina)
{
return mHash(string.Format("hM2IOB:{0}", IdxMacchina));
}
/// <summary>
/// Hash dati relativi a macchina + IOB + conf speciali
/// </summary>
/// <param name="IdxMacchina">Macchina</param>
/// <returns></returns>
public static string hMachineIobConf(string IdxMacchina)
{
return mHash($"IOB:{IdxMacchina}:MachIobConf");
}
/// <summary>
/// Hash dati Macchine Multi SM Ingressi
/// </summary>
/// <param name="IdxMacchina">Macchina PRINCIPALE</param>
/// <returns></returns>
public static string hMSMI(string IdxMacchina)
{
return mHash(string.Format("hMSMI:{0}", IdxMacchina));
}
/// <summary>
/// Hash dati STATE MACHINE INGRESSI x la FAMIGLIA INGRESSI specificata (per completare poi
/// manca singolo micro stato corrente + valore letto x definire chiave)
/// </summary>
/// <param name="idxFamIn"></param>
/// <returns></returns>
public static string hSMI(int idxFamIn)
{
return mHash(string.Format("hSMI:{0}", idxFamIn));
}
/// <summary>
/// Hash dati BUFFER x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="bufferName"></param>
/// <returns></returns>
public static string LiveBufferHash(string idxMacchina, string bufferName)
{
return mHash($"LIVE:{idxMacchina}:{bufferName}");
}
/// <summary>
/// Hash dati LIVE x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string LiveCurrValHash(string idxMacchina)
{
return mHash($"LIVE:{idxMacchina}:CURR_VAL");
}
/// <summary>
/// KEY x i dati del FLog della machina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="flog"></param>
/// <returns></returns>
public static string LiveFLogKeyHash(string idxMacchina, string flog)
{
return mHash($"FLOG:{idxMacchina}:{flog}");
}
/// <summary>
/// Hash dati MemoryMap x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string memMapHash(string idxMacchina)
{
return mHash($"MemMap:{idxMacchina}");
}
/// <summary>
/// Hash Redis contenente i dati MP di una specifico TYPE (es StatusMacchina,
/// StateMachineIngressi, ...)
/// </summary>
/// <param name="dataType"></param>
/// <returns></returns>
public static string mHash(string dataType)
{
return cMemLayer.redHash(dataType);
}
/// <summary>
/// Hash dati OPT PARAMETERS x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string optParHash(string idxMacchina)
{
return mHash(string.Format("OptPar:{0}", idxMacchina));
}
/// <summary>
/// Hash dati COUNTER x la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string pzCountHash(string idxMacchina)
{
return mHash(string.Format("PzCount:{0}", idxMacchina));
}
/// <summary>
/// Hash dati SAVED (EXE) TASK x la macchina specificata x poter ripristinare in caso di
/// perdita valore WRITE
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string savedTaskHash(string idxMacchina)
{
return mHash(string.Format("SavedTask:{0}", idxMacchina));
}
/// <summary>
/// Hash dati STATUS x la macchina specificata.
/// - dati ODL
/// - dati articolo
/// - dati produzione corrente
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string stMaccHash(string idxMacchina)
{
return mHash(string.Format("StMac:{0}", idxMacchina));
}
/// <summary>
/// Hash x VETO force Start PODL la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string vetoForceStartPOdlMaccHash(string idxMacchina)
{
return mHash($"VetoStartPOdlMacc:{idxMacchina}");
}
/// <summary>
/// Hash x VETO dello SPLIT ODL la macchina specificata
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public static string vetoSplitOdlMaccHash(string idxMacchina)
{
return mHash($"VetoOdlMacc:{idxMacchina}");
}
/// <summary>
/// Salva richiesta azione
/// </summary>
/// <param name="act2save"></param>
/// <returns></returns>
public bool ActionSetReq(DisplayAction act2save)
{
bool fatto = false;
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
// cerco in redis...
string rawData = JsonConvert.SerializeObject(act2save);
// invio broadcast + salvo in redis
BroadastMsgPipe.saveAndSendMessage(Constants.redisActionReq, rawData);
fatto = true;
//await redisDb.StringSetAsync(redisActionReq, rawData);
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Info($"ActionSetReq REDIS send to broadcast + Write cache: {ts.TotalMilliseconds}ms");
return fatto;
}
/// <summary>
/// verifica se sia da reinviare un task alla macchina dall'elenco di quelli salvati (in
/// modalità upsert) se non scaduti
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="taskKey"></param>
/// <param name="taskVal"></param>
/// <returns></returns>
public bool addCheckTask4Machine(string idxMacchina, taskType taskKey, string taskVal)
{
bool answ = false;
string currHash = exeTaskHash(idxMacchina);
Log.Info($"addCheckTask4Machine idxMacchina: {idxMacchina} | taskKey: {taskKey} | taskVal: {taskVal}");
try
{
Dictionary<string, string> savedTask = mSavedTaskMacchina(idxMacchina);
// cerco valore saved
string savedVal = savedTask[taskKey.ToString()];
// se ho un valore != "" --> rimetto in coda di invio...
if (!string.IsNullOrEmpty(savedVal) && (savedVal != taskVal))
{
// leggo task attuali...
Dictionary<string, string> currTask = mTaskMacchina(idxMacchina);
// rimetto in task da eseguire...
currTask[taskKey.ToString()] = savedVal;
answ = cMemLayer.redSaveHashDict(currHash, currTask);
Log.Info($"re-issued task4machine: idxMacchina: {idxMacchina} | taskKey: {taskKey} | savedVal: {savedVal}");
}
}
catch
{ }
return answ;
}
/// <summary>
/// Aggiunge un PARAMETRO OPZIONALE all'elenco di quelli salvati (in modalità upsert)
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="taskKey"></param>
/// <param name="taskVal"></param>
/// <returns></returns>
public bool addOptPar4Machine(string idxMacchina, string taskKey, string taskVal)
{
bool answ = false;
string currHash = optParHash(idxMacchina);
try
{
// leggo task attuali...
var currVal = mOptParMacchina(idxMacchina);
currVal[taskKey] = taskVal;
answ = cMemLayer.redSaveHashDict(currHash, currVal);
}
catch { }
return answ;
}
/// <summary>
/// Aggiunge un task all'elenco di quelli salvati (in modalità upsert)
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="taskKey"></param>
/// <param name="taskVal"></param>
/// <returns></returns>
public bool addTask4Machine(string idxMacchina, taskType taskKey, string taskVal)
{
bool answ = false;
string currHash = exeTaskHash(idxMacchina);
string currSavedParHash = savedTaskHash(idxMacchina);
Dictionary<string, string> currTask = new Dictionary<string, string>();
Dictionary<string, string> savedTask = new Dictionary<string, string>();
try
{
//Log.Info($"Request: idxMacchina: {idxMacchina} | taskKey: {taskKey} | taskVal: {taskVal}");
// leggo task attuali...
currTask = mTaskMacchina(idxMacchina);
if (currTask.ContainsKey($"{taskKey}"))
{
currTask[$"{taskKey}"] = taskVal;
}
else
{
currTask.Add($"{taskKey}", taskVal);
}
answ = cMemLayer.redSaveHashDict(currHash, currTask);
Log.Info($"Task ADD - idxMacchina: {idxMacchina} | taskKey: {taskKey} | taskVal: {taskVal}");
}
catch { }
// verifico in base al tipo di task se fare backup...
switch (taskKey)
{
case taskType.setArt:
case taskType.setComm:
case taskType.setPzComm:
case taskType.setProg:
// leggo task SALVATI attuali...
savedTask = mSavedTaskMacchina(idxMacchina);
savedTask[taskKey.ToString()] = taskVal;
answ = cMemLayer.redSaveHashDict(currSavedParHash, savedTask);
break;
case taskType.endProd:
// salvo un DICT vuoto x resettare
savedTask = new Dictionary<string, string>();
answ = cMemLayer.redSaveHashDict(currSavedParHash, savedTask);
break;
default:
break;
}
return answ;
}
/// <summary>
/// Elenco stati macchina
/// </summary>
/// <returns></returns>
public DS_applicazione.AnagraficaStatiDataTable AnagraficaStati()
{
DS_applicazione.AnagraficaStatiDataTable answTab = null;
// cerco in cache...
string rCall = "";
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("hasAnagStati");
try
{
rCall = cMemLayer.getRSV(currAnagStatiMacc());
if (!string.IsNullOrEmpty(rCall))
{
answTab = JsonConvert.DeserializeObject<DS_applicazione.AnagraficaStatiDataTable>(rCall);
}
else
{
//2020.01.31 nuovo obj x evitare concorrenza
MapoDb man = new MapoDb();
answTab = man.taAnagSt.GetData();
//resultList = MapoDbObj.taAnagSt.GetData();
// salvo in redis...
rCall = JsonConvert.SerializeObject(answTab);
int anagrCacheDur = cMemLayer.CRI("anagrCacheDur");
cMemLayer.setRSV(currAnagStatiMacc(), rCall, anagrCacheDur);
}
}
catch (Exception exc)
{
Log.Info($"Eccezione in recupero currODLRow{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
}
else
{
answTab = MapoDbObj.taAnagSt.GetData();
}
return answTab;
}
/// <summary>
/// Effettua split ODL
/// </summary>
/// <param name="idxMacchina">macchina</param>
/// <param name="doConfirm">effettuare conferma qty</param>
/// <param name="qtyFromLast">imposta la qty prox ODL da ODL che si chiude</param>
/// <param name="matrOpr">matricola operatore</param>
/// <param name="roundStep">
/// STEP x cui arrotondare la quantità prox ODL (corrente come riferimento)
/// </param>
/// <param name="keyRichiesta">Cod ext da associare all'ODL</param>
/// <returns></returns>
public string AutoStartOdl(string idxMacchina, bool doConfirm, bool qtyFromLast, int matrOpr, int roundStep = 100, string keyRichiesta = "")
{
string answ = "KO";
DateTime adesso = DateTime.Now;
// verifico NON CI SIA un veto a NUOVI split... 2 min di default...
string redKey = vetoSplitOdlMaccHash(idxMacchina);
string rawData = cMemLayer.getRSV(redKey);
if (string.IsNullOrEmpty(rawData))
{
// registro VETO x altri split... 5 minuti
cMemLayer.setRSV(redKey, $"Inizio SPLIT-ODL {adesso}", 300);
// calcolo la qta da gestire
int qtyConf = 0;
int qtyNew = 0;
int qtyScarto = 0;
if (doConfirm)
{
DS_ProdTempi.stp_PzProd_getByMacchinaRow rigaProd;
DS_ProdTempi.StatoProdRow statoProd;
try
{
rigaProd = taPzProd2conf.GetData(idxMacchina)[0];
statoProd = taStatoProd.GetData(idxMacchina, adesso)[0];
qtyConf = rigaProd.pezziNonConfermati;
qtyScarto = statoProd.Pz2RecScarto;
// calcolo nuovi pezzi da confermare
if (qtyFromLast)
{
roundStep = roundStep == 0 ? 1 : roundStep;
double ratio = (double)qtyConf / roundStep;
qtyNew = (int)Math.Round(Math.Ceiling(ratio) * roundStep, 0);
}
}
catch (Exception exc)
{
Log.Info(string.Format("Errore recupero pezzi da confermare per la macchina {0}{1}{2}", idxMacchina, Environment.NewLine, exc), tipoLog.ERROR);
}
}
// proseguo
DS_ProdTempi.ODLDataTable currData = null;
// chiamo metodo redis/db...
try
{
// recupero ODL corrente
currData = currODLRowTab(idxMacchina);
if (currData.Count > 0)
{
// preparo var x master/slave
bool isMachMaster = this.isMaster(idxMacchina);
DS_ProdTempi.Macchine2SlaveDataTable slaveList = isMachMaster ? taM2S.getByMaster(idxMacchina) : new DS_ProdTempi.Macchine2SlaveDataTable();
// registro un evento di inizio attrezzaggio (idxTipoEv = 2)
int idxEvento = 2;
Log.Info($"Invio evento ODL-SPLIT per macchina {idxMacchina} | ev: {idxEvento} | art: {currData[0].CodArticolo} | qty conf: {qtyConf} | sty sca: {qtyScarto} | new qty: {qtyNew}", tipoLog.INFO);
inputComandoMapo resCmd = scriviRigaEventoBarcode(idxMacchina, idxEvento, currData[0].CodArticolo, "ODL-SPLIT", 0, "", adesso, adesso);
if (doConfirm)
{
// attendo 100 msec
Thread.Sleep(100);
adesso = DateTime.Now;
// chiamo conferma produzione...
try
{
string chiamata = confRett ? "confermaProdMacchinaFull" : "confermaProdMacchina";
Log.Info($"Chiamata a {chiamata} con parametri {currData[0].IdxMacchina} |{MatrOpr} | {DateTime.Now.AddDays(-10)} | {DateTime.Now} | {qtyConf} | 0 | {qtyScarto} | {DateTime.Now} | false", tipoLog.INFO);
string idxMacchinaSel = currData[0].IdxMacchina;
bool fatto = false;
if (confRett)
{
// confermo al netto dei pezzi lasciati...
fatto = confermaProdMacchinaFull(idxMacchinaSel, cMemLayer.CRI("modoConfProd"), qtyConf, 0, qtyScarto, adesso, matrOpr);
if (cMemLayer.CRB("SlaveConfirmPzProd"))
{
foreach (var machine in slaveList)
{
confermaProdMacchinaFull(machine.IdxMacchinaSlave, cMemLayer.CRI("modoConfProd"), qtyConf, 0, qtyScarto, adesso, matrOpr);
}
}
}
else
{
fatto = confermaProdMacchina(idxMacchinaSel, cMemLayer.CRI("modoConfProd"), qtyConf, qtyScarto, adesso, matrOpr);
if (cMemLayer.CRB("SlaveConfirmPzProd"))
{
foreach (var machine in slaveList)
{
confermaProdMacchina(idxMacchinaSel, cMemLayer.CRI("modoConfProd"), qtyConf, qtyScarto, adesso, matrOpr);
}
}
}
if (!fatto)
{
Log.Info($"ERRORE in chiamata {chiamata}", tipoLog.ERROR);
}
}
catch (Exception exc)
{
Log.Info($"Eccezione in ConfermaProduzione{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
}
// 2025.02.19 portato da 100 a 1000 ms attesa x evitare che ODL sia avviato PRIMA della conferma
// attendo 1000 msec x chiudere ODL
Thread.Sleep(1000);
// chiamo splitOdl
MapoDbObj.taODL.autoStart(currData[0].IdxODL, 0, idxMacchina, currData[0].TCRichAttr, currData[0].PzPallet, $"Nuovo ODL da forceSplitOdl.autoStart", true, qtyNew, keyRichiesta);
// elimino eventuale ODL precedente...
string rKey = cMemLayer.redHash($"ODL:{idxMacchina}");
cMemLayer.setRSV(rKey, "");
// ricalcola ODL macchina
var newOdl = currODL(idxMacchina, true);
// attendo 1000 msec
Thread.Sleep(1000);
adesso = DateTime.Now;
// registro fine ODL (idxTipoEv = 1)
idxEvento = 1;
Log.Info($"Invio evento FINE ODL-SPLIT per macchina {idxMacchina}, evento {idxEvento}, articolo {currData[0].CodArticolo}", tipoLog.INFO);
resCmd = scriviRigaEventoBarcode(idxMacchina, idxEvento, currData[0].CodArticolo, "ODL-START");
// invio eventi setup a macchina....
string setArtVal = $"{currData[0].CodArticolo}";
string setPzCommVal = $"{qtyNew}";
string setCommVal = $"ODL{newOdl}";
if (!string.IsNullOrEmpty(keyRichiesta))
{
setCommVal = $"{keyRichiesta} ODL{newOdl}";
}
try
{
// invio task caricamento dati ODL
addTask4Machine(idxMacchina, taskType.setArt, setArtVal);
addTask4Machine(idxMacchina, taskType.setComm, setCommVal);
addTask4Machine(idxMacchina, taskType.setPzComm, setPzCommVal);
updateMachineParameter(idxMacchina, "setArt", setArtVal);
updateMachineParameter(idxMacchina, "setComm", setCommVal);
updateMachineParameter(idxMacchina, "setPzComm", setPzCommVal);
}
catch
{ }
// chiamo refresh MSE
taMSE.forceRecalc(0, idxMacchina);
// resetto stato macchina...
cMemLayer.redDelKey(currStatoMaccHash(idxMacchina));
answ = "OK";
Log.Info($"Effettuato reset e ricalcoli x split ODL per macchina {idxMacchina}", tipoLog.INFO);
// se è una master richiamo fix x child...
if (isMachMaster)
{
string ts = "";
string outData = "";
taODL.fixMachineSlave(idxMacchina, 30, 1);
foreach (var machine in slaveList)
{
// invio chiusura attrezzaggio
ts = string.Format("{0:yyMMdd}T{0:HHmmss.fff}Z", DateTime.Now);
outData = $"TS:{ts}|MATR:{MatrOpr}|ODL:{newOdl}";
addTask4Machine(machine.IdxMacchinaSlave, taskType.fixStopSetup, outData);
addTask4Machine(machine.IdxMacchinaSlave, taskType.forceResetPzCount, outData);
// invio task caricamento dati ODL
addTask4Machine(machine.IdxMacchinaSlave, taskType.setArt, setArtVal);
addTask4Machine(machine.IdxMacchinaSlave, taskType.setComm, setCommVal);
addTask4Machine(machine.IdxMacchinaSlave, taskType.setPzComm, setPzCommVal);
updateMachineParameter(machine.IdxMacchinaSlave, "setArt", setArtVal);
updateMachineParameter(machine.IdxMacchinaSlave, "setComm", setCommVal);
updateMachineParameter(machine.IdxMacchinaSlave, "setPzComm", setPzCommVal);
}
}
}
}
catch (Exception exc)
{
Log.Info($"Eccezione in forceSplitOdl{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
}
else
{
Log.Info($"VETO ATTIVO | Richiesto forceSplitOdl per impianto {idxMacchina} | impossibile procedere");
}
return answ;
}
/// <summary>
/// controlla se da il segnale di "microstato" deriva un evento da generare - modalità OFFLINE
/// </summary>
/// <param name="idxMacchina">idx macchina</param>
/// <param name="valore">valore ingresso</param>
/// <param name="dtEve">data-ora evento (server)</param>
/// <param name="contatore">sequenza dati inviati</param>
/// <returns></returns>
public inputComandoMapo checkMicroStato(string idxMacchina, string valore, DateTime dtEve, string contatore)
{
int _logLevel = cMemLayer.CRI("_logLevel");
// recupero SE IMPIEGATO REDIS i valori del Dictionary della macchina...
Dictionary<string, string> datiMacc = mDatiMacchine(idxMacchina);
if (_logLevel > 6)
{
Log.Info(string.Format("[ChkMiSt]{2}---------------------------{2}Richiesta verifica INPUT per Macchina {0}, seriale {1}", idxMacchina, valore, Environment.NewLine), tipoLog.INFO);
}
// formatto output
inputComandoMapo answ = new inputComandoMapo();
DS_applicazione.TransizioneIngressiDataTable TabTransIn;
DS_applicazione.TransizioneIngressiRow rigaTransIn = null;
// verifico se esista la macchina altrimenti la creo... REDIS compliant
verificaIdxMacchina(idxMacchina);
string CodArticolo = "";
if (cMemLayer.CRB("IOB_RedEnab"))
{
try
{
// esecuzione in REDIS
CodArticolo = datiMacc["CodArticolo"];
}
catch { }
}
// ...oppure dritto su DB
else
{
// esecuzione in DB... recupero CodArticolo corretto
try
{
// 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione
// NUOVO oggetto
if (cMemLayer.CRB("disable_singleton"))
{
// 2017.07.10 forzo init x errori "sovrapposizioni"
taDatiMacchine = new DS_ProdTempiTableAdapters.DatiMacchineTableAdapter();
}
CodArticolo = taDatiMacchine.getByIdx(idxMacchina)[0].CodArticolo_A;
}
catch (Exception exc)
{
Log.Info(string.Format("[ChkMiSt_4a] - Eccezione in recupero CodArticolo:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION);
}
}
// recupero next microstato
int? valINT = 0;
try
{
valINT = int.Parse(valore, System.Globalization.NumberStyles.HexNumber);
// esecuzione in REDIS...
if (cMemLayer.CRB("IOB_RedEnab"))
{
try
{
int idxFamIn = Convert.ToInt32(datiMacc["IdxFamIn"]);
int idxMicroStato = Convert.ToInt32(datiMacc["IdxMicroStato"]);
int valIOB = Convert.ToInt32(valINT);
int idxTipoEv = 0;
int next_idxMS = idxMicroStato;
// verifico esistenza tab SMI...
string fiHASH = DataLayer.hSMI(idxFamIn);
string todoSMI = "";
bool trovato = cMemLayer.redHashPresentSz(fiHASH);
if (!trovato)
{
// ricarico tabella!
KeyValuePair<string, string>[] valori = mTabSMI(idxFamIn);
}
// recupero singolo valore (stringa) x chiave
todoSMI = valoreSMI(idxFamIn, idxMicroStato, valIOB);
// solo se ho trovato un risultato nella tab SMI della famiglia macchina...
if (todoSMI != "")
{
// splitto e salvo valori OUT...
string[] valori = todoSMI.Split('_');
idxTipoEv = Convert.ToInt32(valori[0]);
next_idxMS = Convert.ToInt32(valori[1]);
// creo la riga tipizzata dai dati di redis x procedere...
DS_applicazione.TransizioneIngressiDataTable tab = new DS_applicazione.TransizioneIngressiDataTable();
rigaTransIn = tab.NewTransizioneIngressiRow();
rigaTransIn.IdxFamigliaIngresso = idxFamIn;
rigaTransIn.IdxMicroStato = idxMicroStato;
rigaTransIn.ValoreIngresso = valIOB;
rigaTransIn.IdxTipoEvento = idxTipoEv;
rigaTransIn.next_IdxMicroStato = next_idxMS;
}
}
catch { }
}
// ...oppure dritto su DB
else
{
// 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione
// NUOVO oggetto
if (cMemLayer.CRB("disable_singleton"))
{
// 2017.06.09 forzo init x errori "sovrapposizioni"
MapoDbObj.taTransIngr = new DS_applicazioneTableAdapters.TransizioneIngressiTableAdapter();
}
TabTransIn = MapoDbObj.taTransIngr.getByIdxMacchinaValore(idxMacchina, valINT);
if (TabTransIn.Rows.Count > 0)
{
rigaTransIn = TabTransIn[0];
}
}
}
catch (Exception exc)
{
Log.Info(string.Format("[ChkMiSt_5a] - - Eccezione in recupero riga Trans ingressi per idxMacchina {3} e valore {2}:{0}{1}", Environment.NewLine, exc, valINT, idxMacchina), tipoLog.EXCEPTION);
}
// effettuo update vari SU DB!!!
if (rigaTransIn != null)
{
try
{
if (_logLevel > 5)
{
Log.Info(string.Format("[ChkMiSt_6a] - Salvo Update Microstato:{0}macchina: {1} | valore seriale: {2} | next micro stato: {3}", Environment.NewLine, idxMacchina, valINT, rigaTransIn.next_IdxMicroStato), tipoLog.INFO);
}
// 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione
// NUOVO oggetto
if (cMemLayer.CRB("disable_singleton"))
{
// 2017.06.09 forzo init x errori "sovrapposizioni"
MapoDbObj.taMSM = new DS_applicazioneTableAdapters.MicroStatoMacchinaTableAdapter();
}
// salvo nuovo microstato...
MapoDbObj.taMSM.updateQuery(rigaTransIn.next_IdxMicroStato, dtEve, valore, idxMacchina);
// controllo se c'è evento
if (rigaTransIn.IdxTipoEvento > 0)
{
if (_logLevel > 5)
{
Log.Info(string.Format("[ChkMiSt_7a] - Salvo evento:{0}macchina: {1} | tipoEvento: {2} | CodArticolo: {3} | contatore: {4} | valore: {5}", Environment.NewLine, idxMacchina, rigaTransIn.IdxTipoEvento, CodArticolo, contatore, valore), tipoLog.INFO);
}
string valEsteso = string.Format("[{0}] {1}", contatore.PadLeft(3, '0'), valore);
// aggiunto contatore!
answ = scriviRigaEvento(idxMacchina, rigaTransIn.IdxTipoEvento, CodArticolo, valEsteso, 0, "-", dtEve, DateTime.Now);
// 2017.09.12 SE era in modalità redis RICARICA dati macchina...
if (cMemLayer.CRB("IOB_RedEnab"))
{
resetDatiMacchina(idxMacchina);
}
if (_logLevel > 5)
{
Log.Info(string.Format("[ChkMiSt_a] - Macchina {0} | seriale(INT) {1} | valEsteso {3} | answ {4}{2}---------------------------{2}", idxMacchina, valINT, Environment.NewLine, valEsteso, answ), tipoLog.INFO);
}
}
}
catch (Exception exc)
{
Log.Info(string.Format("[ChkMiSt_8a] - Eccezione:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION);
}
}
return answ;
}
/// <summary>
/// controlla se da il segnale di "microstato" deriva un evento da generare - modalità OFFLINE
/// </summary>
/// <param name="idxMacchina">idx macchina</param>
/// <param name="valore">valore ingresso</param>
/// <param name="dtEve">data-ora evento (server)</param>
/// <returns></returns>
public inputComandoMapo checkMicroStato(string idxMacchina, string valore, DateTime dtEve)
{
if (cMemLayer.CRI("_logLevel") > 6)
{
Log.Info(string.Format("{2}---------------------------{2}Richiesta verifica INPUT per Macchina {0}, seriale {1}", idxMacchina, valore, Environment.NewLine), tipoLog.INFO);
}
// formatto output
inputComandoMapo answ = new inputComandoMapo();
DS_applicazione.TransizioneIngressiDataTable TabTransIn;
DS_applicazione.TransizioneIngressiRow rigaTransIn = null;
// verifico se esista la macchina altrimenti la creo...
verificaIdxMacchina(idxMacchina);
string CodArticolo = "";
// recupero CodArticolo corretto
try
{
// 2017.07.10 forzo init x errori "sovrapposizioni"
taDatiMacchine = new DS_ProdTempiTableAdapters.DatiMacchineTableAdapter();
CodArticolo = taDatiMacchine.getByIdx(idxMacchina)[0].CodArticolo_A;
}
catch (Exception exc)
{
Log.Info(string.Format("[ChkMiSt_4b] - Eccezione in recupero CodArticolo:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION);
}
// recupero next microstato
//int? valINT = Convert.ToInt32(valore);
int? valINT = 0;
try
{
// 2017.06.09 forzo init x errori "sovrapposizioni"
MapoDbObj.taTransIngr = new DS_applicazioneTableAdapters.TransizioneIngressiTableAdapter();
valINT = int.Parse(valore, System.Globalization.NumberStyles.HexNumber);
TabTransIn = MapoDbObj.taTransIngr.getByIdxMacchinaValore(idxMacchina, valINT);
if (TabTransIn.Rows.Count > 0)
{
rigaTransIn = TabTransIn[0];
}
}
catch (Exception exc)
{
Log.Info(string.Format("[ChkMiSt_5b] - Eccezione in recupero riga Trans ingressi per idxMacchina {3} e valore {2}:{0}{1}", Environment.NewLine, exc, valINT, idxMacchina), tipoLog.EXCEPTION);
}
int _logLevel = cMemLayer.CRI("_logLevel");
// effettuo update vari
if (rigaTransIn != null)
{
try
{
if (_logLevel > 5)
{
Log.Info(string.Format("[ChkMiSt_6b] - Salvo Update Microstato:{0}macchina: {1} | valore seriale: {2} | next micro stato: {3}", Environment.NewLine, idxMacchina, valINT, rigaTransIn.next_IdxMicroStato), tipoLog.INFO);
}
// salvo nuovo microstato...
MapoDbObj.taMSM.updateQuery(rigaTransIn.next_IdxMicroStato, dtEve, valore, idxMacchina);
// controllo se c'è evento
if (rigaTransIn.IdxTipoEvento > 0)
{
if (_logLevel > 5)
{
Log.Info(string.Format("[ChkMiSt_7b] - Salvo evento:{0}macchina: {1} | tipoEvento: {2} | CodArticolo: {3}", Environment.NewLine, idxMacchina, rigaTransIn.IdxTipoEvento, CodArticolo), tipoLog.INFO);
}
answ = scriviRigaEvento(idxMacchina, rigaTransIn.IdxTipoEvento, CodArticolo, valore, 0, "-", dtEve, DateTime.Now);
if (_logLevel > 5)
{
Log.Info(string.Format("[ChkMiSt_b] -Macchina {0}, seriale(INT) {1}{2}---------------------------{2}", idxMacchina, valINT, Environment.NewLine), tipoLog.INFO);
}
}
}
catch (Exception exc)
{
Log.Info(string.Format("[ChkMiSt_8b] - Eccezione:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION);
}
}
return answ;
}
/// <summary>
/// controlla se da il segnale di "microstato" deriva un evento da generare
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="valore"></param>
/// <returns></returns>
public inputComandoMapo checkMicroStato(string idxMacchina, string valore)
{
// wrapper ad ora corrente...
return checkMicroStato(idxMacchina, valore, DateTime.Now);
}
/// <summary>
/// Effettua conferma prod macchina dell'intero periodo da confermare (ultima conferma
/// --&gt; dtEvent)
/// </summary>
/// <param name="idxMacchina">idx macchina da confermare</param>
/// <param name="modoConfProd">0=periodo, 1 = giorno, 2 = turno</param>
/// <param name="numPzConfermati">qta pezzi BUONI da confermare</param>
/// <param name="numPzScarto">qta pezzi SCARTO da confermare</param>
/// <param name="DataOraApp">DataOra in cui registrare approvazione</param>
/// <returns></returns>
public bool confermaProdMacchina(string idxMacchina, int modoConfProd, int numPzConfermati, int numPzScarto, DateTime DataOraApp, int matrOpr)
{
bool answ = false;
try
{
DS_ProdTempi.stp_PzProd_getByMacchinaRow rigaProd = taPzProd2conf.GetData(idxMacchina.ToString())[0];
taPzProd2conf.stp_ConfermaProduzCompleta(idxMacchina, matrOpr, rigaProd.DataFrom, DataOraApp, numPzConfermati, numPzScarto, modoConfProd, DataOraApp, true);
// indico eseguito!
answ = true;
}
catch (Exception exc)
{
Log.Info($"Errore in conferma prod macchina:{Environment.NewLine}{exc}");
}
return answ;
}
/// <summary>
/// Effettua conferma prod macchina dell'intero periodo da confermare (ultima conferma
/// --&gt; dtEvent)
/// </summary>
/// <param name="idxMacchina">idx macchina da confermare</param>
/// <param name="modoConfProd">0=periodo, 1 = giorno, 2 = turno</param>
/// <param name="numPzConfermati">qta pezzi BUONI da confermare</param>
/// <param name="numPzLasciati">
/// qta pezzi LASCIATI alla macchina da confermare (2 eventi 121 rettifica neg/pos)
/// </param>
/// <param name="numPzScarto">qta pezzi SCARTO da confermare</param>
/// <param name="DataOraApp">DataOra in cui registrare approvazione</param>
/// <returns></returns>
public bool confermaProdMacchinaFull(string idxMacchina, int modoConfProd, int numPzConfermati, int numPzLasciati, int numPzScarto, DateTime DataOraApp, int matrOpr)
{
bool answ = false;
try
{
DS_ProdTempi.stp_PzProd_getByMacchinaRow rigaProd = taPzProd2conf.GetData(idxMacchina.ToString())[0];
taPzProd2conf.stp_ConfermaProduzCompletaFull(idxMacchina, matrOpr, rigaProd.DataFrom, DataOraApp, numPzConfermati, numPzLasciati, numPzScarto, modoConfProd, DataOraApp, true);
// indico eseguito!
answ = true;
}
catch (Exception exc)
{
Log.Info($"Errore in conferma prod macchina con rett ev121:{Environment.NewLine}{exc}");
}
return answ;
}
/// <summary>
/// Restituisce l'elenco codici flusso (da confFlux) x una macchina (se presenti) Impiegata
/// anche cache redis
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public List<string> confFluxMach(string idxMacchina)
{
List<string> resultList = new List<string>();
string rawData = "";
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("confFluxMach");
string redKey = confFluxMaccHash(idxMacchina);
try
{
DataLayer man = new DataLayer();
rawData = cMemLayer.getRSV(redKey);
if (!string.IsNullOrEmpty(rawData))
{
var redisResult = JsonConvert.DeserializeObject<List<string>>(rawData);
resultList = redisResult != null ? redisResult : new List<string>();
}
else
{
resultList = man.taConfFlux
.GetData()
.Where(x => x.IdxMacchina == idxMacchina)
.Select(x => x.CodFlux)
.ToList();
// salvo in redis...
rawData = JsonConvert.SerializeObject(resultList);
int IO_CacheConfFluxMin = cMemLayer.CRI("IO_CacheConfFluxMin");
cMemLayer.setRSV(redKey, rawData, IO_CacheConfFluxMin * 60);
}
}
catch (Exception exc)
{
Log.Info($"Eccezione in recupero confFluxMach{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
}
else
{
resultList = taConfFlux
.GetData()
.Where(x => x.IdxMacchina == idxMacchina)
.Select(x => x.CodFlux)
.ToList();
}
if (resultList == null)
{
resultList = new List<string>();
}
return resultList;
}
/// <summary>
/// Restituisce il valore dell'ODL corrente (ODL deve esserci per gestione contapezzi, senza
/// ODL NO invio/gestione ODL)
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public string currODL(string idxMacchina)
{
string answ = "";
string rCall = "";
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("hasODL");
try
{
rCall = cMemLayer.getRSV(currODLHash(idxMacchina));
if (!string.IsNullOrEmpty(rCall))
{
answ = rCall;
}
else
{
answ = getCurrODL(idxMacchina);
// salvo in redis...
saveCurrODL(idxMacchina, answ);
}
}
catch { }
}
return answ;
}
/// <summary>
/// Restituisce il valore dell'ODL corrente (ODL deve esserci per gestione contapezzi, senza
/// ODL NO invio/gestione ODL)
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="forceDb">indica se forzare lettura da db (true) o meno</param>
/// <returns></returns>
public string currODL(string idxMacchina, bool forceDb)
{
string answ = "";
// faccio comunque verifica se sia stato letto da poco il valore... x cui anche a fronte
// di richiesta lettura da DB per 3 sec tengo buono valore in cache redis...
string rKey = cMemLayer.redHash($"ODL:{idxMacchina}");
string _idxOdl = cMemLayer.getRSV(rKey);
if (forceDb)
{
if (!string.IsNullOrEmpty(_idxOdl))
{
answ = _idxOdl;
}
else
{
answ = getCurrODL(idxMacchina);
// salvo in redis...
saveCurrODL(idxMacchina, answ);
cMemLayer.setRSV(rKey, answ, 3);
}
}
else
{
answ = currODL(idxMacchina);
}
return answ;
}
/// <summary>
/// Restituisce il valore dell'intera RIGA ODL corrente (da redis o da DB se non trovata...)
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public DS_ProdTempi.ODLDataTable currODLRowTab(string idxMacchina)
{
DS_ProdTempi.ODLDataTable answTab = null;
string rCall = "";
string rKey = currOdlRowHash(idxMacchina);
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("hasODL_row");
try
{
rCall = cMemLayer.getRSV(rKey);
if (!string.IsNullOrEmpty(rCall))
{
answTab = JsonConvert.DeserializeObject<DS_ProdTempi.ODLDataTable>(rCall);
}
if (answTab == null || answTab.Count == 0)
{
// istanzio un NUOVO oggetto lettura
MapoDb connDb = new MapoDb();
answTab = connDb.currODLTab(idxMacchina);
// salvo in redis...
rCall = JsonConvert.SerializeObject(answTab);
int currOdlRowCacheDur = cMemLayer.CRI("currOdlRowCacheDur");
cMemLayer.setRSV(rKey, rCall, currOdlRowCacheDur);
}
}
catch (Exception exc)
{
Log.Info($"Eccezione in recupero currODLRow{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
}
else
{
// istanzio un NUOVO oggetto lettura
MapoDb connDb = new MapoDb();
answTab = connDb.currODLTab(idxMacchina);
}
return answTab;
}
/// <summary>
/// Restituisce il valore dell'intera RIGA stato macchina corrente (da redis o da DB se non trovata...)
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public DS_applicazione.StatoMacchineDataTable currSMTab(string idxMacchina)
{
DS_applicazione.StatoMacchineDataTable answTab = null;
string rCall = "";
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("hasStatoMacc");
try
{
rCall = cMemLayer.getRSV(currStatoMaccHash(idxMacchina));
if (!string.IsNullOrEmpty(rCall))
{
answTab = JsonConvert.DeserializeObject<DS_applicazione.StatoMacchineDataTable>(rCall);
}
else
{
// 2020.01.31 uso nuovo oggetto connessione
MapoDb man = new MapoDb();
answTab = man.currStatoMaccTab(idxMacchina);
//resultList = MapoDbObj.currStatoMaccTab(idxMacchina);
// salvo in redis...
rCall = JsonConvert.SerializeObject(answTab);
int currStatoMaccCacheDur = cMemLayer.CRI("currStatoMaccCacheDur");
cMemLayer.setRSV(currStatoMaccHash(idxMacchina), rCall, currStatoMaccCacheDur);
}
}
catch (Exception exc)
{
Log.Info($"Eccezione in recupero currODLRow{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
}
else
{
answTab = MapoDbObj.currStatoMaccTab(idxMacchina);
}
return answTab;
}
/// <summary>
/// Restituisce l'elenco delle date dei dossier x una macchina (se presenti) Impiegata anche
/// cache redis
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public List<DateTime> dossierLastByMach(string idxMacchina)
{
List<DateTime> resultList = new List<DateTime>();
string rawData = "";
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("dossierLastByMach");
string redKey = dossLastMaccHash(idxMacchina);
try
{
DataLayer man = new DataLayer();
rawData = cMemLayer.getRSV(redKey);
if (!string.IsNullOrEmpty(rawData) && rawData.Length > 2)
{
var redisResult = JsonConvert.DeserializeObject<List<DateTime>>(rawData);
resultList = redisResult != null ? redisResult : new List<DateTime>();
}
else
{
resultList = man.taDOSS
.getLastByMacc(idxMacchina)
.Select(x => x.DtRif)
.ToList();
// salvo in redis...
rawData = JsonConvert.SerializeObject(resultList);
int IO_CacheDossLastMin = cMemLayer.CRI("IO_CacheDossLastMin");
cMemLayer.setRSV(redKey, rawData, IO_CacheDossLastMin * 60);
}
}
catch (Exception exc)
{
Log.Info($"Eccezione in recupero dossierLastByMach{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
}
else
{
resultList = taDOSS
.getLastByMacc(idxMacchina)
.Select(x => x.DtRif)
.ToList();
}
if (resultList == null)
{
resultList = new List<DateTime>();
}
return resultList;
}
/// <summary>
/// Svuota la cache redis x l'elenco delle righe di confFlux x una macchina (se presenti)
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public bool dossierLastByMachReset(string idxMacchina)
{
bool answ = false;
string rawData = "";
string redKey = dossLastMaccHash(idxMacchina);
cMemLayer.setRSV(redKey, rawData, 1);
return answ;
}
/// <summary>
/// Rimuove Key dell'ODL corrente x una data macchina IOB
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public string emptyCurrODL(string idxMacchina)
{
string answ = "";
try
{
cMemLayer.redDelKey(currODLHash(idxMacchina));
cMemLayer.redDelKey(currOdlRowHash(idxMacchina));
answ = "OK";
}
catch
{
answ = "KO";
}
return answ;
}
/// <summary>
/// effettua enroll del device
/// </summary>
/// <param name="UserAuthKey"></param>
/// <param name="IPv4"></param>
/// <param name="DeviceName"></param>
/// <param name="Description"></param>
/// <param name="idxDipendente"></param>
/// <returns></returns>
public bool enrollDevice(string UserAuthKey, string IPv4, string DeviceName, string Description, int matricola)
{
bool fatto = false;
// in primis testo se dipendente ed authKey sono validi..
if (taOp.getByMatrAuthKey(matricola, UserAuthKey).Rows.Count > 0)
{
// salvo matrOpr
MatrOpr = matricola;
/************************************************
* Gestione riconoscimento devices
*
* - cerco IP del device, testo se è rete interna (A) o extranet/internet (B) cercando substring "localNet" da web.config
* (A): device interni: c'è un DHCP, e "dhcpLeaseTime" deve essere pari a lease time---
* - verifico se IP già in uso da un tempo < "dhcpLeaseTime" --> in questo caso segnalo errore e rimbalzo (NON permetto di registrare device a nuovo utente... sospetto uso "improprio" del device
* - se tempo > dhcpLeaseTime allora può aver cambiato IP: aggiorno IP e descrizione del device e proseguo
* (B): all'esterno vedo tutta una subnet NATtata con unico IP, non è + discriminante
* - le timbrature "da esterno" devono essere confermate (instrodurre "tipo timbratura" x cui interne sono autoconfermate, esterne sono "grayed" (da confermare, da admin o ad esempio se si accende secondo device utente entro 5/10 min)
* - le timbrature ext DOVREBBERO chiedere location (jScript?) e inviarla, visibile in conferma
*
*
* **********************************************/
// calcolo il secret...
DateTime adesso = DateTime.Now;
string Dominio = cMemLayer.CRS("dominio");
string UsrName = cMemLayer.CRS("user");
// recupero dati da matricola...
try
{
DataLayer_AnagGen.UTENTERow rigaUt = user_std.UtSn.rigaUtenteDaMatricola($"{matricola}");
if (rigaUt != null)
{
Dominio = rigaUt.DOMINIO;
UsrName = rigaUt.USER_NAME;
}
else
{
Log.Info($"Non sono riuscito a recuperare RIGA utente per matricola {matricola}", tipoLog.ERROR);
}
}
catch
{
Log.Info($"Eccezione! non sono riuscito a recuperare utente per matricola {matricola}", tipoLog.ERROR);
Dominio = cMemLayer.CRS("dominio");
UsrName = cMemLayer.CRS("user");
}
string cookieName = cMemLayer.CRS("cookieName");
//DateTime expDate = DateTime.Now.AddDays(cMemLayer.CRI("cookieDayExpire"));
string cookieDayExpire = cMemLayer.CRS("cookieDayExpire").Replace(".", ",");
double dayExp = 1;
NumberStyles style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands;
CultureInfo culture = CultureInfo.CreateSpecificCulture("it-IT");
double.TryParse(cookieDayExpire, style, culture, out dayExp);
DateTime expDate = DateTime.Now.AddDays(dayExp);
string Secret = authProxy.getSecret(Dominio, UsrName, matricola, DeviceName, adesso);
string devSecret = SteamCrypto.EncryptString(Secret, cookieName);
try
{
// creo device + cookie!
fatto = authProxy.createNewCookie(Dominio, UsrName, matricola, DeviceName, Description, IPv4, cookieName, expDate);
// loggo!
Log.Info(string.Format("Effettuato enroll nuovo device: utente {0}\\{1} | matricola {2} | DeviceName {3} | Descrizione {4} | IP {5} | nome cookie {6} | valido sino a {7:yyyy/MM/dd HH:mm:ss}", Dominio, UsrName, matricola, DeviceName, Description, IPv4, cookieName, expDate));
}
catch (Exception exc)
{
Log.Info($"Errore enroll nuovo device:{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
}
return fatto;
}
/// <summary>
/// Restituisce l'elenco delle data-ora di confFlux x una macchina (se presenti) Impiegata
/// anche cache redis
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="numMax">num record da recuperare</param>
/// <returns></returns>
public List<DateTime> fluxLogFirstByMach(string idxMacchina, int numMax = 10)
{
List<DateTime> resultList = new List<DateTime>();
string rawData = "";
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("fluxLogFirstByMach");
string redKey = fluxLogFirstMaccHash(idxMacchina);
try
{
DataLayer man = new DataLayer();
rawData = cMemLayer.getRSV(redKey);
if (!string.IsNullOrEmpty(rawData))
{
var redisResult = JsonConvert.DeserializeObject<List<DateTime>>(rawData);
resultList = redisResult != null ? redisResult : new List<DateTime>();
}
else
{
resultList = man.taFL
.getFirstByMacc(idxMacchina, numMax)
.Select(x => x.dtEvento)
.ToList();
// salvo in redis...
rawData = JsonConvert.SerializeObject(resultList);
int IO_CacheFluxLogFirstMin = cMemLayer.CRI("IO_CacheFluxLogFirstMin");
cMemLayer.setRSV(redKey, rawData, IO_CacheFluxLogFirstMin * 60);
}
}
catch (Exception exc)
{
Log.Info($"Eccezione in recupero fluxLogFirstByMach{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
}
else
{
resultList = taFL
.getFirstByMacc(idxMacchina, numMax)
.Select(x => x.dtEvento)
.ToList();
}
if (resultList == null)
{
resultList = new List<DateTime>();
}
return resultList;
}
/// <summary>
/// Effettua force Start PODL [CurrProdStatus = 1] se fosse già in essere ODL collegato
/// --&gt; lascia aperto [CurrProdStatus = 2] se esistesse un ODL da altro PODL x diverso
/// articolo/fase --&gt; chiude vecchio x poi far partire nuovo [CurrProdStatus = 3] se
/// fosse chiuso ODL collegato --&gt; duplica PODL e poi avvia nuovo ODL [CurrProdStatus =
/// 4] se fosse già in essere ODL non collegato --&gt; lascia aperto e collego
/// </summary>
/// <param name="idxMacchina">macchina</param>
/// <param name="CodArt">Codice articolo x PODL da creare</param>
/// <param name="NumPz">Qty assegnata</param>
/// <param name="CodGruppo">Codice Gruppo opzionale, default = ND-00</param>
/// <param name="TCiclo">TCiclo assegnato opzionale, default = 1</param>
/// <returns></returns>
public int ForceCreatePOdl(string idxMacchina, string CodArt, int NumPz, string CodGruppo = "ND-00", decimal TCiclo = 1)
{
int answ = 0;
DateTime adesso = DateTime.Now;
// sistemo codice e descrizione...
string DescArt = CodArt;
CodArt = CodArt.Replace(" ", "_");
// creazione record articolo SE non ci fosse...
var listArt = taAnagArt.getByCod(CodArt);
if (listArt == null || listArt.Count == 0)
{
// cerco x descrizione...
listArt = taAnagArt.getByDescr(DescArt);
// seleziono come codArt il primo trovato...
if (listArt != null && listArt.Count > 0)
{
CodArt = listArt.FirstOrDefault().CodArticolo;
}
}
// ricontrollo se devo creare articolo...
if (listArt == null || listArt.Count == 0)
{
// recupero conf azienda...
string CodAzienda = "*";
var listConf = taConfig.GetData();
var recAzienda = listConf.Where(x => x.chiave.Equals("AZIENDA", StringComparison.CurrentCultureIgnoreCase)).FirstOrDefault();
if (recAzienda != null)
{
CodAzienda = recAzienda.valore != "*" ? recAzienda.valore : recAzienda.valoreStd;
}
taAnagArt.insert(CodArt, DescArt, "", CodArt, "ART", CodAzienda);
}
// creazione richiesta
string keyRich = $"{idxMacchina}-{adesso:yyyyMMdd-HHmmss}";
taPODL.insertQuery(keyRich, keyRich, true, CodArt, CodGruppo, idxMacchina, NumPz, TCiclo, adesso, 1, 1, "");
// cerco PODL da chiave...
var listPOdl = taPODL.getByCodArt(CodArt, true);
var thisPodl = listPOdl.Where(x => x.KeyRichiesta == keyRich).FirstOrDefault();
if (thisPodl != null)
{
answ = thisPodl.idxPromessa;
}
return answ;
}
/// <summary>
/// Effettua force Start PODL [CurrProdStatus = 1] se fosse già in essere ODL collegato
/// --&gt; lascia aperto [CurrProdStatus = 2] se esistesse un ODL da altro PODL x diverso
/// articolo/fase --&gt; chiude vecchio x poi far partire nuovo [CurrProdStatus = 3] se
/// fosse chiuso ODL collegato --&gt; duplica PODL e poi avvia nuovo ODL [CurrProdStatus =
/// 4] se fosse già in essere ODL non collegato --&gt; lascia aperto e collego
/// </summary>
/// <param name="idxMacchina">macchina</param>
/// <param name="idxPODL">IDX PODL da processare</param>
/// <param name="doConfirm">effettuare conferma qty</param>
/// <param name="matrOpr">effettuare conferma qty</param>
/// <param name="dtEve">data-ora di avvio (opzionale)</param>
/// <param name="dtCurr">data-ora attuale (opzionale)</param>
/// <returns></returns>
public string ForceStartPOdl(string idxMacchina, int idxPODL, bool doConfirm, int matrOpr = 0, string dtEve = "", string dtCurr = "")
{
string answ = "KO";
int CurrProdStatus = 0;
string sIdxODL = "";
// Verifica se evento realtime oppure ho data specificata x processing @dtEve
DateTime dtEvent = DateTime.Now;
bool rtimeProc = string.IsNullOrEmpty(dtEve);
if (!rtimeProc)
{
dtEvent = GetSrvDtEvent(dtEve, dtCurr);
}
// verifico NON CI SIA un veto altre chiamate (es split...) - 30 sec di default...
string redKey = vetoForceStartPOdlMaccHash(idxMacchina);
string rawData = cMemLayer.getRSV(redKey);
if (!string.IsNullOrEmpty(rawData))
{
Log.Info($"VETO ATTIVO | Richiesto ForceStartPOdl per impianto {idxMacchina} | impossibile procedere");
}
else
{
// determino veto: se realtime 30sec, altrimenti 1 soltanto
int vetoTtl = rtimeProc ? 30 : 1;
// registro VETO x altre chiamate (es split...) 30sec
cMemLayer.setRSV(redKey, $"Inizio FORCE START PODL: {idxPODL} | realtime: {rtimeProc} | dtEve: {dtEvent}", vetoTtl);
// calcolo la qta da gestire
int qtyConf = 0;
if (doConfirm)
{
DS_ProdTempi.stp_PzProd_getByMacchinaRow rigaProd;
try
{
rigaProd = taPzProd2conf.GetData(idxMacchina)[0];
qtyConf = rigaProd.pezziNonConfermati;
}
catch (Exception exc)
{
Log.Info($"Errore recupero pezzi da confermare per la macchina {idxMacchina}{Environment.NewLine}{exc}", tipoLog.ERROR);
}
}
// proseguo
DS_ProdTempi.ODLDataTable currODLData = null;
DS_ProdTempi.PromesseODLDataTable reqPODLData = null;
DS_ProdTempi.ODLRow OdlRow = null;
DS_ProdTempi.PromesseODLRow POdlRow = null;
// metodo principale...
try
{
sIdxODL = getCurrODL(idxMacchina);
// recupero dati da PODL
reqPODLData = getPODLRowTab(idxPODL);
// recupero ODL corrente...
currODLData = currODLRowTab(idxMacchina);
// procedo SOLO SE ho trovato un PODL
if (reqPODLData != null && reqPODLData.Rows.Count > 0)
{
POdlRow = reqPODLData[0];
// prima cosa: verifico se sia un PODL libero (idxODL==0)
if (reqPODLData[0].IdxODL == 0)
{
if (currODLData != null && currODLData.Count > 0)
{
OdlRow = currODLData[0];
// verifico ODL corrente, se compatibili...
if (OdlRow.CodArticolo == POdlRow.CodArticolo && OdlRow.KeyRichiesta == POdlRow.KeyRichiesta && OdlRow.IdxMacchina == POdlRow.IdxMacchina)
{
// compatibili --> caso 4
CurrProdStatus = 4;
}
else
{
// anche qui chiusura ed avvio
CurrProdStatus = 2;
}
}
else
{
CurrProdStatus = 2;
}
}
// altrimenti se PODL già associato
else
{
// se trovo qualcosa come ODL
if (currODLData != null && currODLData.Count > 0)
{
OdlRow = currODLData[0];
// se è quello già associato
if ($"{reqPODLData[0].IdxODL}" == sIdxODL)
{
// non devo fare nulla
CurrProdStatus = 1;
}
else
{
// altrimenti devo clonare
CurrProdStatus = 3;
}
}
else
{
// anche in questo caso devo clonare PODL
CurrProdStatus = 3;
}
}
}
else
{
Log.Info($"Errore in ForceStartPOdl: non trovato PODL per idxPODL{idxPODL}", tipoLog.ERROR);
}
// OVVIAMENTE solo se ho POdlRow...
if (POdlRow != null)
{
switch (CurrProdStatus)
{
case 1:
// --> non tocco nulla PODL/ODL
Log.Info($"Richiesto ForceStartPOdl, caso 1 | PODL {idxPODL} | ODL {sIdxODL} | nessun intervento", tipoLog.INFO);
break;
case 2:
// eventuale chiusura vecchio ODL, 2 sec prima...
if (currODLData.Count > 0)
{
doCloseCurrODL(idxMacchina, doConfirm, qtyConf, currODLData, dtEvent.AddSeconds(-2), matrOpr);
}
// avvio PODL: creo nuovo ODL da promessa ed associo
taODL.inizioSetupPromessa(idxPODL, MatrOpr, POdlRow.IdxMacchina, POdlRow.TCAssegnato, POdlRow.PzPallet, POdlRow.Note, dtEvent);
// resetto info PODL
resetPODLData(idxPODL);
// fix (invio ) dati ODL alla macchina tramite IOB
Thread.Sleep(200);
answ = saveOdlData(idxMacchina, currODLData, reqPODLData);
break;
case 3:
// eventuale chiusura vecchio ODL
if (currODLData.Count > 0)
{
doCloseCurrODL(idxMacchina, doConfirm, qtyConf, currODLData, dtEvent.AddSeconds(-2), matrOpr);
}
// duplico PODL... inserisco nuovo record...
taPODL.insertQuery(POdlRow.KeyRichiesta, POdlRow.KeyBCode, true, POdlRow.CodArticolo, POdlRow.CodGruppo, POdlRow.IdxMacchina, POdlRow.NumPezzi, POdlRow.TCAssegnato, POdlRow.DueDate, POdlRow.Priorita, POdlRow.PzPallet, POdlRow.Note);
// recupero PODL attivabili...
var podlList = taPODL.getByCodArt(POdlRow.CodArticolo, true);
// cerco quello che ha la stessa fase/macchina e + recente...
var lastPodl = podlList.Where(x => x.KeyRichiesta == POdlRow.KeyRichiesta && x.IdxMacchina == POdlRow.IdxMacchina).OrderByDescending(x => x.idxPromessa).FirstOrDefault();
int newPODL = lastPodl != null ? lastPodl.idxPromessa : POdlRow.idxPromessa;
// avvio (nuovo) PODL
taODL.inizioSetupPromessa(idxPODL, MatrOpr, POdlRow.IdxMacchina, POdlRow.TCAssegnato, POdlRow.PzPallet, POdlRow.Note, dtEvent);
// resetto info PODL
resetPODLData(idxPODL);
// fix (invio ) dati ODL alla macchina tramite IOB
Thread.Sleep(200);
answ = saveOdlData(idxMacchina, currODLData, reqPODLData);
break;
case 4:
// eventuale chiusura vecchio ODL, 2 sec prima...
if (currODLData.Count > 0)
{
doCloseCurrODL(idxMacchina, doConfirm, qtyConf, currODLData, dtEvent.AddSeconds(-2), matrOpr);
}
// avvio PODL: creo nuovo ODL da promessa ed associo
taODL.inizioSetupPromessa(idxPODL, MatrOpr, POdlRow.IdxMacchina, POdlRow.TCAssegnato, POdlRow.PzPallet, POdlRow.Note, dtEvent);
// reseetto info PODL
resetPODLData(idxPODL);
// fix (invio ) dati ODL alla macchina tramite IOB
Thread.Sleep(200);
answ = saveOdlData(idxMacchina, currODLData, reqPODLData);
break;
default:
break;
}
}
else
{
answ = "NF";
}
}
catch (Exception exc)
{
Log.Info($"Eccezione in ForceStartPOdl{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
}
return answ;
}
/// <summary>
/// Recupera ArtNum dato CodArt (per impianti che accettano solo INT in scrittura)
/// </summary>
/// <param name="CodArt">
/// CodArt richiesto, se vuoto restituisce TUTTI i valori in tabella di decodifica
/// </param>
/// <returns>Dizionario contenente le righe delle codifiche attive Articolo/Numero</returns>
public Dictionary<string, int> getArtNum(string codArt)
{
Dictionary<string, int> answ = new Dictionary<string, int>();
DS_applicazione.DecNumArticoliDataTable rawData;
// se vuoto --> leggo tabella
if (string.IsNullOrEmpty(codArt))
{
rawData = taDecNA.GetData();
}
// se non vuoto --> chiamo stored x recuperare info
else
{
rawData = taDecNA.getByKey(codArt);
}
foreach (var item in rawData)
{
answ.Add(item.CodArticolo, item.NumART);
}
return answ;
}
/// <summary>
/// GET elenco parametri correnti x IOB
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public List<objItem> getCurrObjItems(string idxMacchina)
{
string serVal = cMemLayer.getRSV(currParametersHash(idxMacchina));
List<objItem> actValues = new List<objItem>();
if (serVal != null)
{
try
{
var rawVal = JsonConvert.DeserializeObject<List<objItem>>(serVal);
// ordino!
actValues = rawVal
.OrderBy(x => x.displOrdinal)
.ThenBy(x => x.description)
.ToList();
#if false
actValues.Sort((a, b) => (a.name.CompareTo(b.name)));
#endif
}
catch (Exception exc)
{
Log.Info($"Eccezione in deserializzazione getCurrObjItems{Environment.NewLine}{exc}");
}
}
return actValues;
}
/// <summary>
/// GET elenco parametri che richiedono una WRITE x IOB
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public List<objItem> getCurrObjItemsPendigWrite(string idxMacchina)
{
string serVal = cMemLayer.getRSV(currParametersHash(idxMacchina));
List<objItem> actValues = new List<objItem>();
List<objItem> writeValues = new List<objItem>();
if (serVal != null)
{
try
{
actValues = JsonConvert.DeserializeObject<List<objItem>>(serVal);
// cerco e rimuovo parametri sola lettura o SENZA richieste scrittura
foreach (var item in actValues)
{
if (item.writable && !string.IsNullOrEmpty(item.reqValue))
{
writeValues.Add(item);
}
}
}
catch (Exception exc)
{
Log.Info($"Eccezione in deserializzazione getCurrObjItemsPendigWrite{Environment.NewLine}{exc}");
}
}
return writeValues;
}
/// <summary>
/// restituisce valore dell'ODL attivo (iniziato e NON concluso)
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public string getCurrODL(string idxMacchina)
{
string answ = "";
// recupero con stored NUOVA...
DS_ProdTempi.ODLDataTable tabOdl = taODL.getByMacchina(idxMacchina);
if (tabOdl.Rows.Count > 0)
{
// solo SE ho idxODL (altrimenti loggo errore)
if (tabOdl[0].IdxODL > 0)
{
answ = tabOdl[0].IdxODL.ToString();
answ = answ == "" ? "0" : answ;
}
else
{
answ = "0";
Log.Info("[currODL] Errore in currODL x idxMacchina " + idxMacchina + ": IdxODL = 0");
}
}
else
{
// se è empty --> 0!!!
answ = "0";
}
// ultimo controllo su idxOdl...
answ = answ == "" ? "0" : answ;
// restituisco!
return answ;
}
/// <summary>
/// Dati deroga SchedaTecnica serializzati in REDIS (get/set)
/// </summary>
public StCheckOverride getDerogaSt(int idxST)
{
StCheckOverride answ = new StCheckOverride() { IdxST = idxST };
string keyDerogaST = cMemLayer.redHash($"DerogaSt:{user_std.UtSn.utente}:{idxST:000}");
string rawData = cMemLayer.getRSV(keyDerogaST);
if (!string.IsNullOrEmpty(rawData))
{
try
{
answ = JsonConvert.DeserializeObject<StCheckOverride>(rawData);
}
catch
{ }
}
return answ;
}
/// <summary>
/// restituisce una tabella con tutte le transizioni degli ingressi per una data macchina
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public DS_applicazione.TransizioneIngressiDataTable getMatriceIngressi(string idxMacchina)
{
DS_applicazione.TransizioneIngressiDataTable answ;
try
{
answ = taTranIngr.getMatriceByIdxMacchina(idxMacchina);
}
catch
{
answ = null;
}
return answ;
}
/// <summary>
/// Recupera (da DB) i dati della State Machine multi ingressi nel formato
/// key: IdxMacchina
/// value: IdxFamigliaIngresso
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public KeyValuePair<string, string>[] getMSMI_DB(string idxMacchina)
{
DS_applicazione.MSFDDataTable tabMSMI = new DS_applicazione.MSFDDataTable();
// 2017.09.13: inserisco gestione singleton condizionale
if (cMemLayer.CRB("disable_singleton"))
{
// instanzio un nuovo oggetto MapoDb
MapoDb connDb = new MapoDb();
tabMSMI = connDb.taMSFD.getMulti(idxMacchina);
}
else
{
// leggo DB da singleton
tabMSMI = MapoDbObj.taMSFD.getMulti(idxMacchina);
}
KeyValuePair<string, string>[] answ = new KeyValuePair<string, string>[tabMSMI.Count];
// salvo tutti i valori StateMachineIngressi...
int i = 0;
foreach (var item in tabMSMI)
{
answ[i] = new KeyValuePair<string, string>(item.IdxMacchina, item.IdxFamigliaIngresso.ToString());
i++;
}
return answ;
}
/// <summary>
/// Restituisce il valore dell'intera RIGA PODL data chiave (da redis o da DB se non trovata...)
/// </summary>
/// <param name="idxPODL">IDX della PODL</param>
/// <returns></returns>
public DS_ProdTempi.PromesseODLDataTable getPODLRowTab(int idxPODL)
{
DS_ProdTempi.PromesseODLDataTable answTab = null;
string rCall = "";
string rKey = getPOdlRowHash(idxPODL);
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("hasPODL_row");
try
{
rCall = cMemLayer.getRSV(rKey);
if (!string.IsNullOrEmpty(rCall))
{
answTab = JsonConvert.DeserializeObject<DS_ProdTempi.PromesseODLDataTable>(rCall);
}
if (answTab == null || answTab.Count == 0)
{
answTab = taPODL.getByKey(idxPODL);
// salvo in redis...
rCall = JsonConvert.SerializeObject(answTab);
int currOdlRowCacheDur = cMemLayer.CRI("currOdlRowCacheDur");
cMemLayer.setRSV(rKey, rCall, currOdlRowCacheDur);
}
}
catch (Exception exc)
{
Log.Info($"Eccezione in recupero getPODLRowTab{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
}
else
{
answTab = taPODL.getByKey(idxPODL);
}
return answTab;
}
/// <summary>
/// Effettua calcolo data-ora di riferimento per il server a poartire da
/// </summary>
/// <param name="dtEve"></param>
/// <param name="dtCurr"></param>
/// <returns></returns>
public DateTime GetSrvDtEvent(string dtEve, string dtCurr)
{
DateTime dataOraEvento = DateTime.Now;
// 2017.09.14 trimmo eventualmente lo zero finale dalle date SE supera i millisecondi...
dtEve = dtEve.Length > 17 ? dtEve.Substring(0, 17) : dtEve;
dtCurr = dtCurr.Length > 17 ? dtCurr.Substring(0, 17) : dtCurr;
DateTime dtEvento, dtCorrente;
// controllo: se ho valori dt x evento e orario DIVERSI per acquisitore IOB calcolo
// dataOraEvento corretto
if (dtEve != dtCurr)
{
Int64 delta = 0;
try
{
// se ho meno decimali x evento rispetto dtCorrente...
if (dtEve.Length < dtCurr.Length)
{
dtEve = dtEve.PadRight(dtCurr.Length, '0');
}
delta = Convert.ToInt64(dtCurr) - Convert.ToInt64(dtEve);
// se meno di 60'000 ms ...
if (delta < 59999)
{
dataOraEvento = dataOraEvento.AddMilliseconds(-delta);
}
else
{
// in questo caso elimino i MS dalle stringhe e converto i datetime....
CultureInfo provider = CultureInfo.InvariantCulture;
string format = "yyyyMMddHHmmssfff";
dtEvento = DateTime.ParseExact(dtEve, format, provider);
dtCorrente = DateTime.ParseExact(dtCurr, format, provider);
TimeSpan deltaTS = dtCorrente.Subtract(dtEvento);
dataOraEvento = dataOraEvento.Add(-deltaTS);
}
}
catch (Exception exc)
{
Log.Info($"getSrvDtEvent | Errore calcolo ms evento/ora corrente da device remoto:{Environment.NewLine}" +
$"dtEve : {dtEve}{Environment.NewLine}" +
$"dtCurr: {dtCurr}{Environment.NewLine}" +
$"{exc}", tipoLog.EXCEPTION);
}
}
return dataOraEvento;
}
/// <summary>
/// restituisce il TempoCiclo effettivo (tecnico) della macchina
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public decimal getTcEffMacchina(string idxMacchina)
{
decimal tc = 0;
try
{
DS_ProdTempi.stp_repDonati_getDatiProdMacchinaPeriodoRow riga = taDatiProdMacchPer.GetData(idxMacchina, DateTime.Now.AddMinutes(-30), DateTime.Now)[0];
if (riga.TCEffRT > 0)
{
tc = riga.TCEffRT;
}
else
{
tc = riga.TCAssegnato;
}
}
catch { }
// imposto a 99'TC
if (tc == 0)
{
tc = 99.9M;
// scrivo log per indicare mancato caricamento dati tc dichiarato e conseguente
// errore sul timer - 2/11/2012 EN&CV
Log.Info(string.Format("Impostato TC Tempo Ciclo a 99' (99.9M) causa mancato inserimento tempo ciclo dichiarato"));
}
return tc;
}
/// <summary>
/// Restituisce il valore booleano se la macchina sia abilitata all'input
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public bool insEnab(string idxMacchina)
{
bool answ = false;
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("insEnabled");
try
{
answ = Convert.ToBoolean(mDatiMacchinaVal(idxMacchina, "insEnabled"));
}
catch { }
}
// ...oppure dritto su DB
else
{
if (cMemLayer.CRB("disable_singleton"))
{
// instanzio un nuovo oggetto MapoDb
MapoDb connDb = new MapoDb();
answ = connDb.insEnabled(idxMacchina);
}
else
{
// leggo DB da singleton
answ = MapoDbObj.insEnabled(idxMacchina);
}
}
return answ;
}
/// <summary>
/// Restituisce il valore booleano se la macchina sia di tipo MASTER (imposta ODL x gli slave)
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public bool isMaster(string idxMacchina)
{
bool answ = false;
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("isMaster");
try
{
answ = Convert.ToBoolean(mDatiMacchinaVal(idxMacchina, "Master") == "1");
}
catch { }
}
// ...oppure dritto su DB
else
{
answ = MapoDbObj.isMaster(idxMacchina);
}
return answ;
}
/// <summary>
/// Restituisce il valore booleano se la macchina sia di tipo MULTI (con più state machine x INGRESSI)
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public bool isMulti(string idxMacchina)
{
bool answ = false;
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("isMulti");
try
{
answ = Convert.ToBoolean(mDatiMacchinaVal(idxMacchina, "Multi") == "1");
}
catch { }
}
// ...oppure dritto su DB
else
{
answ = MapoDbObj.isMulti(idxMacchina);
}
return answ;
}
/// <summary>
/// Restituisce il valore booleano se la macchina sia di tipo SLAVE (ODL impostato da MASTER)
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public bool isSlave(string idxMacchina)
{
bool answ = false;
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("isSlave");
try
{
answ = Convert.ToBoolean(mDatiMacchinaVal(idxMacchina, "Slave") == "1");
}
catch { }
}
// ...oppure dritto su DB
else
{
answ = MapoDbObj.isSlave(idxMacchina);
}
return answ;
}
/// <summary>
/// Restituisce valore di una singola chiave del dizionario DatiMacchina
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="chiave"></param>
/// <returns></returns>
public string mDatiMacchinaVal(string idxMacchina, string chiave)
{
string answ = "";
try
{
answ = mDatiMacchine(idxMacchina)[chiave];
}
catch { }
return answ;
}
/// <summary>
/// Restitusice elenco KVP dei campi DatiMacchine + StatoMacchine per l'impianto indicato
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public Dictionary<string, string> mDatiMacchine(string idxMacchina)
{
// hard coded dimensione vettore DatiMacchine
Dictionary<string, string> answ = new Dictionary<string, string>();
// ORA recupero da memoria redis...
try
{
string currHash = dtMaccHash(idxMacchina);
answ = cMemLayer.redGetHashDict(currHash);
// se è vuoto... leggo da DB e popolo!
if (answ.Count == 0)
{
answ = resetDatiMacchina(idxMacchina);
}
}
catch (Exception exc)
{
Log.Info(string.Format("Errore in compilazione dati Macchine x Redis - idxMacchina {2}:{0}{1}", Environment.NewLine, exc, idxMacchina));
}
return answ;
}
/// <summary>
/// Restitusice elenco KVP dei TASK (da passare a IOB-WIN) per l'impianto indicato
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public Dictionary<string, string> mOptParMacchina(string idxMacchina)
{
// hard coded dimensione vettore DatiMacchine
Dictionary<string, string> answ = new Dictionary<string, string>();
// ORA recupero da memoria redis...
try
{
string currHash = optParHash(idxMacchina);
answ = cMemLayer.redGetHashDict(currHash);
}
catch (Exception exc)
{
Log.Info(string.Format("Errore in compilazione dati OPT PARAM x Redis - idxMacchina {2}:{0}{1}", Environment.NewLine, exc, idxMacchina));
}
return answ;
}
/// <summary>
/// Restitusice elenco KVP dei TASK SALVATI (da passare a IOB-WIN) per l'impianto indicato
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public Dictionary<string, string> mSavedTaskMacchina(string idxMacchina)
{
// hard coded dimensione vettore DatiMacchine
Dictionary<string, string> answ = new Dictionary<string, string>();
// ORA recupero da memoria redis...
try
{
string currHash = savedTaskHash(idxMacchina);
answ = cMemLayer.redGetHashDict(currHash);
}
catch (Exception exc)
{
Log.Info($"Errore in recupero dati SAVED TASK x Redis mSavedTaskMacchina | idxMacchina {idxMacchina}{Environment.NewLine}{exc}");
}
return answ;
}
/// <summary>
/// Restitusice elenco KVP
/// key: IdxMacchina
/// value: IdxFamigliaIngresso
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public KeyValuePair<string, string>[] mTabMSMI(string idxMacchina)
{
// hard coded dimensione vettore DatiMacchine
KeyValuePair<string, string>[] answ = new KeyValuePair<string, string>[1];
// iniziualizzo con un valore... 0/0
answ[0] = new KeyValuePair<string, string>("0", "0");
// ORA recupero da memoria redis...
try
{
string currHash = hMSMI(idxMacchina);
answ = cMemLayer.redGetHash(currHash);
// se è vuoto... leggo da DB e popolo!
if (answ.Length == 0)
{
answ = resetMSMI(idxMacchina);
}
}
catch (Exception exc)
{
Log.Info(string.Format("Errore in compilazione Tabella Multi State Machine Ingressi x Redis:{0}{1}", Environment.NewLine, exc));
}
return answ;
}
/// <summary>
/// Restitusice elenco KVP dei campi della State Machine ingressi nel formato
/// key: cState_nVal (current MICRO-STATE + "_" + new Value)
/// value: iTipoEv_nState (IdxTipoEv da trasmettere + New MICRO-STATE
/// </summary>
/// <param name="idxFamIn"></param>
/// <returns></returns>
public KeyValuePair<string, string>[] mTabSMI(int idxFamIn)
{
// hard coded dimensione vettore DatiMacchine
KeyValuePair<string, string>[] answ = new KeyValuePair<string, string>[1];
// iniziualizzo con un valore... 0/0
answ[0] = new KeyValuePair<string, string>("0", "0");
// ORA recupero da memoria redis...
try
{
string currHash = hSMI(idxFamIn);
answ = cMemLayer.redGetHash(currHash);
// se è vuoto... leggo da DB e popolo!
if (answ.Length == 0)
{
answ = resetSMI(idxFamIn);
}
}
catch (Exception exc)
{
Log.Info(string.Format("Errore in compilazione State Machine Ingressi x Redis:{0}{1}", Environment.NewLine, exc));
}
return answ;
}
/// <summary>
/// Restitusice elenco KVP dei TASK (da passare a IOB-WIN) per l'impianto indicato
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public Dictionary<string, string> mTaskMacchina(string idxMacchina)
{
// hard coded dimensione vettore DatiMacchine
Dictionary<string, string> answ = new Dictionary<string, string>();
// ORA recupero da memoria redis...
try
{
string currHash = exeTaskHash(idxMacchina);
answ = cMemLayer.redGetHashDict(currHash);
}
catch (Exception exc)
{
Log.Info(string.Format("Errore in recupero dati EXE TASK x Redis mTaskMacchina - idxMacchina {2}:{0}{1}", Environment.NewLine, exc, idxMacchina));
}
return answ;
}
/// <summary>
/// Processa registrazione FL da IOB
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="flux"></param>
/// <param name="valore"></param>
/// <param name="dtEve"></param>
/// <param name="dtCurr"></param>
/// <param name="contatore"></param>
/// <param name="disabKA"></param>
/// <returns></returns>
public string processFluxLog(string idxMacchina, string flux, string valore, string dtEve, string dtCurr, int contatore, bool disabKA)
{
// instanzio un nuovo oggetto MapoDb
MapoDb connDb = new MapoDb();
// se non vietato...
if (!disabKA)
{
// scrivo keep alive!!! (se necessario, altrimenti è in cache...)
connDb.scriviKeepAlive(idxMacchina, DateTime.Now);
}
// registro conteggio impiego chiamate REDIS
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("processFluxLog");
}
string answ = "";
DateTime dataOraEvento = GetSrvDtEvent(dtEve, dtCurr);
// inizio processing vero e proprio INPUT...
if (idxMacchina != null && valore != null)
{
if (idxMacchina != "" && valore != "")
{
// 2020.01.31 nuovo OBJ
DataLayer man = new DataLayer();
man.taFL.InsNew(idxMacchina, dataOraEvento, flux, valore, contatore);
// 2022.06.06 salvo su redis il valore ULTIMO del flux x recupero rapido ultimo valore
string key = DataLayer.LiveFLogKeyHash(idxMacchina, flux);
// 10 min cache max...
int ttlFlog = 60 * 10;
cMemLayer.setRSV(key, valore, ttlFlog);
// registro in risposta che è andato tutto bene...
answ = "OK";
}
else
{
string errore = "processFluxLog | Errore: parametri macchina/valore vuoti";
Log.Info(errore, tipoLog.INFO);
answ = errore;
}
}
else
{
string errore = "processFluxLog | Errore: mancano parametri macchina/valore";
Log.Info(errore, tipoLog.INFO);
answ = errore;
}
return answ;
}
/// <summary>
/// Processa input da IOB eventualmente registrando i segnali inviati
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="valore"></param>
/// <param name="dtEve"></param>
/// <param name="dtCurr"></param>
/// <param name="contatore"></param>
/// <returns></returns>
public string processInput(string idxMacchina, string valore, string dtEve, string dtCurr, string contatore)
{
string answ = "";
// 2018.10.26 controllo dtEve e dtCurr
if (dtEve == null || dtCurr == null)
{
Log.Info(string.Format("procInput: valori nulli date: idxMacchina: {0} | valore: {1} | dtEve: {2} | dtCurr:{3}", idxMacchina, valore, dtEve, dtCurr));
}
else if (dtEve.Length < 17 || dtCurr.Length < 17)
{
Log.Info(string.Format("procInput: valori data non corretti: idxMacchina: {0} | valore: {1} | dtEve: {2} | dtCurr:{3}", idxMacchina, valore, dtEve, dtCurr));
}
else
{
// 2017.09.14 trimmo eventualmente lo zero finale dalle date SE supera i millisecondi...
dtEve = dtEve.Length > 17 ? dtEve.Substring(0, 17) : dtEve;
dtCurr = dtCurr.Length > 17 ? dtCurr.Substring(0, 17) : dtCurr;
// registro conteggio impiego chiamate REDIS
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("processInput");
}
DateTime dataOraEvento = DateTime.Now;
DateTime dtEvento, dtCorrente;
// controllo: se ho valori dt x evento e orario DIVERSI per acquisitore IOB calcolo
// dataOraEvento corretto
if (dtEve != dtCurr)
{
// delta è un calcolo MOLTO approssimativo della differenza temporale...
Int64 delta = 0;
try
{
// se ho meno decimali x evento rispetto dtCorrente...
if (dtEve.Length < dtCurr.Length)
{
Log.Info(string.Format("processInput: fix valore dtEve: {0} vs dtCurr: {1}", dtEve, dtCurr), tipoLog.INFO);
dtEve = dtEve.PadRight(dtCurr.Length, '0');
}
delta = Convert.ToInt64(dtCurr) - Convert.ToInt64(dtEve);
// log della classe del delta (1-10, 10-100, 100-1k, 1k-10k, > 10k ms)
string deltaClass = "";
// faccio SEMPRE calcolo esatto sennò sbaglia...
CultureInfo provider = CultureInfo.InvariantCulture;
string format = "yyyyMMddHHmmssfff";
dtEvento = DateTime.ParseExact(dtEve, format, provider);
dtCorrente = DateTime.ParseExact(dtCurr, format, provider);
Int64 tiks = dtCorrente.Ticks - dtEvento.Ticks;
TimeSpan ts = new TimeSpan(tiks);
double ms = Math.Abs(ts.TotalMilliseconds);
// calcolo ESATTO dataora evento
dataOraEvento = dataOraEvento.AddTicks(-tiks);
if (ms <= 10)
{
deltaClass = "delta 0-10 ms";
}
else if (ms <= 100)
{
deltaClass = "delta 10-100 ms";
}
else if (ms <= 1000)
{
deltaClass = "delta 100-1000 ms";
}
else if (ms <= 10000)
{
deltaClass = "delta 1-10 sec";
}
else
{
deltaClass = "delta > 10 sec";
}
// se ho deltaClass loggo
if (deltaClass != "")
{
Log.Info("Correzione " + deltaClass);
}
}
catch (Exception exc)
{
Log.Info(string.Format("Errore calcolo ms evento/ora corrente da device remoto:{0}dtEve : {1}{0}dtCurr: {2}{0}{3}", Environment.NewLine, dtEve, dtCurr, exc), tipoLog.EXCEPTION);
}
}
// inizio processing vero e proprio INPUT...
if (idxMacchina != null && valore != null)
{
if (idxMacchina != "" && valore != "")
{
// 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la
// gestione NUOVO oggetto
if (cMemLayer.CRB("disable_singleton"))
{
// instanzio un nuovo oggetto MapoDb
MapoDb connDb = new MapoDb();
// se abilitato registro evento sul DB
if (idxMacchina != "" && sLogEnab(idxMacchina))
{
saveSigLog(idxMacchina, valore, dataOraEvento, contatore);
}
// continuo col resto
try
{
// scrivo keep alive!!! (se necessario, altrimenti è in cache...)
connDb.scriviKeepAlive(idxMacchina, DateTime.Now);
// verifico se sia una macchina MULTI ed in tal caso calcolo i
// SUB-systems e CHIAMERO' alla fine pure loro....
if (isMulti(idxMacchina))
{
// inizio preprocessing
string newVal = "";
// processo OGNI macchina a stati dell'impianto... (KEY:
// IdxMacchina / IdxMacchina#qualcosa, Val = IdxFamIn)
foreach (var item in mTabMSMI(idxMacchina))
{
newVal = preProcInput(item.Key, valore);
// ora processo e salvo il valore del microstato...
// INTERNAMENTE gestisce i casi DB/REDIS secondo necessità
checkMicroStato(item.Key, newVal, dataOraEvento, contatore);
}
}
else
{
// ora processo e salvo il valore del microstato... INTERNAMENTE
// gestisce i casi DB/REDIS secondo necessità
checkMicroStato(idxMacchina, valore, dataOraEvento, contatore);
}
// registro in risposta che è andato tutto bene...
answ = "OK";
}
catch (Exception exc)
{
if (cMemLayer.CRI("_logLevel") > 5)
{
string errore = string.Format("Errore: {0}{1}", Environment.NewLine, exc);
Log.Info(errore, tipoLog.EXCEPTION);
answ = errore;
}
}
}
else
{
// se abilitato registro evento sul DB
if (idxMacchina != "" && MapoDbObj.sLogEnabled(idxMacchina))
{
saveSigLog(idxMacchina, valore, dataOraEvento, contatore);
}
// continuo col resto
try
{
// scrivo keep alive!!! (se encessario, altrimenti è in cache...)
MapoDbObj.scriviKeepAlive(idxMacchina, DateTime.Now);
// verifico se sia una macchina MULTI ed in tal caso calcolo i
// SUB-systems e CHIAMERO' alla fine pure loro....
if (MapoDbObj.isMulti(idxMacchina))
{
// inizio preprocessing
string newVal = "";
// processo OGNI macchina a stati dell'impianto... (KEY:
// IdxMacchina / IdxMacchina#qualcosa, Val = IdxFamIn)
foreach (var item in getMSMI_DB(idxMacchina))
{
newVal = preProcInput(item.Key, valore);
// ora processo e salvo il valore del microstato...
checkMicroStato(item.Key, newVal, dataOraEvento, contatore);
}
}
else
{
// ora processo e salvo il valore del microstato...
checkMicroStato(idxMacchina, valore, dataOraEvento, contatore);
}
answ = "OK"; // registro in risposta che è andato tutto bene...
}
catch (Exception exc)
{
if (cMemLayer.CRI("_logLevel") > 5)
{
string errore = string.Format("Errore: {0}{1}", Environment.NewLine, exc);
Log.Info(errore, tipoLog.EXCEPTION);
answ = errore;
}
}
}
}
else
{
string errore = "Errore: parametri macchina/valore vuoti";
Log.Info(errore, tipoLog.INFO);
answ = errore;
}
}
else
{
string errore = "Errore: mancano parametri macchina/valore";
Log.Info(errore, tipoLog.INFO);
answ = errore;
}
}
return answ;
}
/// <summary>
/// Processa registrazione di uno stream di dati LIVE da IOB
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="liveData">Dati live nel formato di lista di KVP chiave/valore1</param>
/// <returns></returns>
public string processLiveJson(string idxMacchina, liveIOB liveData)
{
if (liveData == null)
{
throw new ArgumentNullException(nameof(liveData));
}
// registro conteggio impiego chiamate REDIS
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("processLiveJson");
}
string answ = "";
DateTime dataOraEvento = DateTime.Now;
// inizio processing vero e proprio INPUT...
if (!string.IsNullOrEmpty(idxMacchina) && liveData != null)
{
// SE ho dei segnali...
if (liveData.dataList.Count > 0)
{
// salvo in Redis nell'area CURR_VAL TUTTI i valori live
cMemLayer.redSaveHashList(LiveCurrValHash(idxMacchina), liveData.dataList);
// accodo in buffer ULTIMI valori con dataora uno ad uno...
KeyValuePair<string, string>[] newData = new KeyValuePair<string, string>[1];
foreach (var item in liveData.dataList)
{
// accodo update valori...
newData[0] = new KeyValuePair<string, string>(dataOraEvento.ToString(), item.Value);
cMemLayer.redSaveHash(LiveBufferHash(idxMacchina, item.Key), newData);
}
}
else
{
string errore = "Errore: formato liveData errato (split #)";
Log.Info(errore, tipoLog.ERROR);
answ = errore;
}
// registro in risposta che è andato tutto bene...
answ = "OK";
}
else
{
string errore = "Errore: mancano parametri macchina/liveData come Json";
Log.Info(errore, tipoLog.ERROR);
answ = errore;
}
return answ;
}
/// <summary>
/// Processa registrazione di uno stream di dati LIVE da IOB
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="liveData">Dati live nel formato chiave1|valore1#chiave2|valore2#chiave3|valore3</param>
/// <returns></returns>
public string processLiveRec(string idxMacchina, string liveData)
{
if (liveData == null)
{
throw new ArgumentNullException(nameof(liveData));
}
// registro conteggio impiego chiamate REDIS
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("processLiveRec");
}
string answ = "";
DateTime dataOraEvento = DateTime.Now;
// inizio processing vero e proprio INPUT...
if (idxMacchina != null && liveData != null)
{
if (idxMacchina != "" && liveData != "")
{
// prendo il vettore LiveData e lo splitto per variabili inviate
string[] liveSignals = liveData.Split('|');
// SE ho dei segnali...
if (liveSignals.Length > 0)
{
KeyValuePair<string, string>[] liveSet = new KeyValuePair<string, string>[liveSignals.Length];
string[] kvp;
int i = 0;
foreach (string liveKVP in liveSignals)
{
// ogni variabile la splitto come chiave/valore
kvp = liveKVP.Split(':');
liveSet[i] = new KeyValuePair<string, string>(kvp[0], kvp[1]);
i++;
}
// salvo in Redis nell'area CURR_VAL TUTTI i valori live
cMemLayer.redSaveHash(LiveCurrValHash(idxMacchina), liveSet);
// accodo in buffer ULTIMI valori con dataora uno ad uno...
KeyValuePair<string, string>[] newData = new KeyValuePair<string, string>[1];
foreach (var item in liveSet)
{
// accodo update valori...
newData[0] = new KeyValuePair<string, string>(dataOraEvento.ToString(), item.Value);
cMemLayer.redSaveHash(LiveBufferHash(idxMacchina, item.Key), newData);
}
}
else
{
string errore = "Errore: formato liveData errato (split #)";
Log.Info(errore, tipoLog.ERROR);
answ = errore;
}
// registro in risposta che è andato tutto bene...
answ = "OK";
}
else
{
string errore = "Errore: parametri macchina/liveData vuoti";
Log.Info(errore, tipoLog.ERROR);
answ = errore;
}
}
else
{
string errore = "Errore: mancano parametri macchina/liveData";
Log.Info(errore, tipoLog.ERROR);
answ = errore;
}
return answ;
}
/// <summary>
/// Processa registrazione UserLog da IOB
/// </summary>
/// <param name="idxMacchina">Macchina</param>
/// <param name="flux">Flusso: DI/RC/RC</param>
/// <param name="valore">valore = note/valString</param>
/// <param name="dtEve">data evento</param>
/// <param name="dtCurr">data corrente</param>
/// <param name="contatore">contatore invio</param>
/// <param name="matrOpr">Matricola Operatore</param>
/// <param name="label">label = causale scarto / tagCode</param>
/// <param name="valNum">valNum = esitoOk (0/1) / Quantità di scarto associata</param>
/// <returns></returns>
public string processUserLog(string idxMacchina, string flux, string valore, string dtEve, string dtCurr, int contatore, int matrOpr, string label, int valNum)
{
// instanzio un nuovo oggetto MapoDb
MapoDb connDb = new MapoDb();
// scrivo keep alive!!! (se necessario, altrimenti è in cache...)
connDb.scriviKeepAlive(idxMacchina, DateTime.Now);
// 2017.09.14 trimmo eventualmente lo zero finale dalle date SE supera i millisecondi...
dtEve = dtEve.Length > 17 ? dtEve.Substring(0, 17) : dtEve;
dtCurr = dtCurr.Length > 17 ? dtCurr.Substring(0, 17) : dtCurr;
// registro conteggio impiego chiamate REDIS
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("processUserLog");
}
string answ = "";
DateTime dataOraEvento = DateTime.Now;
DateTime dtEvento, dtCorrente;
// controllo: se ho valori dt x evento e orario DIVERSI per acquisitore IOB calcolo
// dataOraEvento corretto
if (dtEve != dtCurr)
{
Int64 delta = 0;
try
{
// se ho meno decimali x evento rispetto dtCorrente...
if (dtEve.Length < dtCurr.Length)
{
dtEve = dtEve.PadRight(dtCurr.Length, '0');
}
delta = Convert.ToInt64(dtCurr) - Convert.ToInt64(dtEve);
// se meno di 60'000 ms ...
if (delta < 59999)
{
dataOraEvento = dataOraEvento.AddMilliseconds(-delta);
}
else
{
// in questo caso elimino i MS dalle stringhe e converto i datetime....
CultureInfo provider = CultureInfo.InvariantCulture;
string format = "yyyyMMddHHmmssfff";
dtEvento = DateTime.ParseExact(dtEve, format, provider);
dtCorrente = DateTime.ParseExact(dtCurr, format, provider);
Int64 tiks = dtCorrente.Ticks - dtEvento.Ticks;
dataOraEvento = dataOraEvento.AddTicks(-tiks);
}
}
catch (Exception exc)
{
Log.Info(string.Format("processUserLog | Errore calcolo ms evento/ora corrente da device remoto:{0}dtEve : {1}{0}dtCurr: {2}{0}{3}", Environment.NewLine, dtEve, dtCurr, exc), tipoLog.EXCEPTION);
}
}
// inizio processing vero e proprio INPUT...
if (string.IsNullOrEmpty(idxMacchina))
{
string errore = "processUserLog | Errore: macchina mancante";
Log.Info(errore, tipoLog.INFO);
answ = errore;
}
else
{
if (string.IsNullOrEmpty(flux))
{
string errore = "processUserLog | Errore: parametro flux vuoto";
Log.Info(errore, tipoLog.INFO);
answ = errore;
}
else
{
// 2020.01.31 nuovo OBJ
DataLayer DLMan = new DataLayer();
// in base al flusso decido dove e cosa scrivere...
switch (flux)
{
case "DI":
DLMan.taDiarioDich.insertQuery(label, idxMacchina, dataOraEvento, matrOpr, valore);
break;
case "RC":
bool esitoOk = valNum != 0;
DLMan.taRC.insertQuery(idxMacchina, matrOpr, esitoOk, valore, dataOraEvento);
break;
case "RS":
DLMan.taRS.insertQuery(idxMacchina, dataOraEvento, label, valNum, valore, matrOpr);
break;
default:
break;
}
// registro in risposta che è andato tutto bene...
answ = "OK";
}
}
return answ;
}
/// <summary>
/// Restituisce il contapezzi salvato per la macchina
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public int pzCounter(string idxMacchina)
{
int answ = -1;
string rCall = "";
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("getCounter");
try
{
rCall = cMemLayer.getRSV(pzCountHash(idxMacchina));
if (rCall != "" && rCall != null)
{
int.TryParse(rCall, out answ);
}
else
{
answ = pzCounterTC(idxMacchina);
// salvo in redis...
saveCounter(idxMacchina, answ.ToString());
}
}
catch { }
}
return answ;
}
/// <summary>
/// Restituisce il contapezzi come CONTEGGIO da TCRilevati per la macchina
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public int pzCounterTC(string idxMacchina)
{
int answ = -1;
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("getCounterTC");
}
// variabile x controllo dati recuperati
DS_ProdTempi.StatoProdDataTable datiProdAct = null;
bool okDatiProd = false;
int taSP_ms_ant = cMemLayer.cdvi("taStatoProd_ms_anticipo");
DateTime dataRif = DateTime.Now.AddMilliseconds(-taSP_ms_ant);
okDatiProd = getStatoProd(idxMacchina, ref datiProdAct, dataRif);
// se NON avesse recuperato --> aspetto taSP_ms_ant e poi RICHIAMO procedura...
int maxTry = 3;
while (!okDatiProd && maxTry > 0)
{
Log.Info(string.Format("[pzCounterTC] Impossibile recuperare dati ODL x idxMacchina {0}", idxMacchina), tipoLog.WARNING);
// sleep...
Thread.Sleep(taSP_ms_ant * 2);
// riprovo lettura...
okDatiProd = getStatoProd(idxMacchina, ref datiProdAct, dataRif);
maxTry--;
}
// ora proseguo SE ho trovato i dati...
if (okDatiProd)
{
if (datiProdAct != null)
{
if (datiProdAct.Count > 0)
{
if (!datiProdAct[0].IsPzTotODLNull())
{
// ...a questo punto recupero DAVVERO i dati (o almeno ci provo...)
try
{
// controllo
answ = datiProdAct[0].PzTotODL;
}
catch (Exception exc)
{
Log.Info(string.Format("[pzCounterTC] Eccezione in recupero PzTotODL x idxMacchina {0}{1}{2}", idxMacchina, Environment.NewLine, exc), tipoLog.EXCEPTION);
}
}
}
}
}
else
{
Log.Info(string.Format("[pzCounterTC] Dati ODL x idxMacchina {0} non recuperati dopo tentativi reiterati...", idxMacchina), tipoLog.WARNING);
}
return answ;
}
/// <summary>
/// RIMUOVE un PARAMETRO OPZIONALE dall'elenco di quelli salvati
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="taskKey"></param>
/// <returns></returns>
public bool remOptPar4Machine(string idxMacchina, string taskKey)
{
bool answ = false;
string currHash = optParHash(idxMacchina);
try
{
// leggo task attuali...
var currVal = mOptParMacchina(idxMacchina);
currVal.Remove(taskKey);
cMemLayer.redDelKey(currHash);
answ = cMemLayer.redSaveHashDict(currHash, currVal);
}
catch { }
return answ;
}
/// <summary>
/// RIMUOVE un task dall'elenco di quelli salvati
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="taskKey"></param>
/// <returns></returns>
public bool remTask4Machine(string idxMacchina, taskType taskKey)
{
bool answ = false;
string currHash = exeTaskHash(idxMacchina);
try
{
// leggo task attuali...
var currTask = mTaskMacchina(idxMacchina);
currTask.Remove(taskKey.ToString());
cMemLayer.redDelKey(currHash);
answ = cMemLayer.redSaveHashDict(currHash, currTask);
Log.Info($"Task REM - idxMacchina: {idxMacchina} | taskKey: {taskKey.ToString()}");
}
catch { }
return answ;
}
/// <summary>
/// Resetta (rileggendo) i dati della macchina
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public Dictionary<string, string> resetDatiMacchina(string idxMacchina)
{
string currHash = dtMaccHash(idxMacchina);
// inizio con un bel reset...
cMemLayer.redFlushKey(currHash);
Dictionary<string, string> answ = new Dictionary<string, string>();
DS_applicazione.MSFDDataTable tabMSFD = new DS_applicazione.MSFDDataTable();
// 2018.01.08 SEMPRE senza singleton: instanzio un nuovo oggetto MapoDb
MapoDb connDb = new MapoDb();
tabMSFD = connDb.taMSFD.getByIdxMacc(idxMacchina);
bool trovato = false;
// se ho righe...
DS_applicazione.MSFDDataTable tab = new DS_applicazione.MSFDDataTable();
DS_applicazione.MSFDRow rigaMSFD;
if (tabMSFD.Rows.Count > 0)
{
try
{
rigaMSFD = tabMSFD[0];
trovato = true;
}
catch
{
rigaMSFD = tab.NewMSFDRow();
}
}
else
{
rigaMSFD = tab.NewMSFDRow();
}
if (trovato)
{
// ora provo a compilare...
try
{
// salvo 1:1 i valori... STATO
answ.Add("IdxMicroStato", rigaMSFD.IdxMicroStato.ToString());
answ.Add("IdxStato", rigaMSFD.IdxStato.ToString());
answ.Add("CodArticolo", rigaMSFD.CodArticolo);
answ.Add("insEnabled", rigaMSFD.insEnabled.ToString());
answ.Add("sLogEnabled", rigaMSFD.sLogEnabled.ToString());
answ.Add("pallet", rigaMSFD.pallet);
answ.Add("CodArticolo_A", rigaMSFD.CodArticolo_A);
answ.Add("CodArticolo_B", rigaMSFD.CodArticolo_B);
answ.Add("TempoCicloBase", rigaMSFD.TempoCicloBase.ToString());
answ.Add("PzPalletProd", rigaMSFD.PzPalletProd.ToString());
answ.Add("MatrOpr", rigaMSFD.MatrOpr.ToString());
answ.Add("lastVal", rigaMSFD.lastVal);
answ.Add("TCBase", rigaMSFD.TempoCicloBase.ToString());
//...e SETUP
answ.Add("CodMacc", rigaMSFD.codmacchina);
answ.Add("IdxFamIn", rigaMSFD.IdxFamigliaIngresso.ToString());
answ.Add("Multi", rigaMSFD.Multi.ToString());
answ.Add("BitFilt", rigaMSFD.BitFilt.ToString());
answ.Add("MaxVal", rigaMSFD.MaxVal.ToString());
answ.Add("BSR", rigaMSFD.BSR.ToString());
answ.Add("ExplodeBit", rigaMSFD.ExplodeBit.ToString());
answ.Add("NumBit", rigaMSFD.NumBit.ToString());
answ.Add("IdxFamMacc", rigaMSFD.IdxFamiglia.ToString());
answ.Add("simplePallet", rigaMSFD.simplePallet.ToString());
answ.Add("palletChange", rigaMSFD.palletChange.ToString());
}
catch (Exception exc)
{
Log.Info(string.Format("Errore in compilazione dati MSFD:{0}{1}", Environment.NewLine, exc), tipoLog.EXCEPTION);
}
// cerco dati master/slave...
string isMaster = connDb.taM2S.getByMaster(idxMacchina).Count > 0 ? "1" : "0";
string isSlave = connDb.taM2S.getBySlave(idxMacchina).Count > 0 ? "1" : "0";
answ.Add("Master", isMaster);
answ.Add("Slave", isSlave);
// verifico il timeout che cambia a seconda che sia vero o falso insEnabled...
int tOutShort = cMemLayer.cdvi("TmOut.MS.S");
int tOutLong = cMemLayer.cdvi("TmOut.MS.L");
int redDtMacTOut = tOutLong;
try
{
redDtMacTOut = (answ["insEnabled"].ToLower() == "true") ? tOutShort : tOutLong;
}
catch (Exception exc)
{
Log.Info($"Eccezione in calcolo timeout dati macchina: idxMacchina{idxMacchina} | TShort: {tOutShort} | TLong {tOutLong}{Environment.NewLine}{exc}");
}
// salvo in redis!
cMemLayer.redSaveHashDict(currHash, answ, redDtMacTOut);
}
else
{
Log.Info("Errore in chiamata stp_MSFD_getMacc (connDb.taMSFD.getByIdxMacc(idxMacchina))");
}
return answ;
}
/// <summary>
/// Effettua reset microstato macchina
/// </summary>
/// <param name="idxMacchina"></param>
public void resetMicrostatoMacchina(string idxMacchina)
{
// salvo microstato 0...
DateTime dtEve = DateTime.Now;
MapoDbObj.taMSM.updateQuery(0, dtEve, "FER", idxMacchina);
// reset in redis
resetDatiMacchina(idxMacchina);
}
/// <summary>
/// Resetta (rileggendo) i dati della State Machine multi ingressi nel formato
/// key: IdxMacchina
/// value: IdxFamigliaIngresso
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public KeyValuePair<string, string>[] resetMSMI(string idxMacchina)
{
string currHash = hMSMI(idxMacchina);
DS_applicazione.MSFDDataTable tabMSMI = new DS_applicazione.MSFDDataTable();
// 2017.09.13: inserisco gestione singleton condizionale
if (cMemLayer.CRB("disable_singleton"))
{
// instanzio un nuovo oggetto MapoDb
MapoDb connDb = new MapoDb();
tabMSMI = connDb.taMSFD.getMulti(idxMacchina);
}
else
{
// leggo DB da singleton
tabMSMI = MapoDbObj.taMSFD.getMulti(idxMacchina);
}
KeyValuePair<string, string>[] answ = new KeyValuePair<string, string>[tabMSMI.Count];
// salvo tutti i valori StateMachineIngressi...
int i = 0;
foreach (var item in tabMSMI)
{
answ[i] = new KeyValuePair<string, string>(item.IdxMacchina, item.IdxFamigliaIngresso.ToString());
i++;
}
// verifico il timeout (default 60 sec...)
int tOut = (cMemLayer.cdvi("TmOut.MSMI") <= 0) ? 60 : cMemLayer.cdvi("TmOut.MSMI");
// salvo in redis!
cMemLayer.redSaveHash(currHash, answ, tOut);
return answ;
}
/// <summary>
/// Resetta (rileggendo) i dati della State Machine ingressi nel formato
/// key: cState_nVal (current MICRO-STATE + "_" + new Value)
/// value: iTipoEv_nState (IdxTipoEv da trasmettere + New MICRO-STATE)
/// </summary>
/// <param name="idxFamIn"></param>
/// <returns></returns>
public KeyValuePair<string, string>[] resetSMI(int idxFamIn)
{
string currHash = hSMI(idxFamIn);
DS_applicazione.TransizioneIngressiDataTable tabSMI = new DS_applicazione.TransizioneIngressiDataTable();
// 2017.09.13: inserisco gestione singleton condizionale
if (cMemLayer.CRB("disable_singleton"))
{
// instanzio un nuovo oggetto MapoDb
MapoDb connDb = new MapoDb();
tabSMI = connDb.taTransIngr.getByIdxFamIng(idxFamIn);
}
else
{
// leggo DB da singleton
tabSMI = MapoDbObj.taTransIngr.getByIdxFamIng(idxFamIn);
}
KeyValuePair<string, string>[] answ = new KeyValuePair<string, string>[tabSMI.Count];
// salvo tutti i valori StateMachineIngressi...
int i = 0;
string key = "";
string val = "";
foreach (var item in tabSMI)
{
key = string.Format("{0}_{1}", item.IdxMicroStato, item.ValoreIngresso);
val = string.Format("{0}_{1}", item.IdxTipoEvento, item.next_IdxMicroStato);
answ[i] = new KeyValuePair<string, string>(key, val);
i++;
}
// verifico il timeout (default 60 sec...)
int tOut = (cMemLayer.cdvi("TmOut.SMI") <= 0) ? 60 : cMemLayer.cdvi("TmOut.SMI");
// salvo in redis!
cMemLayer.redSaveHash(currHash, answ, tOut);
return answ;
}
/// <summary>
/// rigenera la tab diario di bordo x la macchian richiesta nell'intervallo definito
/// </summary>
/// <param name="IdxMacchina"></param>
/// <param name="dataInizio"></param>
/// <param name="dataFine"></param>
public void rigeneraDiarioDiBordo(string IdxMacchina, DateTime dataInizio, DateTime dataFine)
{
// elimino da diario di bordo i valori nell'intervallo...
MapoDbObj.taDiario.DeleteByMacchinaPeriodo(IdxMacchina, dataInizio, dataFine);
// seleziono le righe eventi interessate e le processo 1 ad 1...
DS_applicazione.EventListDataTable tabEventi = MapoDbObj.taEvList.GetByMacchinaPeriodo(IdxMacchina, dataInizio, dataFine);
foreach (DS_applicazione.EventListRow rigaEv in tabEventi)
{
if (rigaEv.IdxTipo <= 12) // è barcode
{
checkCambiaStatoBatch(tipoInputEvento.barcode, IdxMacchina, rigaEv.InizioStato, rigaEv.IdxTipo, rigaEv.CodArticolo, rigaEv.Value, rigaEv.MatrOpr, rigaEv.pallet);
}
else // è hw
{
checkCambiaStatoBatch(tipoInputEvento.hw, IdxMacchina, rigaEv.InizioStato, rigaEv.IdxTipo, rigaEv.CodArticolo, rigaEv.Value, rigaEv.MatrOpr, rigaEv.pallet);
}
}
}
/// <summary>
/// Processa registrazione EVENTO CONTEGGIO PEZZI x una data macchina IOB
/// </summary>
/// <param name="idxMacchina">Macchina</param>
/// <param name="qty">Pezzi da registrare</param>
/// <returns></returns>
public string saveCaricoPezzi(string idxMacchina, string qty)
{
// default: 0, non registrato come cautela...
string answ = "0";
// controllo per proseguire
if (!string.IsNullOrEmpty(idxMacchina) && !string.IsNullOrEmpty(qty))
{
int numPzIncr = -1;
int.TryParse(qty, out numPzIncr);
// se il conteggio è >= 0 SALVO evento...
if (numPzIncr >= 0)
{
// recupero ODL corrente
var currData = currODLRowTab(idxMacchina);
// registro evento 120 --> contapezzi in blocco !!!HARD CODED!!! !!!FIXME!!!
int idxEvento = 120;
// istanziato un NUOVO oggetto x scrivere...
scriviRigaEventoBarcode(idxMacchina, idxEvento, currData[0].CodArticolo, qty);
}
// registro in risposta che è andato tutto bene... ovvero la qty richiesta...
answ = qty;
}
else
{
string errore = $"Errore: mancano parametri macchina/incremento: idxMacchina {idxMacchina} | qty {qty}";
Log.Info(errore, tipoLog.ERROR);
answ = errore;
}
return answ;
}
/// <summary>
/// Processa registrazione EVENTO CONTEGGIO PEZZI x una data macchina IOB
/// </summary>
/// <param name="idxMacchina">Macchina</param>
/// <param name="qty">Pezzi da registrare</param>
/// <returns></returns>
public string saveCaricoPezzi(string idxMacchina, string qty, string dtEve = "", string dtCurr = "")
{
// default: 0, non registrato come cautela...
string answ = "0";
// Verifica se evento realtime oppure ho data specificata x processing @dtEve
DateTime adesso = DateTime.Now;
DateTime dtEvent = adesso;
bool rtimeProc = string.IsNullOrEmpty(dtEve);
if (!rtimeProc)
{
dtEvent = GetSrvDtEvent(dtEve, dtCurr);
}
// controllo per proseguire
if (!string.IsNullOrEmpty(idxMacchina) && !string.IsNullOrEmpty(qty))
{
int numPzIncr = -1;
int.TryParse(qty, out numPzIncr);
// se il conteggio è >= 0 SALVO evento...
if (numPzIncr >= 0)
{
string codArt = "";
// recupero ODL ALLA DATA.. da evento a 1 sec dopo
DataLayer man = new DataLayer();
var listOdl = man.taODL.getByMacchinaPeriodo(idxMacchina, dtEvent, dtEvent.AddSeconds(1));
if (listOdl != null && listOdl.Count > 0)
{
codArt = listOdl.FirstOrDefault().CodArticolo;
// registro evento 120 --> contapezzi in blocco !!!HARD CODED!!! !!!FIXME!!!
int idxEvento = 120;
// istanziato un NUOVO oggetto x scrivere...
scriviRigaEventoBarcode(idxMacchina, idxEvento, codArt, qty, 0, "", dtEvent, adesso);
// registro in risposta che è andato tutto bene... ovvero la qty richiesta...
answ = qty;
}
}
}
else
{
string errore = $"Errore: mancano parametri macchina/incremento: idxMacchina {idxMacchina} | qty {qty}";
Log.Info(errore, tipoLog.ERROR);
answ = errore;
}
return answ;
}
/// <summary>
/// Processa registrazione di un counter x una data macchina IOB
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="counter">contapezzi</param>
/// <returns></returns>
public string saveCounter(string idxMacchina, string counter)
{
// registro conteggio impiego chiamate REDIS
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("saveCounter");
}
string answ = "0";
// inizio processing vero e proprio INPUT...
if (!string.IsNullOrEmpty(idxMacchina))
{
if (!string.IsNullOrEmpty(counter))
{
int newCounter = -1;
int.TryParse(counter, out newCounter);
// se il conteggio è >= 0 SALVO come nuovo conteggio...
if (newCounter >= 0)
{
string redKey = pzCountHash(idxMacchina);
// verifico SE ci sia chiave in redis (ALTRIMENTI rileggo da DB)
string redVal = cMemLayer.getRSV(redKey);
if (!string.IsNullOrEmpty(redVal))
{
// salvo in Redis nell'area corretta il valore richiesto
cMemLayer.setRSV(redKey, counter);
// imposto risposta...
answ = counter;
}
else
{
// rileggo da DB e salvo e poi restituisco questo...
int currCount = pzCounterTC(idxMacchina);
cMemLayer.setRSV(redKey, currCount.ToString());
// imposto risposta...
answ = currCount.ToString();
}
}
}
else
{
string errore = "Errore: parametro counter vuoto";
Log.Info(errore, tipoLog.ERROR);
answ = errore;
}
}
else
{
string errore = "Errore: parametro macchina vuoto";
Log.Info(errore, tipoLog.ERROR);
answ = errore;
}
return answ;
}
/// <summary>
/// Processa registrazione ODL corrente x macchina
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="currODL">cod ODL in produzione, se "" --&gt; non c'è...</param>
/// <returns></returns>
public string saveCurrODL(string idxMacchina, string currODL)
{
if (currODL == null)
{
throw new ArgumentNullException(nameof(currODL));
}
// registro conteggio impiego chiamate REDIS
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("saveCurrODL");
}
string answ = "";
// inizio processing vero e proprio INPUT...
if (idxMacchina != null && currODL != null)
{
if (idxMacchina != "" && currODL != "")
{
int currOdlCacheDur = cMemLayer.CRI("currOdlCacheDur");
// se ODL fosse 0 USO DURATA CACHE 1/4...
if (currODL == "0")
{
currOdlCacheDur = currOdlCacheDur / 4;
}
cMemLayer.setRSV(currODLHash(idxMacchina), currODL, currOdlCacheDur);
// registro in risposta che è andato tutto bene...
answ = "OK";
}
else
{
string errore = string.Format("Errore: parametri macchina/currODL vuoti ({0}/{1})", idxMacchina, currODL);
Log.Info(errore, tipoLog.ERROR);
answ = errore;
}
}
else
{
string errore = "Errore: mancano parametri macchina/currODL";
Log.Info(errore, tipoLog.ERROR);
answ = errore;
}
return answ;
}
/// <summary>
/// salva il segnale di "microstato"
/// </summary>
/// <param name="idxMacchina">idx macchina</param>
/// <param name="valore">valore ingresso</param>
/// <param name="dtEve">data-ora evento (server)</param>
/// <param name="contatore">sequenza dati inviati</param>
/// <returns></returns>
public void saveSigLog(string idxMacchina, string valore, DateTime dtEve, string contatore)
{
int cont = 0;
try
{
cont = Convert.ToInt32(contatore);
}
catch { }
// 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione NUOVO oggetto
if (cMemLayer.CRB("disable_singleton"))
{
// 2017.06.09 forzo init x errori "sovrapposizioni"
taSigLog = new DS_applicazioneTableAdapters.SignalLogTableAdapter();
}
taSigLog.Insert(DateTime.Now, idxMacchina, valore, dtEve, cont);
}
/// <summary>
/// scrive una riga di evento nel db
/// </summary>
/// <param name="IdxMacchina">codice macchina</param>
/// <param name="IdxTipo">idx evento</param>
/// <param name="CodArticolo">Codice Articolo</param>
/// <param name="Value">valore</param>
/// <param name="MatrOpr">matricola operatore</param>
/// <param name="pallet">pallet (vuoto se nd)</param>
/// <param name="eventTime">data-ora dell'evento</param>
/// <param name="currentTime">data-ora corrente dell'invio</param>
/// <returns></returns>
public inputComandoMapo scriviRigaEvento(string IdxMacchina, int IdxTipo, string CodArticolo, string Value, int MatrOpr, string pallet, DateTime eventTime, DateTime currentTime)
{
int inserito = 0;
// 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione NUOVO oggetto
if (cMemLayer.CRB("disable_singleton"))
{
// 2017.06.09 forzo init x errori "sovrapposizioni"
MapoDbObj.taEvList = new DS_applicazioneTableAdapters.EventListTableAdapter();
}
try
{
// verifico se esista la macchina altrimenti la creo...
verificaIdxMacchina(IdxMacchina);
// calcolo dataOra reale (evento + delta(ora server - ora remota)
DateTime dataOra = eventTime.Add(DateTime.Now - currentTime);
// inserisco evento
inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet);
// faccio controllo per eventuale cambio stato da tab transizioni...
checkCambiaStatoBatch(tipoInputEvento.hw, IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet);
}
catch (Exception exc)
{
Log.Info(string.Format("Errore in fase di scrittura evento con i seguenti dati:{0} macchina {1}{0} IdxTipo {2}{0} CodArticolo {3}{0} Value {4}{0} MatrOpr {5}{0} Pallet {6}{0} eventTime {7}{0} currentTime {8}{0} eccezione: {0}{9}", Environment.NewLine, IdxMacchina, IdxTipo, CodArticolo, Value, MatrOpr, pallet, eventTime, currentTime, exc), tipoLog.EXCEPTION);
}
// formatto output
inputComandoMapo answ = new inputComandoMapo();
answ.outValue = inserito.ToString();
answ.needStatusRefresh = true;
return answ;
}
/// <summary>
/// scrive una riga di evento nel db
/// </summary>
/// <param name="IdxMacchina">codice macchina</param>
/// <param name="IdxTipo">idx evento</param>
/// <param name="CodArticolo">Codice Articolo</param>
/// <param name="Value">valore</param>
/// <param name="MatrOpr">matricola operatore</param>
/// <param name="pallet">pallet (vuoto se nd)</param>
/// <returns></returns>
public inputComandoMapo scriviRigaEvento(string IdxMacchina, int IdxTipo, string CodArticolo, string Value, int MatrOpr, string pallet)
{
int inserito = 0;
// 2017.06.09 forzo init x errori "sovrapposizioni"
MapoDbObj.taEvList = new DS_applicazioneTableAdapters.EventListTableAdapter();
try
{
// verifico se esista la macchina altrimenti la creo...
verificaIdxMacchina(IdxMacchina);
DateTime dataOra = DateTime.Now;
// inserisco evento
inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet);
// faccio controllo per eventuale cambio stato da tab transizioni...
checkCambiaStatoBatch(tipoInputEvento.hw, IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet);
}
catch (Exception exc)
{
Log.Info(string.Format("Errore in fase di scrittura evento con i seguenti dati:{0} macchina {1}{0} IdxTipo {2}{0} CodArticolo {3}{0} Value {4}{0} MatrOpr {5}{0} Pallet {6}{0} eccezione:{0}{7}", Environment.NewLine, IdxMacchina, IdxTipo, CodArticolo, Value, MatrOpr, pallet, exc), tipoLog.EXCEPTION);
}
// formatto output
inputComandoMapo answ = new inputComandoMapo();
answ.outValue = inserito.ToString();
answ.needStatusRefresh = true;
return answ;
}
/// <summary>
/// scrive una riga di evento nel db SENZA passare operatore e pallet (mette a 0 e "-")
/// </summary>
/// <param name="IdxMacchina">codice macchina</param>
/// <param name="IdxTipo">idx evento</param>
/// <param name="CodArticolo">Codice Articolo</param>
/// <param name="Value">valore</param>
/// <returns></returns>
public inputComandoMapo scriviRigaEvento(string IdxMacchina, int IdxTipo, string CodArticolo, string Value)
{
int inserito = 0;
try
{
// verifico se esista la macchina altrimenti la creo...
verificaIdxMacchina(IdxMacchina);
DateTime dataOra = DateTime.Now;
// inserisco evento
inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, 0, "-");
// faccio controllo per eventuale cambio stato da tab transizioni...
checkCambiaStatoBatch(tipoInputEvento.hw, IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, 0, "-");
}
catch
{
Log.Info(string.Format("Errore in fase di scrittura evento con i seguenti dati:{0} macchina {1}{0} IdxTipo {2}{0} CodArticolo {3}{0} Value {4}{0} eccezione: {0}{5}", Environment.NewLine, IdxMacchina, IdxTipo, CodArticolo, Value), tipoLog.EXCEPTION);
}
// formatto output
inputComandoMapo answ = new inputComandoMapo();
answ.outValue = inserito.ToString();
answ.needStatusRefresh = true;
return answ;
}
/// <summary>
/// scrive una riga di evento inviato da Barcode nel db
/// </summary>
/// <param name="IdxMacchina">codice macchina</param>
/// <param name="IdxTipo">idx evento</param>
/// <param name="CodArticolo">Codice Articolo</param>
/// <param name="Value">valore</param>
/// <param name="MatrOpr">matricola operatore</param>
/// <param name="pallet">pallet (vuoto se nd)</param>
/// <param name="eventTime">data-ora dell'evento</param>
/// <param name="currentTime">data-ora corrente dell'invio</param>
/// <returns></returns>
public inputComandoMapo scriviRigaEventoBarcode(string IdxMacchina, int IdxTipo, string CodArticolo, string Value, int MatrOpr, string pallet, DateTime eventTime, DateTime currentTime)
{
int inserito = 0;
// calcolo dataOra reale (evento + delta(ora server - ora remota)
DateTime dataOra = eventTime.Add(DateTime.Now - currentTime);
try
{
// verifico se esista la macchina altrimenti la creo...
verificaIdxMacchina(IdxMacchina);
// inserisco evento
inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet);
}
catch (Exception exc)
{
Log.Info(string.Format("Errore in fase di scrittura evento con i seguenti dati:{0} macchina {1}{0} IdxTipo {2}{0} CodArticolo {3}{0} Value {4}{0} MatrOpr {5}{0} Pallet {6}{0} eventTime {7}{0} currentTime {8}{0} eccezione: {0}{9}", Environment.NewLine, IdxMacchina, IdxTipo, CodArticolo, Value, MatrOpr, pallet, eventTime, currentTime, exc), tipoLog.EXCEPTION);
}
try
{
// faccio controllo per eventuale cambio stato da tab transizioni...
checkCambiaStatoBatch(tipoInputEvento.barcode, IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet);
}
catch (Exception exc)
{
Log.Info($"Eccezione in checkCambiaStatoBatch(8) | tipoInputEvento: {tipoInputEvento.barcode} | IdxMacchina: {IdxMacchina} | dataOra: {dataOra} | IdxTipo: {IdxTipo} | CodArticolo: {CodArticolo} | Value: {Value} | MatrOpr: {MatrOpr} | pallet: {pallet}{Environment.NewLine}{exc}");
}
// formatto output
inputComandoMapo answ = new inputComandoMapo();
answ.outValue = inserito.ToString();
answ.needStatusRefresh = true;
return answ;
}
/// <summary>
/// scrive una riga di evento inviato da Barcode nel db
/// </summary>
/// <param name="IdxMacchina">codice macchina</param>
/// <param name="IdxTipo">idx evento</param>
/// <param name="CodArticolo">Codice Articolo</param>
/// <param name="Value">valore</param>
/// <param name="MatrOpr">matricola operatore</param>
/// <param name="pallet">pallet (vuoto se nd)</param>
/// <returns></returns>
public inputComandoMapo scriviRigaEventoBarcode(string IdxMacchina, int IdxTipo, string CodArticolo, string Value, int MatrOpr, string pallet)
{
int inserito = 0;
DateTime dataOra = DateTime.Now;
try
{
// verifico se esista la macchina altrimenti la creo...
verificaIdxMacchina(IdxMacchina);
// inserisco evento
inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet);
}
catch (Exception exc)
{
Log.Info(string.Format("Errore in fase di scrittura evento con i seguenti dati:{0} macchina {1}{0} IdxTipo {2}{0} CodArticolo {3}{0} Value {4}{0} MatrOpr {5}{0} Pallet {6}{0} eccezione: {0}{7}", Environment.NewLine, IdxMacchina, IdxTipo, CodArticolo, Value, MatrOpr, pallet, exc), tipoLog.EXCEPTION);
}
try
{
// faccio controllo per eventuale cambio stato da tab transizioni...
checkCambiaStatoBatch(tipoInputEvento.barcode, IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet);
}
catch (Exception exc)
{
Log.Info($"Eccezione in checkCambiaStatoBatch(6) | tipoInputEvento: {tipoInputEvento.barcode} | IdxMacchina: {IdxMacchina} | dataOra: {dataOra} | IdxTipo: {IdxTipo} | CodArticolo: {CodArticolo} | Value: {Value} | MatrOpr: {MatrOpr} | pallet: {pallet}{Environment.NewLine}{exc}");
}
// formatto output
inputComandoMapo answ = new inputComandoMapo();
answ.outValue = inserito.ToString();
answ.needStatusRefresh = true;
return answ;
}
/// <summary>
/// scrive una riga di evento inviato da Barcode nel db SENZA operatore e pallet (mette a 0
/// e "-")
/// </summary>
/// <param name="IdxMacchina">codice macchina</param>
/// <param name="IdxTipo">idx evento</param>
/// <param name="CodArticolo">Codice Articolo</param>
/// <param name="Value">valore</param>
/// <returns></returns>
public inputComandoMapo scriviRigaEventoBarcode(string IdxMacchina, int IdxTipo, string CodArticolo, string Value)
{
int inserito = 0;
DateTime dataOra = DateTime.Now;
try
{
// verifico se esista la macchina altrimenti la creo...
verificaIdxMacchina(IdxMacchina);
// inserisco evento
inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, 0, "-");
}
catch
{
Log.Info(string.Format("Errore in fase di scrittura evento con i seguenti dati:{0} macchina {1}{0} IdxTipo {2}{0} CodArticolo {3}{0} Value {4}{0} eccezione: {0}{5}", Environment.NewLine, IdxMacchina, IdxTipo, CodArticolo, Value), tipoLog.EXCEPTION);
}
try
{
// faccio controllo per eventuale cambio stato da tab transizioni...
checkCambiaStatoBatch(tipoInputEvento.barcode, IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, 0, "-");
}
catch (Exception exc)
{
Log.Info($"Eccezione in checkCambiaStatoBatch(4) | tipoInputEvento: {tipoInputEvento.barcode} | IdxMacchina: {IdxMacchina} | dataOra: {dataOra} | IdxTipo: {IdxTipo} | CodArticolo: {CodArticolo} | Value: {Value} | MatrOpr: 0 | pallet: -{Environment.NewLine}{exc}");
}
// formatto output
inputComandoMapo answ = new inputComandoMapo();
answ.outValue = inserito.ToString();
answ.needStatusRefresh = true;
return answ;
}
public int scriviRigaEventoSimulata(DateTime dataOra, string IdxMacchina, int IdxTipo, string CodArticolo, string Value, int MatrOpr, string pallet)
{
// verifico se esista la macchina altrimenti la creo...
verificaIdxMacchina(IdxMacchina);
// inserisco evento
int inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, MatrOpr, pallet);
return inserito;
}
public int scriviRigaEventoSimulata(DateTime dataOra, string IdxMacchina, int IdxTipo, string CodArticolo, string Value)
{
// verifico se esista la macchina altrimenti la creo...
verificaIdxMacchina(IdxMacchina);
// inserisco evento
int inserito = MapoDbObj.taEvList.Insert(IdxMacchina, dataOra, IdxTipo, CodArticolo, Value, 0, "-");
return inserito;
}
/// <summary>
/// scrive una riga di stato nel diario di bordo
/// </summary>
/// <param name="IdxMacchina">codice macchina</param>
/// <param name="IdxStato">idx stato</param>
/// <param name="CodArticolo">Codice Articolo</param>
/// <param name="Value">valore</param>
/// <param name="MatrOpr">matricola operatore</param>
/// <param name="pallet">pallet (vuoto se nd)</param>
/// <param name="eventTime">data-ora dell'evento</param>
/// <param name="currentTime">data-ora corrente dell'invio</param>
/// <returns></returns>
public inputComandoMapo scriviRigaStato(string IdxMacchina, int IdxStato, string CodArticolo, string Value, int MatrOpr, string pallet, DateTime eventTime, DateTime currentTime)
{
int inserito = 0;
try
{
// verifico se esista la macchina altrimenti la creo...
verificaIdxMacchina(IdxMacchina);
// calcolo dataOra reale (evento + delta(ora server - ora remota)
DateTime dataOra = eventTime.Add(DateTime.Now - currentTime);
// inserisco la nuova riga di stato mentre il trigger aggiorna le tab...
inserito = MapoDbObj.taDiario.Insert(IdxMacchina, dataOra, null, IdxStato, null, Value, CodArticolo, null, null, MatrOpr, pallet);
}
catch
{
Log.Info(string.Format("Errore in fase di scrittura stato con i seguenti dati:{0} macchina {1}{0} IdxStato {2}{0} CodArticolo {3}{0} Value {4}{0} MatrOpr {5}{0} Pallet {6}{0} eventTime {7}{0} currentTime {8}{0} eccezione: {0}{9}", Environment.NewLine, IdxMacchina, IdxStato, CodArticolo, Value, MatrOpr, pallet, eventTime, currentTime), tipoLog.EXCEPTION);
}
// formatto output
inputComandoMapo answ = new inputComandoMapo();
answ.outValue = inserito.ToString();
answ.needStatusRefresh = true;
return answ;
}
public int scriviRigaStatoSimulata(DateTime dataOra, string IdxMacchina, int IdxStato, string CodArticolo, string Value, int MatrOpr, string pallet)
{
// verifico se esista la macchina altrimenti la creo...
verificaIdxMacchina(IdxMacchina);
// inserisco la nuova riga di stato mentre il trigger aggiorna le tab...
int inserito = MapoDbObj.taDiario.Insert(IdxMacchina, dataOra, null, IdxStato, null, Value, CodArticolo, null, null, MatrOpr, pallet);
return inserito;
}
public int scriviRigaStatoSimulata(DateTime dataOra, string IdxMacchina, int IdxStato, string CodArticolo, string Value)
{
// verifico se esista la macchina altrimenti la creo...
verificaIdxMacchina(IdxMacchina);
// inserisco la nuova riga di stato mentre il trigger aggiorna le tab...
int inserito = MapoDbObj.taDiario.Insert(IdxMacchina, dataOra, null, IdxStato, null, Value, CodArticolo, null, null, 0, "-");
return inserito;
}
/// <summary>
/// Invia una mail al destinatario con oggetto e contenuto
/// </summary>
/// <param name="destinatario"></param>
/// <param name="oggetto"></param>
/// <param name="corpo"></param>
/// <returns></returns>
public bool sendEmail(string destinatario, string oggetto, string corpo)
{
bool fatto = false;
try
{
// compongo la stringa
string mittente = cMemLayer.CRS("_fromEmail");
gestEmail.geAuth.mandaEmail(mittente, destinatario, oggetto, corpo);
fatto = true;
}
catch (Exception exc)
{
Log.Info($"Eccezione in sendEmail{Environment.NewLine}{exc}", tipoLog.ERROR);
}
return fatto;
}
/// <summary>
/// invia una mail al destinatario x linkare nuovi devices tramite URL
/// </summary>
/// <param name="destinatario"></param>
/// <param name="UserAuthKey"></param>
/// <param name="idxDipendente"></param>
/// <returns></returns>
public bool sendUserAuthEmail(string destinatario, string UserAuthKey, int idxDipendente)
{
bool fatto = false;
string smtpCli = "";
string mittente = "";
string oggetto = "";
string userUrl = "";
string baseUrl = "";
string userWebUrl = "";
string baseWebUrl = "";
string corpo = "";
try
{
// compongo la stringa
smtpCli = cMemLayer.CRS("_smtpCli");
mittente = cMemLayer.CRS("_fromEmail");
oggetto = "Link autorizzazione device per GPW";
baseUrl = cMemLayer.CRS("baseUrl");
baseWebUrl = cMemLayer.CRS("baseWebUrl");
userUrl = string.Format("{2}jumper.aspx?UserAuthkey={0}&idxDipendente={1}", UserAuthKey, idxDipendente, baseUrl);
userWebUrl = string.Format("{2}jumper.aspx?UserAuthkey={0}&idxDipendente={1}", UserAuthKey, idxDipendente, baseWebUrl);
corpo = string.Format("Hai ricevuto questa email su richiesta tua o dell'Admin per poter procedere a registrare un (nuovo) devices con GPW:{0}<br/>Per proseguire clicca sul link seguente(rete interna):<br />{0}{0}{1}{0}{0}<br /><br />oppure sul link seguente (internet):<br />{0}{0}{2}{0}{0}<br /><br />Team GPW Steamware", Environment.NewLine, userUrl, userWebUrl);
gestEmail.geAuth.mandaEmail(mittente, destinatario, oggetto, corpo);
fatto = true;
}
catch { }
return fatto;
}
/// <summary>
/// Invia email di avviso che ci sono dei TC da confermare
/// </summary>
/// <param name="destinatario"></param>
/// <returns></returns>
public bool sendWarnTcChangeReq(string destinatario)
{
bool fatto = false;
string mittente = "";
string oggetto = "";
string pageUrl = "";
string corpo = "";
try
{
// compongo la stringa
mittente = cMemLayer.CRS("_fromEmail");
oggetto = cMemLayer.CRS("oggettoChgTc");
pageUrl = string.Format("{0}{1}", cMemLayer.CRS("baseUrlAdmin"), cMemLayer.CRS("pageUrlApprODL"));
corpo = string.Format(cMemLayer.CRS("corpoChgTc"), Environment.NewLine, pageUrl);
if (cMemLayer.CRB("_useAuthSmtp"))
{
gestEmail.geAuth.mandaEmail(mittente, destinatario, oggetto, corpo);
}
else
{
gestEmail.ge.mandaEmail(mittente, destinatario, oggetto, corpo);
}
fatto = true;
}
catch { }
return fatto;
}
/// <summary>
/// SET elenco parametri correnti x IOB
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="currValues"></param>
/// <returns></returns>
public bool setCurrObjItems(string idxMacchina, List<objItem> currValues)
{
bool answ = false;
if (currValues != null)
{
string serVal = JsonConvert.SerializeObject(currValues);
cMemLayer.setRSV(currParametersHash(idxMacchina), serVal);
// controllo se ha valori write...
foreach (var item in currValues)
{
// se fosse un valore WRITE e mi ha dato un valore vuoto --> mando un fix x riscrittura
if (item.writable && (string.IsNullOrEmpty(item.value) || string.IsNullOrEmpty(item.reqValue)))
{
Log.Info($"setCurrObjItems | parametro empty | {item.uid} | Value: {item.value} | reqVal: {item.reqValue}");
// se è un parametro dei "task principali...
try
{
taskType currTask = (taskType)Enum.Parse(typeof(taskType), item.uid);
string newVal = !string.IsNullOrEmpty(item.reqValue) ? item.reqValue : $"{item.value}";
addCheckTask4Machine(idxMacchina, currTask, newVal);
}
catch (Exception exc)
{
Log.Info($"Eccezione in setCurrObjItems in fase di riaccodamento{Environment.NewLine}{exc}");
}
}
}
answ = true;
}
return answ;
}
public bool setDerogaSt(StCheckOverride deroga)
{
bool fatto = false;
try
{
string keyDerogaST = cMemLayer.redHash($"DerogaSt:{user_std.UtSn.utente}:{deroga.IdxST:000}");
string rawData = JsonConvert.SerializeObject(deroga);
cMemLayer.setRSV(keyDerogaST, rawData, 60 * 2);
fatto = true;
}
catch
{ }
return fatto;
}
/// <summary>
/// Salvataggio YAML completo di configurazione dell'IOB
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="iobConfFull"></param>
/// <returns></returns>
public bool setIobConfYaml(string idxMacchina, string iobConfFull)
{
bool answ = false;
// se ho un area memoria valida...
if (!string.IsNullOrEmpty(iobConfFull))
{
// salvo!
cMemLayer.setRSV(ConfYamlHash(idxMacchina), iobConfFull);
}
return answ;
}
/// <summary>
/// Salvataggio della mappa di memoria dell'IOB x ulteriori impieghi
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="currMemMap"></param>
/// <returns></returns>
public bool setIobMemMap(string idxMacchina, plcMemMap currMemMap)
{
bool answ = false;
// se ho un area memoria valida...
if (currMemMap != null)
{
// salvo!
string serVal = JsonConvert.SerializeObject(currMemMap);
cMemLayer.setRSV(memMapHash(idxMacchina), serVal);
}
return answ;
}
/// <summary>
/// Restituisce il valore booleano se la macchina sia abilitata all'inserimento COMPLETO nel
/// Signal Log
/// </summary>
/// <param name="idxMacchina"></param>
/// <returns></returns>
public bool sLogEnab(string idxMacchina)
{
bool answ = false;
if (cMemLayer.CRB("IOB_RedEnab"))
{
saveCallRec("sLogEnabled");
try
{
answ = Convert.ToBoolean(mDatiMacchinaVal(idxMacchina, "sLogEnabled"));
}
catch { }
}
// ...oppure dritto su DB
else
{
answ = MapoDbObj.sLogEnabled(idxMacchina);
}
return answ;
}
/// <summary>
/// Effettua chiamata DB x snapshot del FluxLog della macchina richiesta (insieme set ultimi dati)
/// </summary>
/// <param name="id">IdxMacchina</param>
/// <param name="id">
/// Dimensione della finestra temporale da ultimo record indietro x salvare valori
/// </param>
/// <returns></returns>
public string takeFlogSnapshot(string id, int windSize)
{
string answ = "ND";
// instanzio un nuovo oggetto MapoDb
MapoDb connDb = new MapoDb();
// scrivo keep alive!!! (se necessario, altrimenti è in cache...)
connDb.scriviKeepAlive(id, DateTime.Now);
try
{
// ora chiamo la stored di duplicazione
DataLayer DLMan = new DataLayer();
DLMan.taFL.takeSnapshot(id, windSize);
answ = "OK";
}
catch (Exception exc)
{
Log.Info($"takeFlogSnapshot:{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
return answ;
}
/// <summary>
/// Effettua chiamata DB x snapshot del FluxLog della macchina richiesta (insieme set ultimi dati)
/// </summary>
/// <param name="id">IdxMacchina</param>
/// <param name="dtMin">DT start x effettuare snapshot</param>
/// <param name="dtMax">DT end x effettuare snapshot</param>
/// <returns></returns>
public string takeFlogSnapshotLast(string id, DateTime dtMin, DateTime dtMax)
{
string answ = "ND";
// instanzio un nuovo oggetto MapoDb
MapoDb connDb = new MapoDb();
// scrivo keep alive!!! (se necessario, altrimenti è in cache...)
connDb.scriviKeepAlive(id, DateTime.Now);
try
{
// ora chiamo la stored di duplicazione
DataLayer DLMan = new DataLayer();
DLMan.taFL.TakeSnapshotLast(id, dtMin, dtMax);
answ = "OK";
}
catch (Exception exc)
{
Log.Info($"TakeSnapshotLast:{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
return answ;
}
/// <summary>
/// Aggiornamento parametro per macchina
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="Original_uid">Parametro macchina come definito in file json</param>
/// <param name="reqValue"></param>
/// <returns></returns>
public bool updateMachineParameter(string idxMacchina, string Original_uid, string reqValue)
{
bool answ = false;
// recupero items...
List<objItem> dcList = getCurrObjItems(idxMacchina);
List<objItem> list2Update = new List<objItem>();
// cerco quello da aggiornare
objItem trovato = dcList.Find(obj => obj.uid == Original_uid);
// se non trova --> crea ed aggiunge...
if (trovato == null)
{
dcList.Add(new objItem() { uid = Original_uid });
trovato = dcList.Find(obj => obj.uid == Original_uid);
}
// se trovato procedo
if (trovato != null)
{
// aggiorno valore richiesto + dt richiesta
trovato.reqValue = reqValue;
trovato.lastRequest = DateTime.Now;
list2Update.Add(trovato);
upsertCurrObjItems(idxMacchina, list2Update);
// accodo in task 2 exe la richiesta di processing
addTask4Machine(idxMacchina, taskType.setParameter, trovato.uid);
// salvo ANCHE il valore di setup ASSOCIATO...
taskType currTask = (taskType)Enum.Parse(typeof(taskType), trovato.uid);
addTask4Machine(idxMacchina, currTask, reqValue);
answ = true;
}
return answ;
}
/// <summary>
/// Effettua UPSERT elenco parametri correnti x IOB (se c'è UPDATE, se manca ADD)
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="innovations"></param>
/// <returns></returns>
public bool upsertCurrObjItems(string idxMacchina, List<objItem> innovations)
{
bool answ = false;
if (innovations != null)
{
Log.Info($"upsertCurrObjItems | idxMacchina: {idxMacchina} | {innovations.Count} innovations");
// leggo i valori attuali...
List<objItem> actValues = getCurrObjItems(idxMacchina);
// per ogni valore passatomi faccio insert o update rispetto elenco valori correnti
// in REDIS
foreach (var item in actValues)
{
// cerco nelle innovazioni SE CI SIA il valore...
objItem trovato = innovations.Find(obj => obj.uid == item.uid);
// se non trovato nelle innovazioni...
if (trovato == null)
{
// lo ri-aggiungo x non perderlo
innovations.Add(item);
Log.Trace($"innovations | add | item.uid: {item.uid} | item.value: {item.value}");
}
else
// altrimenti aggiorno campo (non trasmesso) name e tengo il resto...
{
trovato.name = item.name;
Log.Info($"innovations | update | item.uid: {item.uid} | item.value: {item.value} --> {trovato.value} ");
}
}
// serializzo e salvo
string serVal = JsonConvert.SerializeObject(innovations);
cMemLayer.setRSV(currParametersHash(idxMacchina), serVal);
}
return answ;
}
/// <summary>
/// Restituisce il valore SPECIFICATO per la state machine ingressi
/// value: iTipoEv_nState (IdxTipoEv da trasmettere + New MICRO-STATE)
/// </summary>
/// <param name="idxFamIn"></param>
/// <param name="idxMicroStato"></param>
/// <param name="valoreIn"></param>
/// <returns></returns>
public string valoreSMI(int idxFamIn, int idxMicroStato, int valoreIn)
{
string currHash = hSMI(idxFamIn);
string field = string.Format("{0}_{1}", idxMicroStato, valoreIn);
return cMemLayer.redGetHashField(currHash, field);
}
#endregion Public Methods
#region Protected Fields
/// <summary>
/// indica conferma con rettifica (evento 121)
/// </summary>
protected bool confRett = false;
#endregion Protected Fields
#region Protected Methods
/// <summary>
/// init dei table adapters
/// </summary>
protected void initTA()
{
// istanzio oggetto
taAG = new DS_applicazioneTableAdapters.AnagraficaGruppiTableAdapter();
taAlarmLog = new DS_applicazioneTableAdapters.AlarmLogTableAdapter();
taAnagArt = new DS_ProdTempiTableAdapters.AnagArticoliTableAdapter();
taAnagEventi = new DS_applicazioneTableAdapters.AnagraficaEventiTableAdapter();
taAnagStati = new DS_applicazioneTableAdapters.AnagraficaStatiTableAdapter();
taAnagTags = new DS_applicazioneTableAdapters.AnagTagsTableAdapter();
taAs400 = new DS_IntServTableAdapters.ProduzioneAs400TableAdapter();
taArcaGiac = new DS_ArcaTableAdapters.GiacenzeTableAdapter();
taDecNA = new DS_applicazioneTableAdapters.DecNumArticoliTableAdapter();
taCalFF = new DS_ProdTempiTableAdapters.CalendFesteFerieTableAdapter();
taComm = new DS_UtilityTableAdapters.CommentiTableAdapter();
taConfFlux = new DS_DossParTableAdapters.ConfFluxTableAdapter();
taConfig = new DS_UtilityTableAdapters.ConfigTableAdapter();
taDatiConf = new DS_ProdTempiTableAdapters.DatiConfermatiTableAdapter();
taDatiMacchine = new DS_ProdTempiTableAdapters.DatiMacchineTableAdapter();
taDatiProd = new DS_ProdTempiTableAdapters.DatiProduzioneTableAdapter();
taDatiProdMacch = new DS_ProdTempiTableAdapters.stp_repDonati_getDatiProdMacchinaTableAdapter();
taDatiProdMacchPer = new DS_ProdTempiTableAdapters.stp_repDonati_getDatiProdMacchinaPeriodoTableAdapter();
taDatiStatoMacch = new DS_ProdTempiTableAdapters.stp_repDonati_getLastStatoDurataMacchinaTableAdapter();
taDiarioDich = new DS_applicazioneTableAdapters.DiarioDichiarazioniTableAdapter();
taDOSS = new DS_DossParTableAdapters.DossiersTableAdapter();
taEventi = new DS_applicazioneTableAdapters.EventListTableAdapter();
taFL = new DS_applicazioneTableAdapters.FluxLogTableAdapter();
taIS_TrDati = new DS_IntServTableAdapters.TransitoDatiTableAdapter();
taIstK = new DS_IntServTableAdapters.IstanzeKITTableAdapter();
taKeepAlive = new DS_applicazioneTableAdapters.KeepAliveTableAdapter();
taListVal = new DS_UtilityTableAdapters.v_selListValTableAdapter();
taM2S = new DS_ProdTempiTableAdapters.Macchine2SlaveTableAdapter();
taMacchine = new DS_applicazioneTableAdapters.MacchineTableAdapter();
taMacParams = new DS_PlanTableAdapters.MachineParamsTableAdapter();
taMagELotti = new DS_MAGTableAdapters.ElencoLottiTableAdapter();
taMSE = new DS_ProdTempiTableAdapters.MappaStatoExplTableAdapter();
taODL = new DS_ProdTempiTableAdapters.ODLTableAdapter();
taOp = new DS_applicazioneTableAdapters.AnagraficaOperatoriTableAdapter();
taOp2ins = new DS_applicazioneTableAdapters.AnagraficaOperatori2insTableAdapter();
taPlanCalDisp = new DS_PlanTableAdapters.CalDispTableAdapter();
taPlanCalStop = new DS_PlanTableAdapters.CalStopTableAdapter();
taPlanRichieste = new DS_PlanTableAdapters.RichiesteTableAdapter();
taPODL = new DS_ProdTempiTableAdapters.PromesseODLTableAdapter();
taPostazioni = new DS_ProdTempiTableAdapters.PostazioniMapoTableAdapter();
taPromIn = new DS_PlanTableAdapters.PromesseINTableAdapter();
taPromOut = new DS_PlanTableAdapters.PromesseOUTTableAdapter();
taPzProd2conf = new DS_ProdTempiTableAdapters.stp_PzProd_getByMacchinaTableAdapter();
taRC = new DS_ProdTempiTableAdapters.RegistroControlliTableAdapter();
taRemReb = new DS_applicazioneTableAdapters.RemoteRebootLogTableAdapter();
taRS = new DS_ProdTempiTableAdapters.RegistroScartiTableAdapter();
taSelArt = new DS_UtilityTableAdapters.v_selArticoliTableAdapter();
taSelMacc = new DS_UtilityTableAdapters.v_selMacchineTableAdapter();
taSelOdlFree = new DS_UtilityTableAdapters.v_selODLTableAdapter();
taSigLog = new DS_applicazioneTableAdapters.SignalLogTableAdapter();
taSTA = new DS_SheetTechTableAdapters.ST_ActualTableAdapter();
taSTAR = new DS_SheetTechTableAdapters.ST_ActualRowTableAdapter();
taStati = new DS_applicazioneTableAdapters.DiarioDiBordoTableAdapter();
taStatoMacchine = new DS_applicazioneTableAdapters.StatoMacchineTableAdapter();
taStatoProd = new DS_ProdTempiTableAdapters.StatoProdTableAdapter();
taSTChk = new DS_SheetTechTableAdapters.ST_CheckTableAdapter();
taTempiCicloRilevati = new DS_ProdTempiTableAdapters.TempiCicloRilevatiTableAdapter();
taTempoByClass = new DS_ProdTempiTableAdapters.stp_TempoByIdxMaccPeriodClassTableAdapter();
taTKS = new DS_IntServTableAdapters.TKS_SearchTableAdapter();
taTranIngr = new DS_applicazioneTableAdapters.TransizioneIngressiTableAdapter();
taTurniMacc = new DS_ProdTempiTableAdapters.TurniMacchinaTableAdapter();
taWKS = new DS_IntServTableAdapters.WipSetupKitTableAdapter();
}
// cMemLayer.CRB("confRett");
/// <summary>
/// effettua setup dei connection strings da web.config delal singola applicazione
/// </summary>
protected virtual void setupConnectionStringBase()
{
string connectionString = cMemLayer.confReadString("MoonProConnectionString");
string connectionStringIS = cMemLayer.confReadString("MoonProConnectionStringIS");
string connectionStringArca = cMemLayer.confReadString("MoonProConnectionStringArca");
string connectionStringES3 = cMemLayer.confReadString("MoonProConnectionStringES3");
string connectionStringFluxData = cMemLayer.confReadString("MoonProConnectionStringFluxData");
string connectionStringMAG = cMemLayer.confReadString("MoonProConnectionStringMAG");
// connections del db
taAG.Connection.ConnectionString = connectionString;
taAlarmLog.Connection.ConnectionString = connectionString;
taAnagArt.Connection.ConnectionString = connectionString;
taAnagEventi.Connection.ConnectionString = connectionString;
taAnagStati.Connection.ConnectionString = connectionString;
taAnagTags.Connection.ConnectionString = connectionString;
taAs400.Connection.ConnectionString = connectionStringIS;
taArcaGiac.Connection.ConnectionString = connectionStringArca;
taDecNA.Connection.ConnectionString = connectionString;
taCalFF.Connection.ConnectionString = connectionString;
taConfig.Connection.ConnectionString = connectionString;
taComm.Connection.ConnectionString = connectionString;
taConfFlux.Connection.ConnectionString = connectionStringFluxData;
taDatiConf.Connection.ConnectionString = connectionString;
taDatiMacchine.Connection.ConnectionString = connectionString;
taDatiProd.Connection.ConnectionString = connectionString;
taDatiProdMacch.Connection.ConnectionString = connectionString;
taDatiProdMacchPer.Connection.ConnectionString = connectionString;
taDatiStatoMacch.Connection.ConnectionString = connectionString;
taDiarioDich.Connection.ConnectionString = connectionString;
taDOSS.Connection.ConnectionString = connectionStringFluxData;
taEventi.Connection.ConnectionString = connectionString;
taFL.Connection.ConnectionString = connectionStringFluxData;
taIS_TrDati.Connection.ConnectionString = connectionStringIS;
taIstK.Connection.ConnectionString = connectionStringIS;
taKeepAlive.Connection.ConnectionString = connectionString;
taListVal.Connection.ConnectionString = connectionString;
taM2S.Connection.ConnectionString = connectionString;
taMacchine.Connection.ConnectionString = connectionString;
taMacParams.Connection.ConnectionString = connectionStringES3;
taMagELotti.Connection.ConnectionString = connectionStringMAG;
taMSE.Connection.ConnectionString = connectionString;
taODL.Connection.ConnectionString = connectionString;
taOp.Connection.ConnectionString = connectionString;
taOp2ins.Connection.ConnectionString = connectionString;
taPlanCalDisp.Connection.ConnectionString = connectionStringES3;
taPlanCalStop.Connection.ConnectionString = connectionStringES3;
taPlanRichieste.Connection.ConnectionString = connectionStringES3;
taPODL.Connection.ConnectionString = connectionString;
taPostazioni.Connection.ConnectionString = connectionString;
taPromIn.Connection.ConnectionString = connectionStringES3;
taPromOut.Connection.ConnectionString = connectionStringES3;
taPzProd2conf.Connection.ConnectionString = connectionString;
taRC.Connection.ConnectionString = connectionString;
taRemReb.Connection.ConnectionString = connectionString;
taRS.Connection.ConnectionString = connectionString;
taSelArt.Connection.ConnectionString = connectionString;
taSelMacc.Connection.ConnectionString = connectionString;
taSelOdlFree.Connection.ConnectionString = connectionString;
taSigLog.Connection.ConnectionString = connectionString;
taSTA.Connection.ConnectionString = connectionString;
taSTAR.Connection.ConnectionString = connectionString;
taStati.Connection.ConnectionString = connectionString;
taStatoMacchine.Connection.ConnectionString = connectionString;
taStatoProd.Connection.ConnectionString = connectionString;
taSTChk.Connection.ConnectionString = connectionString;
taTempiCicloRilevati.Connection.ConnectionString = connectionString;
taTempoByClass.Connection.ConnectionString = connectionString;
taTKS.Connection.ConnectionString = connectionStringIS;
taTranIngr.Connection.ConnectionString = connectionString;
taTurniMacc.Connection.ConnectionString = connectionString;
taWKS.Connection.ConnectionString = connectionStringIS;
}
#endregion Protected Methods
#region Private Fields
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
/// <summary>
/// Connessione lazy a redis...
/// </summary>
private Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() =>
{
string RedisConn = cMemLayer.confReadString("RedisConnSPEC");
if (string.IsNullOrEmpty(RedisConn))
{
RedisConn = cMemLayer.confReadString("RedisConn");
}
if (string.IsNullOrEmpty(RedisConn))
{
RedisConn = "localhost,abortConnect=false,ssl=false";
}
return ConnectionMultiplexer.Connect(RedisConn);
});
/// <summary>
/// Connessione lazy a redis...
/// </summary>
private Lazy<ConnectionMultiplexer> lazyConnectionAdmin = new Lazy<ConnectionMultiplexer>(() =>
{
string RedisConnAdmin = cMemLayer.confReadString("RedisConnSPECAdmin");
if (string.IsNullOrEmpty(RedisConnAdmin))
{
RedisConnAdmin = cMemLayer.confReadString("RedisConnAdmin");
}
if (string.IsNullOrEmpty(RedisConnAdmin))
{
RedisConnAdmin = "localhost,abortConnect=false,ssl=false,allowAdmin=true";
}
return ConnectionMultiplexer.Connect(RedisConnAdmin);
});
#endregion Private Fields
#region Private Properties
private static memLayer cMemLayer { get; set; } = new memLayer();
#endregion Private Properties
#region Private Methods
private static T ConvertDataRowToGenericType<T>(DataRow row) where T : class, new()
{
Type entityType = typeof(T);
T objEntity = new T();
foreach (DataColumn column in row.Table.Columns)
{
object value = row[column.ColumnName];
if (value == DBNull.Value) value = null;
PropertyInfo property = entityType.GetProperty(column.ColumnName, BindingFlags.Instance | BindingFlags.IgnoreCase | BindingFlags.Public);
try
{
if (property != null && property.CanWrite)
property.SetValue(objEntity, value, null);
}
catch (Exception ex)
{
throw ex;
}
}
return objEntity;
}
/// <summary>
/// registra su REDIS eventuale superamento numero limite di call x il metodo in oggetto
/// </summary>
/// <param name="callCountKey"></param>
private static void saveCallRec(string callCountKey)
{
// conto la richiesta nel contatore REDIS
long nCall = cMemLayer.setRCntI(mHash($"COUNT:pCall:{callCountKey}"));
//... se == nCall2Log scrivo su log e resetto
long nCall2Log = cMemLayer.cdvi("nCall2Log");
if (nCall >= nCall2Log)
{
// loggo
Log.Info($"{callCountKey}: {nCall} call received", tipoLog.INFO);
// resetto!
cMemLayer.resetRCnt(mHash($"COUNT:pCall:{callCountKey}"));
}
}
/// <summary>
/// verifica se sia necessario inserire un cambio di stato impianto in modalità batch
/// </summary>
/// <param name="tipoInput"></param>
/// <param name="IdxMacchina"></param>
/// <param name="InizioStato"></param>
/// <param name="IdxTipo"></param>
/// <param name="CodArt"></param>
/// <param name="Value"></param>
/// <param name="MatrOpr"></param>
/// <param name="pallet"></param>
private void checkCambiaStatoBatch(tipoInputEvento tipoInput, string IdxMacchina, DateTime InizioStato, int IdxTipo, string CodArt, string Value, int MatrOpr, string pallet)
{
int _logLevel = cMemLayer.CRI("_logLevel");
DS_applicazione.TransizioneStatiDataTable tabTransStati;
DS_applicazione.TransizioneStatiRow rigaTransStati;
switch (tipoInput)
{
case tipoInputEvento.barcode:
// effettuo cambio stato INDIPENDENTEMENTE da stato precedente
try
{
tabTransStati = MapoDbObj.taTranSt.GetUserForcedTransitions(IdxMacchina, IdxTipo);
if (tabTransStati != null)
{
if (tabTransStati.Count > 0)
{
rigaTransStati = tabTransStati[0];
// solo se cambia stato...
if (rigaTransStati.IdxStato != rigaTransStati.next_IdxStato)
{
MapoDbObj.taDiario.InsStatoBatch(IdxMacchina, InizioStato, rigaTransStati.next_IdxStato, CodArt, Value, MatrOpr, pallet);
// aggiorno MSE
taMSE.forceRecalc(0, IdxMacchina);
}
}
else
{
if (_logLevel > 6)
{
Log.Info($"Non trovata riga per: BARCODE | IdxMacchina: {IdxMacchina} | IdxTipo: {IdxTipo} | CodArt: {CodArt} | Value: {Value} | MatrOpr: {MatrOpr} | pallet: {pallet}", tipoLog.INFO);
}
}
}
}
catch (Exception exc)
{
// non dovrebbe succedere... input utente da barcode dovrebbero TUTTI essere
// inseriti in tab transizione con famiglia 1...
Log.Info($"Errore controllo transizione stato x evento barcode: BARCODE | IdxMacchina: {IdxMacchina} | IdxTipo: {IdxTipo} | CodArt: {CodArt} | Value: {Value} | MatrOpr: {MatrOpr} | pallet: {pallet}{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
break;
case tipoInputEvento.hw:
// verifico se ci sia necessità di cambio stato
try
{
tabTransStati = MapoDbObj.taTranSt.GetHwTransitions(IdxMacchina, IdxTipo);
if (tabTransStati != null)
{
if (tabTransStati.Count > 0)
{
rigaTransStati = tabTransStati[0];
if (rigaTransStati != null)
{
// solo se cambia stato...
if (rigaTransStati.IdxStato != rigaTransStati.next_IdxStato)
{
MapoDbObj.taDiario.InsStatoBatch(IdxMacchina, InizioStato, rigaTransStati.next_IdxStato, CodArt, Value, MatrOpr, pallet);
}
}
}
else
{
if (_logLevel > 6)
{
Log.Info($"Non trovata riga per: HW | IdxMacchina: {IdxMacchina} | IdxTipo: {IdxTipo} | CodArt: {CodArt} | Value: {Value} | MatrOpr: {MatrOpr} | pallet: {pallet}", tipoLog.INFO);
}
}
}
}
catch (Exception exc)
{
// non trovo riga [0]... NON scrivo!
Log.Info($"Errore controllo transizione stato x evento barcode: HW | IdxMacchina: {IdxMacchina} | IdxTipo: {IdxTipo} | CodArt: {CodArt} | Value: {Value} | MatrOpr: {MatrOpr} | pallet: {pallet}{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
break;
}
}
private bool doCloseCurrODL(string idxMacchina, bool doConfirm, int qtyConf, DS_ProdTempi.ODLDataTable currODLData, DateTime dtEvento, int matrOpr)
{
DateTime adesso = DateTime.Now;
bool fatto = false;
// registro un evento di attrezzaggio (idxTipoEv = 2) PRIMA di chiudere ODL
int idxEvento = 2;
Log.Info($"Invio evento attrezzaggio x CHIUSURA ODL | idxMacc {idxMacchina} | idxEv {idxEvento} | CodArt {currODLData[0].CodArticolo} | qtyConf {qtyConf}", tipoLog.INFO);
// invio un evento x messa in manuale macchina x attrezzaggio in chiusura
inputComandoMapo resCmd = scriviRigaEventoBarcode(idxMacchina, idxEvento, currODLData[0].CodArticolo, "ODL-CLOSE-ATTR", 0, "", dtEvento, adesso);
if (doConfirm)
{
// modifico la dataEvento
dtEvento.AddMilliseconds(200);
// chiamo conferma produzione...
try
{
string chiamata = confRett ? "confermaProdMacchinaFull" : "confermaProdMacchina";
Log.Info($"Chiamata a {chiamata} con parametri | IdxMacchina: {currODLData[0].IdxMacchina} | MatrOpr: {MatrOpr} | dtEvent {dtEvento} | {qtyConf} | modoConf: {cMemLayer.CRI("modoConfProd")}", tipoLog.INFO);
string idxMacchinaSel = currODLData[0].IdxMacchina;
if (confRett)
{
// confermo al netto dei pezzi lasciati...
fatto = confermaProdMacchinaFull(idxMacchinaSel, cMemLayer.CRI("modoConfProd"), qtyConf, 0, 0, dtEvento, matrOpr);
}
else
{
fatto = confermaProdMacchina(idxMacchinaSel, cMemLayer.CRI("modoConfProd"), qtyConf, 0, dtEvento, matrOpr);
}
if (!fatto)
{
Log.Info($"ERRORE in chiamata {chiamata}", tipoLog.ERROR);
}
}
catch (Exception exc)
{
Log.Info($"Eccezione in doCloseCurrODL{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
}
dtEvento.AddMilliseconds(200);
// chiamo chiusura
MapoDbObj.taODL.forceClose(currODLData[0].IdxODL, idxMacchina, dtEvento);
// elimino eventuale ODL precedente...
string rKey = cMemLayer.redHash($"ODL:{idxMacchina}");
cMemLayer.setRSV(rKey, "");
fatto = true;
return fatto;
}
/// <summary>
/// sistemazione timeout comandi nei tableadapter
/// </summary>
private void fixCommandTimeout()
{
int sqlLongCommandTimeout = cMemLayer.CRI("sqlLongCommandTimeout") > 1 ? cMemLayer.CRI("sqlLongCommandTimeout") : 300;
SetAllCommandTimeouts(taComm, sqlLongCommandTimeout);
}
/// <summary>
/// Recupero dati stato prod da macchina...
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="datiProdAct"></param>
/// <param name="dataRif"></param>
/// <returns></returns>
private bool getStatoProd(string idxMacchina, ref DS_ProdTempi.StatoProdDataTable datiProdAct, DateTime dataRif)
{
bool answ = false;
try
{
// recupero con stored NUOVA...
//2020.01.31 NUOVO oggetto (NON singleton)
DataLayer man = new DataLayer();
datiProdAct = man.taStatoProd.GetData(idxMacchina, dataRif);
if (datiProdAct.Rows.Count > 0)
{
// solo SE ho idxODL (altrimenti loggo errore)
if (datiProdAct[0].IdxOdl > 0)
{
answ = true;
}
else
{
// verifico se ho già questo errore attivo IN REDIS (altrimenti reinvio)
Log.Info($"pzCounterTC: Non trovato currODL x idxMacchina {idxMacchina} ", $"idxMacchina {idxMacchina} | IdxOdl {datiProdAct[0].IdxOdl} | pzTot {datiProdAct[0].PzTotODL} | dataRif {dataRif}", tipoLog.WARNING);
}
}
else
{
Log.Info($"pzCounterTC: Non trovate righe in currODL {idxMacchina}", $"Non trovate righe in currODL x idxMacchina {idxMacchina}: datiProdAct vuota", tipoLog.WARNING);
}
}
catch (Exception exc)
{
Log.Info($"[pzCounterTC] Eccezione in pzCounterTC x idxMacchina {idxMacchina}", $"[pzCounterTC] Eccezione in pzCounterTC x idxMacchina {idxMacchina}{Environment.NewLine}{exc}", tipoLog.EXCEPTION);
}
return answ;
}
/// <summary>
/// Calcola l'effettivo valore da passare alla macchina a stati INGRESSI data conf Macchine2FamigliaIngressi
/// </summary>
/// <param name="idxMacchina"></param>
/// <param name="valore"></param>
/// <returns></returns>
private string preProcInput(string idxMacchina, string valore)
{
string newVal = "";
try
{
// variabili
int valINT = 0;
int BitFilt = 0;
int BSR = 0;
bool ExplodeBit = false;
int NumBit = 0;
int newValInt = 0;
// recupero parametri...
int.TryParse(mDatiMacchinaVal(idxMacchina, "BitFilt"), out BitFilt);
int.TryParse(mDatiMacchinaVal(idxMacchina, "BSR"), out BSR);
Boolean.TryParse(mDatiMacchinaVal(idxMacchina, "ExplodeBit"), out ExplodeBit);
int.TryParse(mDatiMacchinaVal(idxMacchina, "NumBit"), out NumBit); // non usato (x ora)
// recupero valore
valINT = int.Parse(valore, NumberStyles.HexNumber);
// filtro
newValInt = utility.bMaskInt(valINT, BitFilt);
// effettuo eventuale BitShiftRight
if (BSR > 0)
{
newValInt = newValInt >> BSR;
}
// effettuo eventuale esplosione in BIT esclusivi
if (ExplodeBit)
{
newValInt = Convert.ToInt32(1 << newValInt);
}
// riconverto a STRING HEX!!!
newVal = newValInt.ToString("X");
}
catch
{
newVal = valore;
}
return newVal;
}
/// <summary>
/// Reset cache REDIS dati PODL
/// </summary>
/// <exception cref="NotImplementedException"></exception>
private void resetPODLData(int idxPODL)
{
string rKey = getPOdlRowHash(idxPODL);
cMemLayer.setRSV(rKey, "", 1);
}
private string saveOdlData(string idxMacchina, DS_ProdTempi.ODLDataTable currODLData, DS_ProdTempi.PromesseODLDataTable reqPODLData)
{
string answ;
// recupera ODL macchina
var newOdl = currODL(idxMacchina, true);
// attendo 1000 msec registro fine ODL (idxTipoEv = 1)
int idxEvento = 1;
Log.Info($"Invio evento ODL-forced start per macchina {idxMacchina}, evento {idxEvento}, articolo {currODLData[0].CodArticolo}", tipoLog.INFO);
var resCmd = scriviRigaEventoBarcode(idxMacchina, idxEvento, currODLData[0].CodArticolo, "ODL-FORCE-START");
// invio eventi setup a macchina....
string setArtVal = $"{currODLData[0].CodArticolo}";
string setPzCommVal = $"{reqPODLData[0].NumPezzi}";
string setCommVal = $"ODL{newOdl}";
if (!string.IsNullOrEmpty(reqPODLData[0].KeyRichiesta))
{
setCommVal = $"{reqPODLData[0].KeyRichiesta} ODL{newOdl}";
}
try
{
// invio task caricamento dati ODL
addTask4Machine(idxMacchina, taskType.setArt, setArtVal);
addTask4Machine(idxMacchina, taskType.setComm, setCommVal);
addTask4Machine(idxMacchina, taskType.setPzComm, setPzCommVal);
updateMachineParameter(idxMacchina, "setArt", setArtVal);
updateMachineParameter(idxMacchina, "setComm", setCommVal);
updateMachineParameter(idxMacchina, "setPzComm", setPzCommVal);
}
catch
{ }
// chiamo refresh MSE
taMSE.forceRecalc(0, idxMacchina);
// resetto stato macchina...
cMemLayer.redDelKey(currStatoMaccHash(idxMacchina));
answ = "OK";
Log.Info($"Effettuato reset e ricalcoli x split ODL per macchina {idxMacchina}", tipoLog.INFO);
// se è una master richiamo fix x child...
if (isMaster(idxMacchina))
{
string ts = "";
string outData = "";
taODL.fixMachineSlave(idxMacchina, 30, 1);
// ciclo su ogni slave la gestione reinvio pezzi -->calcolo gli slave...
var slaveList = taM2S.getByMaster(idxMacchina);
foreach (var machine in slaveList)
{
// invio chiusura attrezzaggio
ts = string.Format("{0:yyMMdd}T{0:HHmmss.fff}Z", DateTime.Now);
outData = $"TS:{ts}|MATR:{MatrOpr}|ODL:{newOdl}";
addTask4Machine(machine.IdxMacchinaSlave, taskType.fixStopSetup, outData);
// invio task caricamento dati ODL
addTask4Machine(machine.IdxMacchinaSlave, taskType.setArt, setArtVal);
addTask4Machine(machine.IdxMacchinaSlave, taskType.setComm, setCommVal);
addTask4Machine(machine.IdxMacchinaSlave, taskType.setPzComm, setPzCommVal);
updateMachineParameter(machine.IdxMacchinaSlave, "setArt", setArtVal);
updateMachineParameter(machine.IdxMacchinaSlave, "setComm", setCommVal);
updateMachineParameter(machine.IdxMacchinaSlave, "setPzComm", setPzCommVal);
}
}
return answ;
}
private void SetAllCommandTimeouts(object adapter, int timeout)
{
var commands = adapter.GetType().InvokeMember(
"CommandCollection",
BindingFlags.GetProperty | BindingFlags.Instance | BindingFlags.NonPublic,
null, adapter, new object[0]);
var sqlCommand = (SqlCommand[])commands;
foreach (var cmd in sqlCommand)
{
cmd.CommandTimeout = timeout;
}
}
private void setupConf()
{
confRett = cMemLayer.CRB("confRett");
}
/// <summary>
/// cerca codice in anagrafica macchine ed eventualmente inserisce nuova macchina
/// </summary>
/// <param name="IdxMacchina"></param>
private void verificaIdxMacchina(string IdxMacchina)
{
bool needDB = false;
if (!cMemLayer.CRB("disable_verificaIdxMacchina"))
{
if (cMemLayer.CRB("IOB_RedEnab"))
{
try
{
// esecuzione in REDIS...cerco status macchina...
if (mDatiMacchine(IdxMacchina).Count == 0)
{
needDB = true;
}
}
catch { }
}
// ...oppure segno richiesta DB...
else
{
needDB = true;
}
if (needDB)
{
// 2017.07.11 se richiesto di NON usare singleton... riporto FUORI la gestione
// NUOVO oggetto
if (cMemLayer.CRB("disable_singleton"))
{
taMacchine = new DS_applicazioneTableAdapters.MacchineTableAdapter();
MapoDbObj.taMSM = new DS_applicazioneTableAdapters.MicroStatoMacchinaTableAdapter();
}
// verifico esistenza macchina
if (taMacchine.GetByIdx(IdxMacchina).Rows.Count == 0)
{
// inserisco nuova macchina...
taMacchine.Insert(IdxMacchina, "9999", IdxMacchina, "Macchina non codificata", "-", "http://", "nd", "col", 0, 0);
}
// verifico ci sia un microstato macchina...
if (MapoDbObj.taMSM.getByIdxMacchina(IdxMacchina).Rows.Count == 0)
{
// inserisco nuovo stato...
MapoDbObj.taMSM.Insert(IdxMacchina, 0, DateTime.Now, "00");
}
}
}
}
#endregion Private Methods
}
}