fc36b427c4
- fix alalrmi vuoti - fix abilitazione SIM se no allarmi da simulare - fix conf redis allarmi
481 lines
20 KiB
C#
481 lines
20 KiB
C#
using Microsoft.Extensions.Configuration;
|
|
using MP.MONO.Core;
|
|
using MP.MONO.Core.CONF;
|
|
using MP.MONO.Core.DTO;
|
|
using MP.MONO.Data;
|
|
using MP.MONO.Data.Controllers;
|
|
using MP.MONO.Data.DbModels;
|
|
using MP.MONO.DECODER;
|
|
using Newtonsoft.Json;
|
|
using NLog;
|
|
using NLua;
|
|
using StackExchange.Redis;
|
|
using static MP.MONO.Core.Enums;
|
|
|
|
// See https://aka.ms/new-console-template for more information
|
|
|
|
// init parte config, vedere https://blog.hildenco.com/2020/05/configuration-in-net-core-console.html
|
|
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();
|
|
|
|
// init LOG
|
|
Logger Log = LogManager.GetCurrentClassLogger();
|
|
|
|
// initi va di base
|
|
string lineSep = "---------------------------------------------";
|
|
Console.WriteLine(lineSep);
|
|
Console.WriteLine("Start DECODER with LUA integration!");
|
|
Console.WriteLine("");
|
|
Console.WriteLine("Running - press CTRL-C to stop");
|
|
Console.WriteLine(lineSep);
|
|
Console.WriteLine("");
|
|
|
|
// init DB
|
|
// init info x DB
|
|
string dbServerAddr = config["DbConfig:Server"];
|
|
string nKey = config["DbConfig:nKey"];
|
|
string sKey = config["DbConfig:sKey"];
|
|
DbConfig.InitDb(dbServerAddr, nKey, sKey);
|
|
// inizializzo il DB e creo (se necessario) l'utente
|
|
DbConfig.CheckUser(nKey, sKey);
|
|
// verifico se serve applicazione migrazioni
|
|
DbConfig.ExecMigrationMain();
|
|
//DbConfig.ExecMigrationIdentity();
|
|
|
|
// altri parametri per check vari
|
|
string connStringDB = DbConfig.CONNECTION_STRING;
|
|
MpDbController dbController = null!;
|
|
if (string.IsNullOrEmpty(connStringDB))
|
|
{
|
|
Log.Error("ConnString empty!");
|
|
}
|
|
else
|
|
{
|
|
dbController = new MpDbController();
|
|
Log.Info("DbController OK");
|
|
Console.WriteLine("DbController OK");
|
|
}
|
|
|
|
// init info di base
|
|
int MachineId = 1;
|
|
int.TryParse(config.GetValue<string>("MachineId"), out MachineId);
|
|
|
|
// init oggetti REDIS + messagePipe...
|
|
ConnectionMultiplexer.SetFeatureFlag("preventthreadtheft", true);
|
|
ConnectionMultiplexer redisConn = ConnectionMultiplexer.Connect(config.GetConnectionString("Redis"));
|
|
IDatabase? redisDb = redisConn.GetDatabase();
|
|
|
|
// preparo oggetti da configurare
|
|
AlarmReportingMode alarmMode = AlarmReportingMode.ND;
|
|
List<BaseAlarmBankConf>? alarmsBankBitConf = new List<BaseAlarmBankConf>();
|
|
List<BaseAlarmRawConf>? alarmsRListConf = new List<BaseAlarmRawConf>();
|
|
List<string>? activeAlarmList = new List<string>();
|
|
List<AlarmListModel>? alarmsRecorded = new List<AlarmListModel>();
|
|
List<MachineMode>? machineModeConf = new List<MachineMode>();
|
|
List<MachineStatus>? machineStatusConf = new List<MachineStatus>();
|
|
// gestione configurazioni da redis
|
|
setupConf();
|
|
|
|
/* --------------------------------
|
|
* Setup Gestione ALLARMI
|
|
* --------------------------------*/
|
|
// init classe gestione allarmi con LUA
|
|
AlarmsManager alarmsMan = new AlarmsManager();
|
|
// inizializzo gestione messagePipe da Redis x allarmi
|
|
MessagePipe alarmsPipe = new MessagePipe(redisConn, Constants.ALARM_M_QUEUE);
|
|
MessagePipe alarmsValPipe = new MessagePipe(redisConn, Constants.ALARM_ACT_QUEUE);
|
|
// datetime dell'inizio esecuzione task... x usare un semaforo di veto doppia esecuzione entro 30 sec
|
|
DateTime lastExecAlarms = DateTime.Now.AddHours(-1);
|
|
// registro gestione eventi
|
|
alarmsValPipe.EA_NewMessage += AlarmsValPipe_EA_NewMessage;
|
|
|
|
/* --------------------------------
|
|
* Setup Gestione Parametri
|
|
* --------------------------------*/
|
|
ParamsManager paramMan = new ParamsManager();
|
|
// inizializzo gestione messagePipe da Redis x allarmi
|
|
MessagePipe paramsPipe = new MessagePipe(redisConn, Constants.PARAMS_M_QUEUE);
|
|
MessagePipe paramsValPipe = new MessagePipe(redisConn, Constants.PARAMS_ACT_QUEUE);
|
|
// datetime dell'inizio esecuzione task... x usare un semaforo di veto doppia esecuzione entro 30 sec
|
|
DateTime lastExecParams = DateTime.Now.AddHours(-1);
|
|
// registro gestione eventi
|
|
paramsValPipe.EA_NewMessage += ParamsValPipe_EA_NewMessage;
|
|
|
|
|
|
/* --------------------------------
|
|
* Funzioni / metodi accessori
|
|
* --------------------------------*/
|
|
/// <summary>
|
|
/// Recupero da redis le conf (es modi,stati,allarmi)
|
|
/// </summary>
|
|
void setupConf()
|
|
{
|
|
// recupero valori e deserializzo
|
|
string rawData = "";
|
|
|
|
// machine conf
|
|
rawData = redisDb.StringGet(Constants.STATUS_CONF_KEY);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
machineStatusConf = JsonConvert.DeserializeObject<List<MachineStatus>>(rawData);
|
|
}
|
|
|
|
// machine mode
|
|
rawData = redisDb.StringGet(Constants.MODE_CONF_KEY);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
machineModeConf = JsonConvert.DeserializeObject<List<MachineMode>>(rawData);
|
|
}
|
|
|
|
// allarmi..
|
|
rawData = redisDb.StringGet(Constants.ALARMS_MODE_KEY);
|
|
alarmMode = JsonConvert.DeserializeObject<AlarmReportingMode>(rawData);
|
|
// elenco allarmi già registrati (cache DB)
|
|
rawData = redisDb.StringGet(Constants.ALARMS_SETT_RLIST_KEY);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
alarmsRecorded = JsonConvert.DeserializeObject<List<AlarmListModel>>(rawData);
|
|
}
|
|
// ora la conf specifica
|
|
rawData = redisDb.StringGet(Constants.ALARMS_CONF_KEY);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
if (alarmMode == AlarmReportingMode.RawList)
|
|
{
|
|
alarmsRListConf = JsonConvert.DeserializeObject<List<BaseAlarmRawConf>>(rawData);
|
|
}
|
|
else
|
|
{
|
|
alarmsBankBitConf = JsonConvert.DeserializeObject<List<BaseAlarmBankConf>>(rawData);
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gestione evento ricezione messaggi allarmi secondo tipologia attiva...
|
|
/// </summary>
|
|
void AlarmsValPipe_EA_NewMessage(object? sender, EventArgs e)
|
|
{
|
|
PubSubEventArgs currArgs = (PubSubEventArgs)e;
|
|
// conversione on-the-fly List<string> --> allarmi
|
|
if (!string.IsNullOrEmpty(currArgs.newMessage))
|
|
{
|
|
DateTime adesso = DateTime.Now;
|
|
if (alarmMode == AlarmReportingMode.RawList)
|
|
{
|
|
try
|
|
{
|
|
// decodifico allarmi ricevuti
|
|
var alarmList = JsonConvert.DeserializeObject<List<string>>(currArgs.newMessage);
|
|
List<AlarmRecModel> alarmRecList = new List<AlarmRecModel>();
|
|
List<AlarmLogModel> alarmLogList = new List<AlarmLogModel>();
|
|
|
|
|
|
List<AlarmListModel>? mutedAlarmsList = new List<AlarmListModel>();
|
|
string rawData = redisDb.StringGet(Constants.ALARMS_SETT_RLIST_KEY);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
mutedAlarmsList = JsonConvert.DeserializeObject<List<AlarmListModel>>(rawData);
|
|
}
|
|
if (mutedAlarmsList == null)
|
|
{
|
|
mutedAlarmsList = dbController.AlarmListGetAll();
|
|
}
|
|
|
|
// rileggo da REDIS la conf attuale allarmi già attivi da area ALARM_CURR_KEY
|
|
List<string>? lastAlarms = new List<string>();
|
|
rawData = redisDb.StringGet(Constants.ALARM_CURR_KEY);
|
|
// se trovati uso questi...
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
lastAlarms = JsonConvert.DeserializeObject<List<string>>(rawData);
|
|
}
|
|
// altrimenti parto da vuoto
|
|
else
|
|
{
|
|
lastAlarms = new List<string>();
|
|
}
|
|
// ciclo x ogni allarme ricevuto x vedere se sia INIZIATO
|
|
if (alarmList != null)
|
|
{
|
|
// ciclo x ogni allarme attivo x verificare se si sia CHIUSO
|
|
foreach (var newAlarm in alarmList)
|
|
{
|
|
// in primis... se è muted --> lo escludo...
|
|
bool isMuted = false;
|
|
var maybeMuted = mutedAlarmsList.Where(x => x.FullValue == newAlarm).FirstOrDefault();
|
|
if (maybeMuted != null)
|
|
{
|
|
isMuted = maybeMuted.Muted;
|
|
}
|
|
// cerco l'allarme nell'elenco degli allarmi dal DB
|
|
var foundAlarm = alarmsRecorded
|
|
.Where(x => x.FullValue == newAlarm)
|
|
.FirstOrDefault();
|
|
// se non lo trovo --> chiamo procedura che verifica su DB, eventualmente inserisce, restituisce nuovo elenco
|
|
if (foundAlarm == null)
|
|
{
|
|
// salvo sul DB
|
|
foundAlarm = dbController.AlarmListInsert(newAlarm);
|
|
// ora rileggo ed aggiorno redis e cerco di nuovo record...
|
|
alarmsRecorded = dbController.AlarmListGetAll();
|
|
redisDb.StringSet(Constants.ALARMS_SETT_RLIST_KEY, JsonConvert.SerializeObject(alarmsRecorded));
|
|
}
|
|
if (!isMuted && lastAlarms != null)
|
|
{
|
|
if (!lastAlarms.Contains(newAlarm))
|
|
{
|
|
if (foundAlarm != null)
|
|
{
|
|
|
|
// segno come iniziato...
|
|
AlarmRecModel newAlarmRec = new AlarmRecModel()
|
|
{
|
|
MachineId = MachineId,
|
|
DtStart = adesso,
|
|
DtEnd = adesso,
|
|
AlarmId = foundAlarm.AlarmId
|
|
};
|
|
alarmRecList.Add(newAlarmRec);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// rimuovo da alarmList
|
|
alarmList.Remove(newAlarm);
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// processo elenco allarmi già presenti
|
|
if (lastAlarms != null)
|
|
{
|
|
// ciclo x ogni allarme attivo x verificare se si sia CHIUSO
|
|
foreach (var oldData in lastAlarms)
|
|
{
|
|
var trovato = alarmList.Contains(oldData);
|
|
if (!trovato)
|
|
{
|
|
// se non lo trovo
|
|
var foundAlarm = alarmsRecorded
|
|
.Where(x => x.FullValue == oldData)
|
|
.FirstOrDefault();
|
|
if (foundAlarm != null)
|
|
{
|
|
// salvo sul DB
|
|
_ = dbController.AlarmRecCloseActive(foundAlarm.AlarmId);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// verifico se devo scrivere
|
|
bool wALog = lastAlarms.Count != alarmList.Count;
|
|
if (!wALog)
|
|
{
|
|
// verifico se ci siano differenze...
|
|
wALog = alarmList.Union(lastAlarms).Count() != lastAlarms.Count;
|
|
}
|
|
|
|
// salvo se c'è stata variazione...
|
|
if (wALog)
|
|
{
|
|
// preparo dati x alarmLog
|
|
AlarmLogModel newAlarmLog = new AlarmLogModel()
|
|
{
|
|
MachineId = MachineId,
|
|
DtRif = adesso,
|
|
MemAddress = "ND",
|
|
Index = 0,
|
|
Status = (uint)alarmList.Count,
|
|
ValDecoded = alarmList.Count > 0 ? string.Join(", ", alarmList) : "All OK"
|
|
};
|
|
alarmLogList.Add(newAlarmLog);
|
|
}
|
|
|
|
// serializzo l'elenco allarmi...
|
|
string serAlarms = "[]";
|
|
serAlarms = JsonConvert.SerializeObject(alarmList);
|
|
// invio sulla message pipeline corretta TUTTI gli allarmi serializzati
|
|
alarmsPipe.saveAndSendMessage(Constants.ALARM_CURR_KEY, serAlarms);
|
|
|
|
// salvo sul DB
|
|
_ = dbController.AlarmRecInsertMany(alarmRecList).Result;
|
|
_ = dbController.AlarmLogInsertMany(alarmLogList).Result;
|
|
|
|
// salvo nuovo elenco allarmi
|
|
lastAlarms = alarmList;
|
|
|
|
}
|
|
catch
|
|
{ }
|
|
}
|
|
else
|
|
{
|
|
try
|
|
{
|
|
// verifico codici allarmi ricevuti
|
|
var alarmList = JsonConvert.DeserializeObject<Dictionary<string, uint>>(currArgs.newMessage);
|
|
if (alarmList != null)
|
|
{
|
|
// variabili accessorie
|
|
List<string> activeAlarmList = new List<string>();
|
|
List<AlarmLogModel> alarmLogList = new List<AlarmLogModel>();
|
|
|
|
// rileggo da REDIS la conf attuale allarmi da area ALARMS_SETT_KEY, altrimenti uso quella letta inizialmente da conf base
|
|
List<BaseAlarmBankConf>? currAlarmsBankConf = new List<BaseAlarmBankConf>();
|
|
string rawData = redisDb.StringGet(Constants.ALARMS_SETT_BBIT_KEY);
|
|
// se trovati uso questi...
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
currAlarmsBankConf = JsonConvert.DeserializeObject<List<BaseAlarmBankConf>>(rawData);
|
|
}
|
|
// altrimenti uso quelli di default inizialmente letti
|
|
else
|
|
{
|
|
currAlarmsBankConf = alarmsBankBitConf;
|
|
}
|
|
if (currAlarmsBankConf != null)
|
|
{
|
|
// ciclo x ogni bank di allarmi configurato
|
|
foreach (var alarmData in currAlarmsBankConf)
|
|
{
|
|
// recupero valore allarme
|
|
var bankVal = alarmList.FirstOrDefault(x => x.Key == alarmData.memAddr);
|
|
uint actVal = !string.IsNullOrEmpty(bankVal.Key) ? bankVal.Value : 0;
|
|
// valutare se dividere in 2 da 16... FIXME TODO
|
|
var bankAlarmList = AlarmsManager.processData(alarmData.memAddr, alarmData.messages, alarmData.silenceMask[0], alarmData.disableMask[0], alarmData.alarmsState[0], ref actVal);
|
|
// salvo nuovo valore in oggetto...
|
|
if (alarmData.alarmsState[0] != actVal)
|
|
{
|
|
alarmData.alarmsState[0] = actVal;
|
|
// aggiungo...
|
|
activeAlarmList.AddRange(bankAlarmList);
|
|
|
|
AlarmLogModel newAlarmLog = new AlarmLogModel()
|
|
{
|
|
MachineId = MachineId,
|
|
DtRif = adesso,
|
|
MemAddress = bankVal.Key,
|
|
Index = alarmData != null ? alarmData.index : 0,
|
|
Status = alarmData != null ? (uint)bankVal.Value & alarmData.silenceMask[0] & alarmData.disableMask[0] : (uint)bankVal.Value,
|
|
ValDecoded = bankAlarmList.Count > 0 ? string.Join(", ", bankAlarmList) : "All OK"
|
|
};
|
|
alarmLogList.Add(newAlarmLog);
|
|
}
|
|
}
|
|
}
|
|
|
|
// salvo status aggiornato allarme...
|
|
redisDb.StringSet(Constants.ALARMS_SETT_BBIT_KEY, JsonConvert.SerializeObject(currAlarmsBankConf));
|
|
|
|
// serializzo l'elenco allarmi...
|
|
string serAlarms = "[]";
|
|
serAlarms = JsonConvert.SerializeObject(activeAlarmList);
|
|
// invio sulla message pipeline corretta TUTTI gli allarmi serializzati
|
|
alarmsPipe.saveAndSendMessage(Constants.ALARM_CURR_KEY, serAlarms);
|
|
// verifico NON ci sia veto di scrittura... 60 sec...
|
|
if (adesso.Subtract(lastExecAlarms).TotalSeconds > 60)
|
|
{
|
|
lastExecAlarms = adesso;
|
|
if (dbController != null)
|
|
{
|
|
// salvo sul DB
|
|
_ = dbController.AlarmLogInsertMany(alarmLogList).Result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione in AlarmsValPipe_EA_NewMessage, mode {alarmMode}:{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
}
|
|
}
|
|
/// <summary>
|
|
/// Gestione evento ricezione messaggi parametri
|
|
/// </summary>
|
|
void ParamsValPipe_EA_NewMessage(object? sender, EventArgs e)
|
|
{
|
|
PubSubEventArgs currArgs = (PubSubEventArgs)e;
|
|
// conversione on-the-fly Dictionary<string,int> --> parametri valorizzati (tra quelli configurati)
|
|
if (!string.IsNullOrEmpty(currArgs.newMessage))
|
|
{
|
|
DateTime adesso = DateTime.Now;
|
|
try
|
|
{
|
|
// verifico codici ricevuti
|
|
var paramsList = JsonConvert.DeserializeObject<Dictionary<string, double>>(currArgs.newMessage);
|
|
if (paramsList != null)
|
|
{
|
|
// recupero elenco parametri salvati in redis...
|
|
List<DisplayDataDTO>? redisParamConf = new List<DisplayDataDTO>();
|
|
List<DisplayDataDTO> updatedParams = new List<DisplayDataDTO>();
|
|
string rawData = redisDb.StringGet(Constants.PARAMS_CONF_KEY);
|
|
if (!string.IsNullOrEmpty(rawData))
|
|
{
|
|
redisParamConf = JsonConvert.DeserializeObject<List<DisplayDataDTO>>(rawData);
|
|
// se ho i parametri...
|
|
if (redisParamConf != null)
|
|
{
|
|
// ciclo x ogni valore ricevuto da message service...
|
|
foreach (var item in paramsList)
|
|
{
|
|
// cerco il parametro corrispondente...
|
|
var currParam = redisParamConf.FirstOrDefault(x => x.Title == item.Key);
|
|
if (currParam != null)
|
|
{
|
|
currParam.ValueNum = item.Value;
|
|
currParam.Value = $"{item.Value.ToString(currParam.DisplFormat)}";
|
|
// aggiungo a lista...
|
|
updatedParams.Add(currParam);
|
|
}
|
|
}
|
|
// verifico NON ci sia veto di scrittura... 60 sec...
|
|
if (adesso.Subtract(lastExecParams).TotalSeconds > 60)
|
|
{
|
|
lastExecParams = adesso;
|
|
if (dbController != null)
|
|
{
|
|
// verifico x ogni parametro se sia completato il periodo di campionamento...
|
|
var params2save = paramMan.processData(paramsList, redisParamConf);
|
|
if (params2save.Count > 0)
|
|
{
|
|
// salvo sul DB
|
|
_ = dbController.DataLogInsertMany(params2save).Result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// invio sulla message pipeline corretta TUTTI i parametri aggiornati serializzati
|
|
string updRawVal = JsonConvert.SerializeObject(redisParamConf);
|
|
paramsPipe.saveAndSendMessage(Constants.PARAMS_CURR_KEY, updRawVal);
|
|
}
|
|
}
|
|
catch (Exception exc)
|
|
{
|
|
Log.Error($"Eccezione in ParamsValPipe_EA_NewMessage:{Environment.NewLine}{exc}");
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* --------------------------------
|
|
* MAIN
|
|
* --------------------------------*/
|
|
|
|
// Ciclo infinito x attesa chiusura con CTRL-C
|
|
do
|
|
{
|
|
Thread.Sleep(100);
|
|
} while (true); |