Files
mapo-mono/MP.MONO.DECODER/AlarmsBlinkManager.cs
samuele e71b873a4c - nuget update
- pulizia codice da warning
2023-08-21 18:06:54 +02:00

387 lines
14 KiB
C#

using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Configuration;
using MP.MONO.Core;
using MP.MONO.Data;
using MP.MONO.Data.Controllers;
using MP.MONO.Data.DbModels;
using Newtonsoft.Json;
using NLog;
using StackExchange.Redis;
using System.Collections.Concurrent;
namespace MP.MONO.DECODER
{
public class AlarmsBlinkManager
{
#region Public Constructors
public AlarmsBlinkManager()
{
var env = Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT");
var builder = new ConfigurationBuilder()
.AddJsonFile($"appsettings.json", true, true)
.AddJsonFile($"appsettings.{env}.json", true, true)
.AddEnvironmentVariables();
var config = builder.Build();
redisConn = ConnectionMultiplexer.Connect(config.GetConnectionString("Redis"));
redisDb = redisConn.GetDatabase();
Log.Info("ABM: Redis OK!");
// altri parametri per check vari
string connStringDB = DbConfig.CONNECTION_STRING;
if (string.IsNullOrEmpty(connStringDB))
{
Log.Error("ABM: ConnString empty!");
}
else
{
dbController = new MpDbController(config);
Log.Info("ABM: DbController OK");
Console.WriteLine("ABM: DbController OK");
}
setupAlarmState();
Log.Info("AlarmsBlinkManager OK");
Console.WriteLine("AlarmsBlinkManager OK");
}
#endregion Public Constructors
#region Public Properties
/// <summary>
/// Elenco allarmi attivi e acknowled ad es: subito i nuovi, con ritardo i cessati
/// </summary>
public static List<string> alarmsActAck
{
get => getAlarms($"{redisDb.StringGet(Constants.ALARM_CURR_KEY)}");
set => setAlarms(Constants.ALARM_CURR_KEY, value);
}
/// <summary>
/// Elenco ultimo set allarmi ricevuti
/// </summary>
public static List<string> alarmsLastRec
{
get => getAlarms($"{redisDb.StringGet(Constants.ALARM_RECEIV_KEY)}");
set => setAlarms(Constants.ALARM_RECEIV_KEY, value);
}
/// <summary>
/// Ultima Stringa LOG allarmi salvata
/// </summary>
public static string alarmsLogSaved
{
get => $"{redisDb.StringGet(Constants.ALARM_LOG_SAVED)}";
set => redisDb.StringSet(Constants.ALARM_LOG_SAVED, value);
}
public static List<string> alarmsPendingClose
{
get
{
// rileggo da REDIS SE ci sono allarmi che sono pending close... in un area che dura poco (2 sec)
List<string> lista = new List<string>();
// in base al tipo leggo una chiave redis o l'altra...
var rawData = redisDb.StringGet(Constants.ALARM_PEND_KEY);
if (!string.IsNullOrEmpty(rawData))
{
var desList = JsonConvert.DeserializeObject<List<string>>($"{rawData}");
if (desList != null)
{
lista = desList;
}
}
return lista;
}
set
{
string rawData = JsonConvert.SerializeObject(value);
redisDb.StringSet(Constants.ALARM_PEND_KEY, rawData, TimeSpan.FromMilliseconds(3000));
}
}
#endregion Public Properties
#region Public Methods
public static bool isProcessing { get; set; } = false;
public static bool isRemoving { get; set; } = false;
private static int ticketNum { get; set; } = 0;
private static ConcurrentQueue<int> reqList { get; set; } = new ConcurrentQueue<int>();
/// <summary>
/// Recupera un ticket di esecuzione x eseguire in ordine corretto gli insert...
/// </summary>
/// <returns></returns>
public static int getTicket()
{
// incremento contatore
ticketNum++;
// faccio coda 0...9999
ticketNum = ticketNum > 9999 ? 1 : ticketNum;
// accodo...
reqList.Enqueue(ticketNum);
// rendo ticket
return ticketNum;
}
/// <summary>
/// Indica il ticket attualmente in esecuzione
/// </summary>
/// <returns></returns>
public static int currTicket
{
get
{
int answ = -1;
reqList.TryPeek(out answ);
return answ;
}
}
/// <summary>
/// Verifico se il mio ticket sia quello corretto/prossimo
/// </summary>
/// <param name="ticket"></param>
/// <returns></returns>
public static bool checkTicket(int ticket)
{
bool fatto = false;
if (!isProcessing)
{
// verifico se quello richiesto sia il ticket giusto
if (ticket == currTicket)
{
isProcessing = true;
int usedTicket = 0;
fatto = reqList.TryDequeue(out usedTicket);
}
}
return fatto;
}
/// <summary>
/// restituisce elenco allarmi muted, eventualmente da cache redis ( 5 sec)
/// </summary>
/// <returns></returns>
private static List<string> alarmMutedList
{
get
{
List<string> mutedAlarm = new List<string>();
// cerco in redis...
var rawData = redisDb.StringGet(Constants.ALARMS_SETT_MUTED_KEY);
if (!string.IsNullOrEmpty(rawData))
{
var rawAlarm = JsonConvert.DeserializeObject<List<string>>($"{rawData}");
if (rawAlarm != null)
{
mutedAlarm = rawAlarm;
}
}
else
{
// altrimenti da conf/DB... gestione allarmi muted
List<AlarmListModel>? alarmListSetup = new List<AlarmListModel>();
rawData = redisDb.StringGet(Constants.ALARMS_SETT_RLIST_KEY);
if (!string.IsNullOrEmpty(rawData))
{
alarmListSetup = JsonConvert.DeserializeObject<List<AlarmListModel>>($"{rawData}");
}
if (alarmListSetup == null)
{
alarmListSetup = dbController.AlarmListGetAll();
}
// calcolo come lista string...
if (alarmListSetup != null && alarmListSetup.Count > 0)
{
mutedAlarm = alarmListSetup.Where(x => x.Muted).Select(x => x.FullValue).ToList();
}
// salvo cache in redis x 1 minuto...
rawData = JsonConvert.SerializeObject(mutedAlarm);
redisDb.StringSet(Constants.ALARMS_SETT_MUTED_KEY, rawData, TimeSpan.FromSeconds(60));
}
return mutedAlarm;
}
}
/// <summary>
/// Effettua cleanup preliminare allarmi data condizione regext pre/post
/// </summary>
/// <param name="AlarmCleanPre"></param>
/// <param name="AlarmCleanPost"></param>
/// <param name="alarmListRaw"></param>
/// <returns></returns>
public static List<string> cleanAlarms(string AlarmCleanPre, string AlarmCleanPost, List<string> alarmListRaw)
{
List<string> alarmList = new List<string>();
// effettuo cleanup degli allarmi con procedura ricerca regexp
foreach (var item in alarmListRaw)
{
string currData = item;
// se ho valori trim pre/post li applica...
if (!string.IsNullOrEmpty(AlarmCleanPre))
{
currData = item.Replace(AlarmCleanPre, "");
}
if (!string.IsNullOrEmpty(AlarmCleanPost))
{
currData = currData.Replace(AlarmCleanPost, "");
}
// aggiungo
alarmList.Add(currData);
}
// Restituisco
return alarmList;
}
/// <summary>
/// Funzione chiamata x verifica allarmi:
/// - fornisce elenco allarmi correnti aggiornati
/// - fornisce elenco dei NUOVI come ref
/// - fornisce elenco dei CESSATI come ref
/// </summary>
/// <param name="alarmListReceived"></param>
/// <param name="alarmListCurrent"></param>
/// <param name="alarmListAdded"></param>
/// <param name="alarmListCeased"></param>
/// <returns>Boolean che indica se ci siano state variazioni</returns>
public static bool processData(List<string> alarmListReceived, ref List<string> alarmListCurrent, ref List<string> alarmListAdded, ref List<string> alarmListCeased)
{
bool answ = false;
// primo step: verifico gli allarmi ricevuti siano > 0 e NON contengano duplicati...
List<string> alarmListReceivedOk = new List<string>();
if (alarmListReceived.Count > 0)
{
alarmListReceivedOk = alarmListReceived
.GroupBy(x => x)
.Select(grp => grp.First())
.OrderBy(x => x)
.ToList();
Log.Debug($"Ricezione update allarmi | {alarmListReceived.Count} --> {alarmListReceivedOk.Count} distinct");
}
else
{
Log.Debug($"Ricezione ZERO allarmi | {alarmListReceived.Count}");
}
// elimino muted da allarmi
List<string> listMuted = new List<string>(alarmMutedList);
if (listMuted.Count > 0)
{
foreach (var item in listMuted)
{
alarmListReceivedOk.Remove(item);
}
}
// salvo set allarmi ricevuti...
alarmsLastRec = alarmListReceivedOk;
Log.Debug($"Salvataggio LastReceived | count {alarmListReceivedOk.Count}");
// elenco allarmi confermati
var alarmListConf = alarmListCurrent.Intersect(alarmListReceivedOk);
// copio oggetti x allarmi NUOVI e cessati
alarmListAdded = new List<string>(alarmListReceivedOk);
alarmListCeased = new List<string>(alarmListCurrent);
foreach (var item in alarmListConf)
{
// calcolo allarmi nuovi/cessati eliminando eventuali elementi comuni
alarmListAdded.Remove(item);
alarmListCeased.Remove(item);
}
// aggiungo i nuovi a current
alarmListCurrent.AddRange(alarmListAdded);
// riordino
alarmListCurrent = alarmListCurrent.OrderBy(x => x).ToList();
#if false
// ...e salvo subito
alarmsActAck = alarmListCurrent;
#endif
// loggo controllo
Log.Debug($"Esito controllo | {alarmListReceivedOk.Count} ricevuti | {alarmListAdded.Count} aggiunti | {alarmListCeased.Count} cessati");
// restituisco esito = allarmi ricevuti da registrare
answ = (alarmListAdded.Count > 0);
return answ;
}
#endregion Public Methods
#region Protected Fields
protected static Logger Log = LogManager.GetCurrentClassLogger();
#endregion Protected Fields
#region Private Fields
private static ConnectionMultiplexer? redisConn = null;
private static IDatabase redisDb = null!;
private static MpDbController dbController = null!;
#endregion Private Fields
#region Private Properties
#endregion Private Properties
#region Private Methods
/// <summary>
/// Converto deserializzando lista allarmi
/// </summary>
private static List<string> getAlarms(string rawData)
{
List<string> lastAlarms = new List<string>();
// se trovati uso questi...
if (!string.IsNullOrEmpty(rawData))
{
var rawLastAlarms = JsonConvert.DeserializeObject<List<string>>(rawData);
lastAlarms = rawLastAlarms != null ? rawLastAlarms : new List<string>();
}
return lastAlarms;
}
/// <summary>
/// Salvo in redis gli allarmi datala key
/// </summary>
/// <param name="keyName"></param>
/// <param name="listAlarm"></param>
/// <returns></returns>
private static bool setAlarms(string keyName, List<string> listAlarm)
{
bool fatto = false;
string rawData = JsonConvert.SerializeObject(listAlarm);
fatto = redisDb.StringSet(keyName, rawData);
Log.Debug($"Scrittura allarmi | key: {keyName} | num: {listAlarm.Count}");
return fatto;
}
/// <summary>
/// Setup iniziale allarmi
/// </summary>
private void setupAlarmState()
{
// setup preliminare allarmi da DB
var currActive = dbController.AlarmRecGetActive();
alarmsActAck = currActive
.Select(x => x.AlarmListNav.FullValue)
.Distinct()
.ToList();
alarmsLastRec = new List<string>();
alarmsPendingClose = new List<string>();
Log.Debug($"Setup Stato allarmi | act: {alarmsActAck.Count}");
}
#endregion Private Methods
}
}