using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using System.Configuration; using System.Text; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Logging; using GWMS.Data; using Microsoft.Extensions.Caching.Distributed; using Microsoft.Extensions.Caching.Memory; using Newtonsoft.Json; using System.Diagnostics; using NLog; using GWMS.Data.DTO; using GWMS.Data.DatabaseModels; using static GWMS.Data.IobObjects; using System.Globalization; using Microsoft.AspNetCore.Identity.UI.Services; using Microsoft.AspNetCore.Identity; namespace GWMS.UI.Data { public class GWMSDataService : IDisposable { #region Private Fields private static IConfiguration _configuration; private static ILogger _logger; private static NLog.Logger Log = LogManager.GetCurrentClassLogger(); private readonly IEmailSender _emailSender; private readonly UserManager _userManager; private readonly IDistributedCache distributedCache; private readonly IMemoryCache memoryCache; /// /// Durata assoluta massima della cache IN SECONDI /// private int chAbsExp = 60 * 5; /// /// Durata della cache IN SECONDI in modalità inattiva (non acceduta) prima di venire rimossa /// NON estende oltre il tempo massimo di validità della cache (chAbsExp) /// private int chSliExp = 60 * 1; #endregion Private Fields #region Protected Fields protected static string connStringBBM = ""; #endregion Protected Fields #region Public Fields public static GWMS.Data.Controllers.GWMSController dbController; #endregion Public Fields #region Public Constructors public GWMSDataService(IConfiguration configuration, ILogger logger, IMemoryCache memoryCache, IDistributedCache distributedCache, IEmailSender emailSender, UserManager userManager) { _logger = logger; _configuration = configuration; _emailSender = emailSender; _userManager = userManager; // conf cache this.memoryCache = memoryCache; this.distributedCache = distributedCache; // conf DB string connStr = _configuration.GetConnectionString("GWMS.Data"); if (string.IsNullOrEmpty(connStr)) { _logger.LogError("ConnString empty!"); } else { dbController = new GWMS.Data.Controllers.GWMSController(configuration); } } #endregion Public Constructors #region Private Methods private DistributedCacheEntryOptions cacheOpt(bool fastCache) { var numSecAbsExp = fastCache ? chAbsExp : chAbsExp * 10; var numSecSliExp = fastCache ? chSliExp : chSliExp * 10; return new DistributedCacheEntryOptions().SetAbsoluteExpiration(DateTime.Now.AddSeconds(numSecAbsExp)).SetSlidingExpiration(TimeSpan.FromSeconds(numSecSliExp)); } /// /// Recupera PlantDTO e aggiorno valori attuali (se presente...) /// ATTENZIONE: i dati sono sempre ricevuti PER SINGOLO PlantId!!! /// /// private async Task updateCurrDTO(List newItems) { DateTime adesso = DateTime.Now; List dbResult = new List(); int PlantId = newItems.FirstOrDefault().PlantId; string cacheKey = "DATA:PLANTS:ListDTO"; string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); // ora ciclo x ogni flusso/macchina l'ultimo record List lastByFlux = newItems .OrderByDescending(x => x.DtEvent) .GroupBy(g => g.FluxType) .Select(s => s.First()) .ToList(); // aggiorno il DTO x i valori trovati... var currDto = dbResult.Where(x => x.PlantId == PlantId).FirstOrDefault(); // verifico SE c'è Level var lastLev = lastByFlux.Where(x => x.FluxType == "Level").FirstOrDefault(); if (lastLev != null) { currDto.LevelAct = lastLev.ValNumber; currDto.LastUpdate = adesso; } // verifico SE c'è MainPress var lastMain = lastByFlux.Where(x => x.FluxType == "MainPress").FirstOrDefault(); if (lastMain != null) { if (currDto.PressAct.ContainsKey("Main")) { currDto.PressAct["Main"] = lastMain.ValNumber; } else { currDto.PressAct.Add("Main", lastMain.ValNumber); } } // verifico SE c'è PressBH var lastBH = lastByFlux.Where(x => x.FluxType == "PressBH").FirstOrDefault(); if (lastBH != null) { if (currDto.PressAct.ContainsKey("BH")) { currDto.PressAct["BH"] = lastBH.ValNumber; } else { currDto.PressAct.Add("BH", lastBH.ValNumber); } } // verifico SE c'è PressBL var lastBL = lastByFlux.Where(x => x.FluxType == "PressBL").FirstOrDefault(); if (lastBL != null) { if (currDto.PressAct.ContainsKey("BL")) { currDto.PressAct["BL"] = lastBL.ValNumber; } else { currDto.PressAct.Add("BL", lastBL.ValNumber); } } // salvo DTO! rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(true)); } } #endregion Private Methods #region Protected Methods /// /// Hash dati EXE TASK x la macchina specificata /// /// /// protected static string exeTaskHash(string idxMacchina) { return mHash(string.Format("ExeTask:{0}", idxMacchina)); } /// /// FUnzione verifica eventuale creazione NUOVI ordini di consegna /// /// protected async Task checkCreateOrders() { bool fatto = false; List NewOrders = new List(); DateTime adesso = DateTime.Now; int supplierId = 1; int transporterId = 1; double qtyOrd = 0; // faccio ciclo x tutti gli impianti List currPlantData = await PlantsGetAll(); List fullWeekPlan = WeekPlanGet().Result; foreach (var item in currPlantData) { // recupero ordini x il plant var currOrderOpen = await OrdersGetOpen(item.PlantId); // calcolo delta ordinato qtyOrd = currOrderOpen.Sum(x => x.OrderQty); // verifico il livello attuale + i valori degli ordini APERTI rispetto al livello di riordino... if (item.LevelAct + qtyOrd < item.LevelReorder) { // (FARE !!! VERIFICA!!!!) // calcolo supplier/transporter da tab WeekPlan var dailyPlan = fullWeekPlan.Where(x => x.PlantId == item.PlantId && (int)x.DayNum == ((int)adesso.DayOfWeek + 1)).FirstOrDefault(); if (dailyPlan != null) { supplierId = dailyPlan.SupplierId; transporterId = dailyPlan.TransporterId; } else { supplierId = 1; transporterId = 1; } // stacco un NUOVO ordine di quantità finita NewOrders.Add(new OrderModel() { DtOrder = adesso, DtETA = adesso.AddDays(1), OrderQty = item.OrderQtyStd, PlantId = item.PlantId, OrderCode = $"O{item.PlantCode}{adesso:yyMMddHHmm}", OrderDesc = $"Ordine {item.PlantDesc} - {adesso}", SupplierId = supplierId, TransporterId = transporterId }); } } if (NewOrders.Count > 0) { // effettuo inserimento ordini! dbController.OrderInsert(NewOrders); // recupero elenco users associati al FORNITORE.... var rawUserList = UserDataGetFilt("").Result; var supplList = rawUserList .Where(x => x.Roles.Contains("ExtUser")) .ToList(); var transpList = rawUserList .Where(x => x.Roles.Contains("ExtTransp")) .ToList(); // recupero NUOVI ordini x plant... foreach (var plant in currPlantData) { var newOrderOpen = await OrdersGetOpen(plant.PlantId); string emailDest = ""; string emailSubj = ""; string emailBody = ""; StringBuilder sb = new StringBuilder(); // invio email x ogni fornitore / trasportatore x i NUOVI ordini inseriti foreach (var item in newOrderOpen) { // FORNITORI! emailSubj = $"GWMS: Ordine FORNITURA GAS per {item.Plant.PlantDesc}"; sb = new StringBuilder(); sb.AppendLine($"

Fornitore {item.Supplier.SupplierDesc}

"); sb.AppendLine($"Trasportatore {item.Transporter.TransporterDesc}"); sb.AppendLine($"Impianto di destinazione {item.Plant.PlantDesc}"); sb.AppendLine(""); sb.AppendLine($"Ordine di consegna: {item.OrderCode}"); sb.AppendLine($"Data ordine: {item.DtOrder}"); sb.AppendLine($"Data consegna indicativa: {item.DtETA}"); sb.AppendLine($"Quantità ordinata: {item.OrderQty}"); emailBody = sb.ToString().Replace(Environment.NewLine, "
"); System.Security.Claims.Claim suppClaim = new System.Security.Claims.Claim("SupplierId", $"{item.SupplierId}"); // recupero elenco users associati al FORNITORE.... var userListSupp = supplList .Where(x => x.Claims.Where(c => c.Type == "SupplierId" && c.Value == $"{item.SupplierId}").Count() > 0) .ToList(); foreach (var user in userListSupp) { // invio email di notifica nuovi ordini inseriti emailDest = user.Identity.Email; //emailDest = user.Email; // invio! await _emailSender.SendEmailAsync(emailDest, emailSubj, emailBody); _logger.LogInformation($"Email sento to SUPPLIER {emailDest}!"); } // TRASPORTATORI! emailSubj = $"GWMS: Ordine TRASPORTO GAS per {item.Plant.PlantDesc}"; sb = new StringBuilder(); sb.AppendLine($"

Trasportatore {item.Transporter.TransporterDesc}

"); sb.AppendLine($"Fornitore {item.Supplier.SupplierDesc}"); sb.AppendLine($"Impianto di destinazione {item.Plant.PlantDesc}"); sb.AppendLine(""); sb.AppendLine($"Ordine di consegna: {item.OrderCode}"); sb.AppendLine($"Data ordine: {item.DtOrder}"); sb.AppendLine($"Data consegna indicativa: {item.DtETA}"); sb.AppendLine($"Quantità ordinata: {item.OrderQty}"); sb.AppendLine(""); sb.AppendLine($"Note: {item.OrderDesc}"); emailBody = sb.ToString().Replace(Environment.NewLine, "
"); // recupero elenco users associati al TRASPORTATORE.... var userListTransp = transpList .Where(x => x.Claims.Where(c => c.Type == "TransporterId" && c.Value == $"{item.TransporterId}").Count() > 0) .ToList(); foreach (var user in userListTransp) { // invio email di notifica nuovi ordini inseriti emailDest = user.Identity.Email; //emailDest = user.Email; // invio! await _emailSender.SendEmailAsync(emailDest, emailSubj, emailBody); _logger.LogInformation($"Email sento to TRANSPORTER {emailDest}!"); } } } fatto = true; } return fatto; } protected string getCacheKey(string TableName, SelectOrderData CurrFilter) { string answ = $"{TableName}:P_{CurrFilter.PlantId:00}:S_{CurrFilter.SupplierId:00}:T_{CurrFilter.TransporterId:00}:D_{CurrFilter.DateStart:yyyyMMddHHmm}_{CurrFilter.DateEnd:yyyyMMddHHmm}"; return answ; } protected async Task> PlantLogGetLastByFlux(int PlantId) { List lastValues = new List(); // cerco in cache string cacheKey = $"DATA:PLANTS:LastFlux:{PlantId}"; string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); lastValues = JsonConvert.DeserializeObject>(rawData); } // altrimenti DB e salvo... else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); lastValues = dbController.PlantLogGetLastByFlux(PlantId); rawData = JsonConvert.SerializeObject(lastValues); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(true)); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB + caching per PlantLogGetLastByFlux: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(lastValues); } #endregion Protected Methods #region Public Methods /// /// Hash dati MemoryMap x la macchina specificata /// /// /// public static string currMamMapHash(string idxMacchina) { return mHash(string.Format("MemMap:{0}", idxMacchina)); } /// /// Hash dati CurrentParameters x la macchina specificata /// /// /// public static string currParametersHash(string idxMacchina) { return mHash(string.Format("CurrentParameters:{0}", idxMacchina)); } /// /// Hash Redis contenente i dati MP di una specifico TYPE (es StatusMacchina, StateMachineIngressi, ...) /// /// /// public static string mHash(string dataType) { return $"DATA:{dataType}"; } /// /// Hash dati OPT PARAMETERS x la macchina specificata /// /// /// public static string optParHash(string idxMacchina) { return mHash(string.Format("OptPar:{0}", idxMacchina)); } /// /// Hash dati SAVED (EXE) TASK x la macchina specificata x poter ripristinare in caso di perdita valore WRITE /// /// /// public static string savedTaskHash(string idxMacchina) { return mHash(string.Format("SavedTask:{0}", idxMacchina)); } /// /// verifica se sia da reinviare un task alla macchina dall'elenco di quelli salvati (in modalità upsert) se non scaduti /// /// /// /// /// public async Task 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 savedTask = await 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 currTasks = await mTaskMacchina(idxMacchina); // rimetto in task da eseguire... currTasks[taskKey.ToString()] = savedVal; // salvo in redis! string rawData = JsonConvert.SerializeObject(currTasks); await distributedCache.SetAsync(currHash, Encoding.UTF8.GetBytes(rawData)); Log.Info($"Re-issued task4machine | idxMacchina: {idxMacchina} | taskKey: {taskKey} | savedVal: {savedVal}"); } } catch (Exception exc) { Log.Error($"Errore in addCheckTask4Machine | idxMacchina: {idxMacchina} | taskKey: {taskKey} | taskVal: {taskVal}{Environment.NewLine}{exc}"); } return answ; } /// /// Aggiunge un task all'elenco di quelli salvati (in modalità upsert) /// /// /// /// /// public async Task addTask4Machine(string idxMacchina, taskType taskKey, string taskVal) { bool answ = false; string rawData = ""; string currHash = exeTaskHash(idxMacchina); string currSavedParHash = savedTaskHash(idxMacchina); Dictionary currTasks = new Dictionary(); Dictionary savedTask = new Dictionary(); try { Log.Info($"Request: idxMacchina: {idxMacchina} | taskKey: {taskKey} | taskVal: {taskVal}"); // leggo task attuali... currTasks = await mTaskMacchina(idxMacchina); if (currTasks.ContainsKey($"{taskKey}")) { currTasks[$"{taskKey}"] = taskVal; } else { currTasks.Add($"{taskKey}", taskVal); } // salvo in redis! rawData = JsonConvert.SerializeObject(currTasks); await distributedCache.SetAsync(currHash, Encoding.UTF8.GetBytes(rawData)); Log.Info($"Task ADD | idxMacchina: {idxMacchina} | taskKey: {taskKey} | taskVal: {taskVal}"); } catch (Exception exc) { Log.Error($"Errore in remTask4Machine | idxMacchina: {idxMacchina} | taskKey: {taskKey} | taskVal: {taskVal}{Environment.NewLine}{exc}"); } // 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 = await mSavedTaskMacchina(idxMacchina); savedTask[$"{taskKey}"] = taskVal; // salvo in redis! rawData = JsonConvert.SerializeObject(savedTask); await distributedCache.SetAsync(currSavedParHash, Encoding.UTF8.GetBytes(rawData)); break; case taskType.endProd: // salvo un DICT vuoto x resettare savedTask = new Dictionary(); // salvo in redis! rawData = JsonConvert.SerializeObject(savedTask); await distributedCache.SetAsync(currSavedParHash, Encoding.UTF8.GetBytes(rawData)); break; default: break; } return answ; } public async Task> AlarmLogGetFilt(int PlantId, int skipRec, int numRec) { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); var dbResult = dbController.AlarmLogGetFilt(PlantId, skipRec, numRec); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB AlarmLogGetFilt: {ts.TotalMilliseconds} ms"); return await Task.FromResult(dbResult); } public async Task AlarmLogInsert(AlarmLogModel newItem) { bool fatto = await dbController.AlarmLogInsert(newItem); DateTime adesso = DateTime.Now; // se registrato --> invio email if (fatto) { // Gestori! string emailDest = ""; string emailSubj = ""; string emailBody = ""; StringBuilder sb = new StringBuilder(); List allPlants = await PlantsGetAll(); var currPlant = allPlants.Where(x => x.PlantId == newItem.PlantId).FirstOrDefault(); // inizio a comporre email emailSubj = $"GWMS: warning/allarme registrato per impianto {currPlant.PlantDesc}"; sb.AppendLine($"Impianto interessato: {currPlant.PlantDesc}"); sb.AppendLine(""); if (newItem.Status > 0) { sb.AppendLine($"Allarme rilevato in area {newItem.MemAddress}/{newItem.Index} alle {adesso:yyyy.MM.dd HH:mm:ss}"); sb.AppendLine($"{newItem.ValDecoded}"); } else { sb.AppendLine($"Allarme cessato per {newItem.MemAddress}/{newItem.Index} alle {adesso:yyyy.MM.dd HH:mm:ss}"); } emailBody = sb.ToString().Replace(Environment.NewLine, "
"); System.Security.Claims.Claim suppClaim = new System.Security.Claims.Claim("PlantId", $"{newItem.PlantId}"); // recupero elenco users associati al PLANT.... var rawUserList = UserDataGetFilt("").Result; var plantUserList = rawUserList .Where(x => x.Roles.Contains("User")) .ToList(); //var plantList = await PlantsGetAll(); var userListSupp = plantUserList .Where(x => x.Claims.Where(c => c.Type == "PlantId" && c.Value == $"{newItem.PlantId}").Count() > 0) .ToList(); foreach (var user in userListSupp) { // invio email di notifica nuovi ordini inseriti emailDest = user.Identity.Email; //emailDest = user.Email; // invio! await _emailSender.SendEmailAsync(emailDest, emailSubj, emailBody); _logger.LogInformation($"Email sento to PLANT USER {emailDest}!"); } } return fatto; } /// /// effettua verifica x tutti i plant, se livello > livello riordino e NON ci sono ordini APERTI in arrivo --> lancia ordine /// public async Task checkLevels() { bool fatto = false; // effettuo verifica veto ricalcolo ordini da cache... DateTime adesso = DateTime.Now; DateTime vetoCheck = adesso.AddMinutes(1); string cacheKey = "DATA:CHECKLEVEL"; string rawData; try { var redisDataList = await distributedCache.GetAsync(cacheKey); // se non ho veto --> controllo if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); vetoCheck = JsonConvert.DeserializeObject(rawData); } else { vetoCheck = adesso.AddMinutes(-1); } if (adesso > vetoCheck) { fatto = await checkCreateOrders(); // imposto nuovo veto a 5 min... vetoCheck = adesso.AddMinutes(5); rawData = JsonConvert.SerializeObject(vetoCheck); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(false)); } } catch { } return fatto; } public async Task> ConfigGetAll() { //return Task.FromResult(dbController.ActionsGetAll()); List dbResult = new List(); string cacheKey = "DATA:CONFIG"; string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.GetConfig(); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(false)); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB + caching per ConfigGetAll: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } public PlantLogModel convertFluxToPL(int plantId, flogData origData) { // cerco di ottenere un val in cifre double valDbl = 0; NumberStyles style = NumberStyles.Number; CultureInfo culture = CultureInfo.CreateSpecificCulture("it-IT"); string valString = origData.valore; // verifico SE contiene o meno la ","... if (valString.IndexOf(',') > 0 && valString.IndexOf('.') > 0) { valString = origData.valore.Replace(".", ""); } else if (valString.IndexOf(',') < 0) { valString = origData.valore.Replace(".", ","); } double.TryParse(valString, style, culture, out valDbl); TimeSpan delta = origData.dtCurr.Subtract(origData.dtEve); PlantLogModel answ = new PlantLogModel() { FluxType = origData.flux, ValNumber = valDbl, ValString = origData.valore, PlantId = plantId, DtEvent = DateTime.Now.Subtract(delta) }; return answ; } public async Task DbForceMigrate() { return await Task.FromResult(dbController.DbForceMigrate()); } public void Dispose() { // Clear database controller dbController.Dispose(); } /// /// Restitusice elenco PARAMETRI (da passare a IOB-WIN) per l'impianto indicato /// /// Impianto richiesto /// public async Task> getCurrObjItems(string idxMacchina) { List answ = new List(); List outList = new List(); // ORA recupero da memoria redis... try { string cacheKey = currParametersHash(idxMacchina); string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); answ = JsonConvert.DeserializeObject>(rawData); // ordino! outList = answ .OrderByDescending(x => x.writable) .ThenBy(x => x.name) .ToList(); } } catch (Exception exc) { Log.Info($"Errore in recupero ParametriMacchinaGet | idxMacchina {idxMacchina}{Environment.NewLine}{exc}"); } return outList; } /// /// Restitusice elenco PARAMETRI che richiedono una WRITE x IOB /// /// Impianto richiesto /// public async Task> getCurrObjItemsPendigWrite(string idxMacchina) { List actValues = new List(); List writeValues = new List(); // ORA recupero da memoria redis... try { string cacheKey = currParametersHash(idxMacchina); string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); actValues = JsonConvert.DeserializeObject>(rawData); // 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($"Errore in recupero ParametriMacchinaWriteGet | idxMacchina {idxMacchina}{Environment.NewLine}{exc}"); } return writeValues; } public async Task HasPlantLog() { return await Task.FromResult(dbController.HasPlantLog()); } /// /// invalida tutta la cache in caso di update /// /// public async Task InvalidateAllCache() { await distributedCache.RemoveAsync("DATA:CONFIG"); await distributedCache.RemoveAsync("DATA:CHECKLEVEL"); await distributedCache.RemoveAsync("DATA:PLANTS:ListDTO"); await distributedCache.RemoveAsync("DATA:SUPPL:List"); await distributedCache.RemoveAsync("DATA:TRANSP:List"); await distributedCache.RemoveAsync("DATA:WEEKPLAN:List"); await distributedCache.RemoveAsync("ParamSend:List"); } public async Task> ItemsGetAll() { //return Task.FromResult(dbController.ActionsGetAll()); List dbResult = new List(); string cacheKey = "DATA:ITEMS"; string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.GetItems(); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(false)); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB + caching per ItemsGetAll: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } /// /// Restitusice elenco KVP dei TASK (da passare a IOB-WIN) per l'impianto indicato /// /// /// public async Task> mOptParMacchina(string idxMacchina) { // hard coded dimensione vettore DatiMacchine Dictionary answ = new Dictionary(); // ORA recupero da memoria redis... try { string currHash = optParHash(idxMacchina); var redisDataList = await distributedCache.GetAsync(currHash); if (redisDataList != null) { string rawData = Encoding.UTF8.GetString(redisDataList); answ = JsonConvert.DeserializeObject>(rawData); } } catch (Exception exc) { Log.Error($"Errore in compilazione dati OPT PARAM mOptParMacchina | idxMacchina {idxMacchina}{Environment.NewLine}{exc}"); } return answ; } /// /// Restitusice elenco KVP dei TASK SALVATI (da passare a IOB-WIN) per l'impianto indicato /// /// /// public async Task> mSavedTaskMacchina(string idxMacchina) { // hard coded dimensione vettore DatiMacchine Dictionary answ = new Dictionary(); // ORA recupero da memoria redis... try { string cacheKey = savedTaskHash(idxMacchina); string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); answ = JsonConvert.DeserializeObject>(rawData); } } catch (Exception exc) { Log.Error($"Errore in recupero dati SAVED TASK x Redis mSavedTaskMacchina | idxMacchina {idxMacchina}{Environment.NewLine}{exc}"); } return answ; } /// /// Restitusice elenco KVP dei TASK (da passare a IOB-WIN) per l'impianto indicato /// /// /// public async Task> mTaskMacchina(string idxMacchina) { // hard coded dimensione vettore DatiMacchine Dictionary answ = new Dictionary(); // ORA recupero da memoria redis... try { string cacheKey = exeTaskHash(idxMacchina); var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { string rawData = Encoding.UTF8.GetString(redisDataList); answ = JsonConvert.DeserializeObject>(rawData); } } catch (Exception exc) { Log.Error($"Errore in recupero dati EXE TASK x Redis mTaskMacchina | idxMacchina: {idxMacchina}{Environment.NewLine}{exc}"); } return answ; } /// /// Cancellazione Ordine consegna GAS /// /// /// public async Task OrderDelete(OrderModel currItem) { bool done = false; try { done = dbController.OrderDelete(currItem); await InvalidateAllCache(); } catch (Exception exc) { Log.Error($"Eccezione in OrderDelete:{Environment.NewLine}{exc}"); } return await Task.FromResult(done); } public async Task OrderGetByCode(string OrderCode) { OrderModel dbResult = new OrderModel(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.GetOrderByCode(OrderCode); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per OrderGetByCode: {ts.TotalMilliseconds} ms"); return await Task.FromResult(dbResult); } public async Task OrderGetById(int OrderId) { OrderModel dbResult = new OrderModel(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.GetOrderById(OrderId); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per OrderGetById: {ts.TotalMilliseconds} ms"); return await Task.FromResult(dbResult); } public async Task> OrdersGetFilt(SelectOrderData CurrFilter) { List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.GetOrdersFilt(CurrFilter.PlantId, CurrFilter.SupplierId, CurrFilter.TransporterId, CurrFilter.DateStart, CurrFilter.DateEnd, CurrFilter.ShowClosed); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per OrdersGetFilt: {ts.TotalMilliseconds} ms"); return await Task.FromResult(dbResult); } /// /// Elenco degli ordini ancora aperti x il Plant /// /// /// public async Task> OrdersGetOpen(int PlantId) { List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.GetOrdersOpen(PlantId); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per OrdersGetOpen | PlantId: {PlantId} | {ts.TotalMilliseconds} ms"); return await Task.FromResult(dbResult); } /// /// Aggiornamento ordine /// /// /// public async Task OrderUpdate(OrderModel currItem) { bool done = false; try { done = dbController.OrderUpdate(currItem); await InvalidateAllCache(); } catch (Exception exc) { Log.Error($"Eccezione in OrderUpdate:{Environment.NewLine}{exc}"); } return await Task.FromResult(done); } /// /// Elenco di TUTTI i parametri send gestiti /// /// public async Task ParamSendGet(int PlantId, string ParamUid) { ParamSendModel currRecord = dbController.ParamSendGet(PlantId, ParamUid); return await Task.FromResult(currRecord); } /// /// Elenco di TUTTI i parametri send gestiti /// /// public async Task> ParamSendGetAll() { List dbResult = new List(); string cacheKey = "ParamSend:List"; string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.ParamSendGetAll(); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(false)); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB + caching per ParamSendGetAll: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } /// /// Aggiornamento ParamSend record /// /// /// public async Task ParamSendUpdate(ParamSendModel currItem) { bool done = false; try { done = dbController.ParamSendUpdate(currItem); } catch (Exception exc) { Log.Error($"Eccezione in ParamSendUpdate:{Environment.NewLine}{exc}"); } return await Task.FromResult(done); } /// /// Ottiene il valore calcolato x il parametro richiesto al momento della richiesta /// /// /// /// public async Task ParamSetCalcVal(int PlantId, string ParamUid) { decimal answ = 0; List ListRecords = await ParamSetGetFilt(PlantId, ParamUid); if (ListRecords != null && ListRecords.Count > 1) { // prendo i 2 valori precedente e successivo DateTime oggi = DateTime.Today; var prevPar = ListRecords.Where(x => x.Scadenza <= oggi).OrderByDescending(x => x.Scadenza).FirstOrDefault(); var nextPar = ListRecords.Where(x => x.Scadenza >= oggi).OrderBy(x => x.Scadenza).FirstOrDefault(); // se ho valori if (prevPar != null && nextPar != null) { double num = oggi.Subtract(prevPar.Scadenza).TotalDays; double den = nextPar.Scadenza.Subtract(prevPar.Scadenza).TotalDays; den = den != 0 ? den : 1; answ = prevPar.TargetVal + (nextPar.TargetVal - prevPar.TargetVal) * (decimal)(num / den); } } return answ; } /// /// Cancellazione ParamSet /// /// /// public async Task ParamSetDelete(ParamSetModel currItem) { bool done = false; try { done = dbController.ParamSetDelete(currItem); } catch (Exception exc) { Log.Error($"Eccezione in ParamSetDelete:{Environment.NewLine}{exc}"); } return await Task.FromResult(done); } /// /// Recupera ParamSet dato plant e UID parametro /// /// /// public async Task> ParamSetGetFilt(int PlantId, string ParamUid) { List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.ParamSetGet(PlantId, ParamUid); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per ParamSetGetByPlant: {ts.TotalMilliseconds} ms"); return await Task.FromResult(dbResult); } /// /// Aggiornamento ParamSet /// /// /// public async Task ParamSetUpdate(ParamSetModel currItem) { bool done = false; if (currItem != null) { try { done = dbController.ParamSetUpdate(currItem); } catch (Exception exc) { Log.Error($"Eccezione in ParamSetUpdate:{Environment.NewLine}{exc}"); } } return await Task.FromResult(done); } /// /// Effettua verifica parametri da inviare ed eventualmente invia /// /// public async Task ParamsSendCheck() { bool answ = false; // prima di tutto invalido cache dei parametri... await distributedCache.RemoveAsync("ParamSend:List"); DateTime adesso = DateTime.Now; var currParams = await ParamSendGetAll(); // ciclo x tutti dove siano attivi e NON ci fosse veto var activeParams = currParams .Where(x => x.enabled && x.VetoSend <= adesso) .ToList(); if (activeParams != null && activeParams.Count > 0) { foreach (var item in activeParams) { await ParamsSetCheck(item.PlantId, item.ParamUid); // recupero valore... var newVal = await ParamSetCalcVal(item.PlantId, item.ParamUid); // registro richiesta bool fatto = await updateMachineParameter(item.PlantId, item.ParamUid, $"{newVal:N3}"); // registro nuovo veto if (fatto) { // rand attesa... Random rnd = new Random(); DateTime vetoSend = DateTime.Today.AddDays(1).AddHours(item.windStart + rnd.NextDouble() * (item.windEnd - item.windStart)); // salvo! item.LastSend = adesso; item.VetoSend = vetoSend; await ParamSendUpdate(item); } } } // alla fine di nuovo invalido cache dei parametri... await distributedCache.RemoveAsync("ParamSend:List"); return await Task.FromResult(answ); } /// /// Effettua verifica parametri SET ed eventualmente aggiorna (deve esserci 1 record futuro ed 1 passato x interpolare) /// /// public async Task ParamsSetCheck(int PlantId, string ParamUid) { bool answ = false; // elenco parametri set... List ListRecords = await ParamSetGetFilt(PlantId, ParamUid); // per invecchiare DEVONO essere almeno 2 if (ListRecords != null && ListRecords.Count > 1) { // cerco se ci sia 1 valore successivo... DateTime oggi = DateTime.Today; var nextPar = ListRecords.Where(x => x.Scadenza >= oggi).OrderBy(x => x.Scadenza).FirstOrDefault(); if (nextPar == null) { // prendo il valore + vecchio e lo sposto avanti 1 anno... var oldestPar = ListRecords.Where(x => x.Scadenza <= oggi).OrderBy(x => x.Scadenza).FirstOrDefault(); oldestPar.Scadenza = oldestPar.Scadenza.AddYears(1); // salvo! await ParamSetUpdate(oldestPar); } answ = true; } return await Task.FromResult(answ); } public async Task> PlantLogGetFilt(int PlantId, DateTime DtMaxDate, int numRec) { List dbResult = new List(); string cacheKey = $"DATA:PLANTS:LOGS:{PlantId}:{DtMaxDate:yyyyMMddHHmm}:{numRec}"; string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.GetPlantLog(PlantId, DtMaxDate, numRec); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(true)); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB + caching per PlantLogGetFilt: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } public async Task PlantLogInsert(List newItems) { bool fatto = false; // init valori int IntervalMin = 60; int.TryParse(_configuration["IntervalMin"], out IntervalMin); List item2insert = new List(); int PlantId = newItems.FirstOrDefault().PlantId; // aggiorno valori ACT x DTO await updateCurrDTO(newItems); // recupero ultimi inseriti List lastValues = PlantLogGetLastByFlux(PlantId).Result; // verifico i flussi presenti tra quelli ricevuti List fluxList = newItems .GroupBy(g => g.FluxType) .Select(s => s.First().FluxType) .ToList(); foreach (var item in fluxList) { // cerco se c'è valore... var lastInserted = lastValues.Where(x => x.FluxType == item).FirstOrDefault(); DateTime dateLimit = DateTime.Today.AddDays(-1); if (lastInserted != null) { // per ogni flusso calcolo il valore minimo x inserimento (arrotondando a minInt) dateLimit = dbController.DateRoundEnd(lastInserted.DtEvent, IntervalMin); } // cerco se ho record > valore minimo x ogni flusso ricevuto List insCandidates = newItems.Where(x => x.FluxType == item && x.DtEvent >= dateLimit).OrderBy(x => x.DtEvent).ToList(); int num2ins = insCandidates.Count; while (num2ins > 0) { var newRec = insCandidates.First(); // il primo lo accodo da inserire item2insert.Add(newRec); // calcolo nuovo veto dateLimit = dbController.DateRoundEnd(newRec.DtEvent, IntervalMin); // ...e se ho record > data limite accodo insCandidates = newItems.Where(x => x.FluxType == item && x.DtEvent > dateLimit).OrderBy(x => x.DtEvent).ToList(); num2ins = insCandidates.Count; } } // se ho record da inserire... if (item2insert.Count > 0) { // faccio vero insert fatto = dbController.PlantLogInsertNew(item2insert); // invalido i vari valori in cache await distributedCache.RemoveAsync($"DATA:PLANTS:LastFlux:{PlantId}"); await distributedCache.RemoveAsync($"DATA:PLANTS:ListDTO"); Log.Trace($"PlantLogInsert | PlantId: {PlantId} | Completato insert {item2insert.Count} rec"); } // restituisco return await Task.FromResult(fatto); } public async Task> PlantsAnalisysGetByCode(SelectOrderData CurrFilter) { List dbResult = new List(); string cacheKey = $"DATA:PLANTS:LevelSum:{CurrFilter.PlantId}:{CurrFilter.DateStart:yyMMdd}:{CurrFilter.DateEnd:yyMMdd}"; string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.GetPlantLogSummary(CurrFilter.PlantId, CurrFilter.DateStart, CurrFilter.DateEnd); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(true)); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB + caching per PlantsAnalisysGetByCode: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } public async Task PlantsAnalisysReset(SelectOrderData CurrFilter) { bool answ = false; string cacheKey = $"DATA:PLANTS:LevelSum:{CurrFilter.PlantId}:{CurrFilter.DateStart:yyMMdd}:{CurrFilter.DateEnd:yyMMdd}"; await distributedCache.RemoveAsync(cacheKey); answ = true; return await Task.FromResult(answ); } public async Task> PlantsGetAll() { List dbResult = new List(); string cacheKey = "DATA:PLANTS:ListDTO"; string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); int maxRec = 100; int.TryParse(_configuration["MaxLogRecord"], out maxRec); dbResult = dbController.GetPlantsDTO(maxRec); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(true)); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB + caching per PlantsGetAll: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } public async Task PlantsGetByCode(string PlantCode) { PlantDTO answ = new PlantDTO(); var ListRecords = await PlantsGetAll(); var found = ListRecords.Where(x => x.PlantCode == PlantCode).FirstOrDefault(); if (found != null) { answ = found; } return await Task.FromResult(answ); } public async Task PlantUpdate(PlantDTO currItem) { bool done = false; try { done = dbController.PlantUpdate(currItem); await InvalidateAllCache(); } catch (Exception exc) { Log.Error($"Eccezione in OrderUpdate:{Environment.NewLine}{exc}"); } return await Task.FromResult(done); } public void RebootLogInsert(RebootLogModel newItem) { try { dbController.RecordRebootLog(newItem); } catch { } } /// /// Rimuove un item da parametri correnti x IOB /// /// /// /// public async Task remObjItem(string idxMacchina, objItem item2rem) { bool answ = false; if (item2rem != null) { string cacheKey = currParametersHash(idxMacchina); string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); var actValues = JsonConvert.DeserializeObject>(rawData); // cerco e rimuovo var remCand = actValues .Where(x => x.uid == item2rem.uid) .FirstOrDefault(); if (remCand != null) { actValues.Remove(remCand); } // salvo! rawData = JsonConvert.SerializeObject(actValues); await distributedCache.SetAsync(cacheKey, Encoding.UTF8.GetBytes(rawData)); } } return answ; } /// /// RIMUOVE un PARAMETRO OPZIONALE dall'elenco di quelli salvati /// /// /// /// public async Task remOptPar4Machine(string idxMacchina, string taskKey) { bool answ = false; string currHash = optParHash(idxMacchina); try { // leggo task attuali... var currVal = await mOptParMacchina(idxMacchina); currVal.Remove(taskKey); // salvo in redis! string rawData = JsonConvert.SerializeObject(currVal); await distributedCache.SetAsync(currHash, Encoding.UTF8.GetBytes(rawData)); } catch { } return answ; } /// /// RIMUOVE un task dall'elenco di quelli salvati /// /// /// /// public async Task remTask4Machine(string idxMacchina, taskType taskKey) { bool answ = false; string currHash = exeTaskHash(idxMacchina); try { // leggo task attuali... var currTasks = await mTaskMacchina(idxMacchina); // cerco se chiave esiste -_> sostituisco if (currTasks.ContainsKey($"{taskKey}")) { currTasks.Remove($"{taskKey}"); // salvo in redis! string rawData = JsonConvert.SerializeObject(currTasks); await distributedCache.SetAsync(currHash, Encoding.UTF8.GetBytes(rawData)); Log.Info($"Task REM | idxMacchina: {idxMacchina} | taskKey: {taskKey}"); } } catch (Exception exc) { Log.Error($"Errore in remTask4Machine | idxMacchina: {idxMacchina} | taskKey: {taskKey}{Environment.NewLine}{exc}"); } return answ; } public void rollBackEdit(object item) { dbController.rollBackEntity(item); } /// /// salva la conf di memoria della amcchina in redis /// /// /// /// public async Task saveMemMap(string idxMacchina, plcMemMap currMap) { bool answ = false; if (currMap != null) { string currHash = currMamMapHash(idxMacchina); // salvo in redis! string rawData = JsonConvert.SerializeObject(currMap); await distributedCache.SetAsync(currHash, Encoding.UTF8.GetBytes(rawData)); answ = true; } return answ; } /// /// SET elenco parametri correnti x IOB /// /// /// /// public async Task setCurrObjItems(string idxMacchina, List currValues) { bool answ = false; if (currValues != null) { string currHash = currParametersHash(idxMacchina); // salvo in redis! string rawData = JsonConvert.SerializeObject(currValues); await distributedCache.SetAsync(currHash, Encoding.UTF8.GetBytes(rawData)); // 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)) { taskType currTask = (taskType)Enum.Parse(typeof(taskType), item.uid); await addCheckTask4Machine(idxMacchina, currTask, item.value); } } answ = true; } return answ; } public async Task> SuppliersGetAll() { List dbResult = new List(); string cacheKey = "DATA:SUPPL:List"; string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.GetSuppliers(); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(true)); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB + caching per PlantsGetAll: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } public async Task TestSendEmail(string destEmail, string oggetto, string corpo) { bool answ = false; try { await _emailSender.SendEmailAsync(destEmail, oggetto, corpo); answ = true; } catch { } return answ; } public async Task> TransportersGetAll() { List dbResult = new List(); string cacheKey = $"DATA:TRANSP:List"; string rawData; var redisDataList = await distributedCache.GetAsync(cacheKey); if (redisDataList != null) { rawData = Encoding.UTF8.GetString(redisDataList); dbResult = JsonConvert.DeserializeObject>(rawData); } else { Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.GetTransporters(); rawData = JsonConvert.SerializeObject(dbResult); redisDataList = Encoding.UTF8.GetBytes(rawData); await distributedCache.SetAsync(cacheKey, redisDataList, cacheOpt(true)); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB + caching per PlantsGetAll: {ts.TotalMilliseconds} ms"); } return await Task.FromResult(dbResult); } /// /// Aggiornamento parametro per macchina /// /// /// Parametro macchina come definito in file json /// /// public async Task updateMachineParameter(int PlantId, string Original_uid, string reqValue) { bool fatto = false; var plantList = await PlantsGetAll(); var currPlant = plantList .Where(x => x.PlantId == PlantId) .FirstOrDefault(); if (currPlant != null) { fatto = await updateMachineParameter(currPlant.PlantCode, Original_uid, reqValue); } return fatto; } /// /// Aggiornamento parametro per macchina /// /// /// Parametro macchina come definito in file json /// /// public async Task updateMachineParameter(string idxMacchina, string Original_uid, string reqValue) { bool answ = false; // recupero items... List dcList = await getCurrObjItems(idxMacchina); List list2Update = new List(); // 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); await upsertCurrObjItems(idxMacchina, list2Update); // accodo in Task2Exe la richiesta di processing await addTask4Machine(idxMacchina, taskType.setParameter, trovato.uid); if (Enum.IsDefined(typeof(taskType), trovato.uid)) { // salvo ANCHE il valore di setup ASSOCIATO... taskType currTask = (taskType)Enum.Parse(typeof(taskType), trovato.uid); await addTask4Machine(idxMacchina, currTask, reqValue); } answ = true; } return answ; } /// /// Effettua UPSERT elenco parametri correnti x IOB (se c'è UPDATE, se manca ADD) /// /// /// /// public async Task upsertCurrObjItems(string idxMacchina, List innovations) { bool answ = false; if (innovations != null) { string currHash = currParametersHash(idxMacchina); // leggo i valori attuali... List actValues = await getCurrObjItems(idxMacchina); var oldUid = actValues.Select(x => x.uid).Intersect(innovations.Select(i => i.uid)).ToList(); actValues.RemoveAll(x => oldUid.Contains(x.uid)); innovations.AddRange(actValues); // serializzo e salvo string serVal = JsonConvert.SerializeObject(innovations); await distributedCache.SetAsync(currHash, Encoding.UTF8.GetBytes(serVal)); } return answ; } public async Task> UserDataGetFilt(string searchVal) { // Collezione utenti List RawList = new List(); List UsersList = new List(); // recupero utenti da obj _userManager var allData = _userManager.Users.ToList(); if (!string.IsNullOrEmpty(searchVal)) { RawList = allData.Where(x => x.NormalizedEmail.Contains(searchVal.ToUpper()) || x.NormalizedUserName.Contains(searchVal.ToUpper())).ToList(); } else { RawList = allData; } var user = RawList.Select(x => new IdentityUser { Id = x.Id, UserName = x.UserName, Email = x.Email, PhoneNumber = x.PhoneNumber, PasswordHash = "*****", EmailConfirmed = x.EmailConfirmed }).ToList(); foreach (var item in user) { var UserRoles = await _userManager.GetRolesAsync(item); var UserClaims = await _userManager.GetClaimsAsync(item); var newItem = new UserData() { Identity = item, Roles = UserRoles.ToList(), Claims = UserClaims.ToList() }; UsersList.Add(newItem); } return await Task.FromResult(UsersList); } public async void WeekPlanDelete(WeekPlanModel currItem) { try { //dbController.ResetController(); dbController.WeekPlanDelete(currItem); string cacheKey = $"DATA:WEEKPLAN:List"; await distributedCache.RemoveAsync(cacheKey); } catch { } } public async Task> WeekPlanGet() { List dbResult = new List(); Stopwatch stopWatch = new Stopwatch(); stopWatch.Start(); dbResult = dbController.GetWeekPlan(); stopWatch.Stop(); TimeSpan ts = stopWatch.Elapsed; Log.Trace($"Effettuata lettura da DB per WeekPlanGet: {ts.TotalMilliseconds} ms"); return await Task.FromResult(dbResult); } public async void WeekPlanUpdate(WeekPlanModel currItem) { try { //dbController.ResetController(); dbController.WeekPlanUpdate(currItem); string cacheKey = $"DATA:WEEKPLAN:List"; await distributedCache.RemoveAsync(cacheKey); } catch { } } #endregion Public Methods } }