UPdate gestione SIM x nuovo val

This commit is contained in:
Samuele Locatelli
2022-10-03 15:55:14 +02:00
parent 904cafa91b
commit cfaf57f34f
10 changed files with 379 additions and 11 deletions
+2 -1
View File
@@ -74,9 +74,10 @@ namespace MP.MONO.Core
// REDIS Channels messaggi (verso DECODER)
public static readonly string ALARM_RAW_QUEUE = $"AlarmsRawVal";
public static readonly string COUNT_RAW_QUEUE = $"CountRawVal";
public static readonly string PARAMS_RAW_QUEUE = $"ParamsRawVal";
public static readonly string STATUS_RAW_QUEUE = $"StatusRawVal";
public static readonly string COUNT_RAW_QUEUE = $"CountRawVal";
public static readonly string TOOLS_RAW_QUEUE = $"ToolsRawVal";
#endregion Public Fields
}
+1
View File
@@ -133,6 +133,7 @@ namespace MP.MONO.DECODER
DtRif = adesso,
FluxType = item.Key,
MachineId = 1,
DataType = Enums.DataLogType.Parameter,
ValNum = calcVal,
ValStr = $"{calcVal:N3}"
+95
View File
@@ -100,6 +100,7 @@ setupConf();
DateTime lastExecParams = DateTime.Now.AddHours(-1);
DateTime lastLogDetail = DateTime.Now.AddHours(-1);
int numSendParam = 1;
int numSendTools = 1;
int numSendMStatus = 1;
/* --------------------------------
@@ -126,6 +127,19 @@ DateTime lastExecStatus = DateTime.Now.AddHours(-1);
// registro gestione eventi
mpStatusRecvPipe.EA_NewMessage += MpStatusRecvPipe_EA_NewMessage;
/* --------------------------------
* Setup Gestione Tools
* --------------------------------*/
ToolsManager toolsMan = new ToolsManager();
// inizializzo gestione messagePipe da Redis x allarmi
MessagePipe toolsSendPipe = new MessagePipe(redisConn, Constants.TOOLS_M_QUEUE);
MessagePipe toolsRecvPipe = new MessagePipe(redisConn, Constants.TOOLS_RAW_QUEUE);
// datetime dell'inizio esecuzione task... x usare un semaforo di veto doppia esecuzione entro 30 sec
DateTime lastExecTools = DateTime.Now.AddHours(-1);
// registro gestione eventi
toolsRecvPipe.EA_NewMessage += ToolsRecvPipe_EA_NewMessage;
/* --------------------------------
* Setup Gestione Parametri
* --------------------------------*/
@@ -535,6 +549,87 @@ void AlarmsValPipe_EA_NewMessage(object? sender, EventArgs e)
}
}
/// <summary>
/// Gestione evento ricezione messaggi tools
/// </summary>
void ToolsRecvPipe_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;
List<DisplayDataDTO>? redisToolsConf = new List<DisplayDataDTO>();
try
{
// verifico codici ricevuti
var toolsList = JsonConvert.DeserializeObject<Dictionary<string, double>>(currArgs.newMessage);
if (toolsList != null)
{
// recupero elenco parametri salvati in redis...
string rawData = redisDb.StringGet(Constants.TOOLS_CONF_KEY);
if (!string.IsNullOrEmpty(rawData))
{
redisToolsConf = JsonConvert.DeserializeObject<List<DisplayDataDTO>>(rawData);
// se ho i parametri...
if (redisToolsConf != null)
{
// ciclo x ogni valore ricevuto da message service...
foreach (var item in toolsList)
{
// cerco il parametro corrispondente...
var currToolVal = redisToolsConf.FirstOrDefault(x => x.Title == item.Key);
if (currToolVal != null)
{
currToolVal.ValueNum = item.Value;
currToolVal.Value = $"{item.Value.ToString(currToolVal.DisplFormat)}";
}
}
// verifico NON ci sia veto di scrittura... DbSampleInt (60 sec...)
if (adesso.Subtract(lastExecTools).TotalSeconds > DbSampleInt)
{
lastExecTools = adesso;
if (dbController != null)
{
// verifico x ogni parametro se sia completato il periodo di campionamento...
var val2save = toolsMan.processData(toolsList, redisToolsConf);
if (val2save.Count > 0)
{
// salvo sul DB
_ = dbController.DataLogInsertMany(val2save).Result;
Log.Info($"Tools | DB | {val2save.Count} rec inserted");
}
}
}
}
}
// invio sulla message pipeline corretta TUTTI i parametri aggiornati serializzati
string updRawVal = JsonConvert.SerializeObject(redisToolsConf);
toolsSendPipe.saveAndSendMessage(Constants.TOOLS_CURR_KEY, updRawVal);
if (redisToolsConf != null)
{
if (adesso.Subtract(lastLogDetail).TotalSeconds > 5 || numSendTools > 10)
{
Log.Info($"TOOLS | {redisToolsConf.Count} data transmitted x {numSendTools}");
lastLogDetail = adesso;
numSendTools = 0;
}
else
{
numSendTools++;
}
}
}
}
catch (Exception exc)
{
Log.Error($"Eccezione in ToolsRecvPipe_EA_NewMessage:{Environment.NewLine}{exc}{Environment.NewLine}{currArgs.newMessage}");
}
}
}
/// <summary>
/// Gestione evento ricezione messaggi parametri
/// </summary>
+155
View File
@@ -0,0 +1,155 @@
using MP.MONO.Core;
using MP.MONO.Core.DTO;
using MP.MONO.Data.DbModels;
using NLog;
using NLua;
namespace MP.MONO.DECODER
{
public class ToolsManager
{
#region Private Fields
/// <summary>
/// Dizionario dei valori accumulati sulle variabili
/// </summary>
private Dictionary<string, VCData> VarAccumulator = new Dictionary<string, VCData>();
#endregion Private Fields
#region Protected Fields
protected static Logger Log = LogManager.GetCurrentClassLogger();
protected static string luaPath = "";
protected static Lua state = new Lua();
protected List<string> AlarmList = new List<string>();
#endregion Protected Fields
#region Public Fields
public static string alarmStatus = "";
public static bool valueChanged = false;
#endregion Public Fields
#region Public Constructors
public ToolsManager()
{
// preparo variabile x avvisare script che il modo è da NLua
state["callMode"] = "NLua";
state["vcFunct"] = "AVG";
// carico il file (derivato da quello dei parametri)
luaPath = Path.Combine(Directory.GetCurrentDirectory(), "lua", "ToolsDecoder.lua");
state.DoFile(luaPath);
Log.Info("ToolsManager OK");
Console.WriteLine("ToolsManager OK");
}
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Funzione chiamata LUA x calcolo degli eventuali parametri con periodi "scaduti"
/// </summary>
/// <param name="paramsList"></param>
/// <param name="redisParamConf"></param>
/// <returns></returns>
public List<DataLogModel> processData(Dictionary<string, double> paramsList, List<DisplayDataDTO> redisParamConf)
{
List<DataLogModel> answ = new List<DataLogModel>();
DateTime adesso = DateTime.Now;
// vado ad "accumulare i dati" a quelli presenti...
foreach (var item in paramsList)
{
var currParam = redisParamConf.FirstOrDefault(x => x.Title == item.Key);
// cerco nelle variabili accomulatori...
if (!VarAccumulator.ContainsKey(item.Key))
{
if (currParam != null)
{
var dataList = new List<double>();
dataList.Add(item.Value);
VCData newSet = new VCData()
{
dataArray = dataList,
DTStart = adesso,
Funzione = currParam.VcFunc,
Period = currParam.SamplePeriod
};
// se non ci fosse creo
VarAccumulator.Add(item.Key, newSet);
}
}
else
{
// altrimenti aggiorno
VarAccumulator[item.Key].dataArray.Add(item.Value);
}
// effettuo verifiche scadenza
bool calcOk = false;
double calcVal = 0;
if (VarAccumulator.ContainsKey(item.Key))
{
if (VarAccumulator[item.Key].isElapsed)
{
string funcMode = $"{VarAccumulator[item.Key].Funzione}";
// se scaduto --> mando a LUA x calcolo
state["valList"] = VarAccumulator[item.Key].dataArray;
state["numRec"] = VarAccumulator[item.Key].dataArray.Count;
state["vcFunct"] = funcMode;
// effettuo calcolo
state.DoString("doProcess()");
// recupero valore calcolato
bool.TryParse(state.GetString("calcOk"), out calcOk);
if (calcOk)
{
try
{
var stringVal = state.GetString("calcVal");
if (!string.IsNullOrEmpty(stringVal))
{
calcVal = state.GetNumber("calcVal");
Log.Trace($"calcVal: {calcVal}");
}
}
catch (Exception exc)
{
Log.Error($"exception during processData for {item.Key}{Environment.NewLine}{exc}");
}
}
// aggiungo alla lista finale...
var dbRecord = new DataLogModel()
{
DtRif = adesso,
FluxType = item.Key,
MachineId = 1,
DataType = Enums.DataLogType.Tools,
ValNum = calcVal,
ValStr = $"{calcVal:N3}"
};
answ.Add(dbRecord);
// elimino dai valori accumulati...
VarAccumulator.Remove(item.Key);
}
}
}
return answ;
}
#endregion Public Methods
}
}
+2 -2
View File
@@ -1,10 +1,10 @@
--[[---------------------------------------------------
Procedura calcolo statistiche parametri:
Procedura calcolo statistiche counters (derivato dai parametri):
Variabili IN:
- vcFunct(string): tipo di processing da effettuare tra [POINT/AVG/MEDIAN/MIN/MAX]
- valList(<double>): elenco VALORI double da processare
- numRec(int): conteggio numero recorda da processare
- numRec(int): conteggio numero record da processare
Variabili OUT:
- calcVal(double): valore calcolato finale
+1 -1
View File
@@ -4,7 +4,7 @@ Procedura calcolo statistiche parametri:
Variabili IN:
- vcFunct(string): tipo di processing da effettuare tra [POINT/AVG/MEDIAN/MIN/MAX]
- valList(<double>): elenco VALORI double da processare
- numRec(int): conteggio numero recorda da processare
- numRec(int): conteggio numero record da processare
Variabili OUT:
- calcVal(double): valore calcolato finale
+105
View File
@@ -0,0 +1,105 @@
--[[---------------------------------------------------
Procedura calcolo statistiche TOOLS:
Variabili IN:
- vcFunct(string): tipo di processing da effettuare tra [POINT/AVG/MEDIAN/MIN/MAX]
- valList(<double>): elenco VALORI double da processare
- numRec(int): conteggio numero record da processare
Variabili OUT:
- calcVal(double): valore calcolato finale
-----------------------------------------------------]]
-- Per eventuale debug
local ZBS = "c:/ZeroBraneStudio"
if not package.path:find(ZBS,1,true) then
package.path = ZBS .. "/lualibs/?/?.lua;" .. ZBS .. "/lualibs/?.lua;" .. package.path
package.cpath = ZBS .. "/bin/?.dll;" .. ZBS .. "/bin/clibs53/?.dll;" .. package.cpath
end
-- se non è da NLua inizializzo variabili accessorie
local function checkInit()
if (callMode ~= 'NLua') then
-- imposto valori test
valList = { 4467, 4468, 4467, 4467, 4467, 4467 }
numRec = #valList
--valList = { 4.0, 5.0, 3.0, 6.0, 1.0, 2.0 }
vcFunct = 'AVG'
--POINT AVG MEDIAN MIN MAX
end
end
local function setupTable()
if numRec > 0 and valList[0] ~= nil then
for i = numRec, 1, -1 do
valListTable[i] = valList[i-1]
end
else
valListTable = valList
end
end
local function doCalc()
if(numRec > 0) then
-- verifica il tipo di richiesta
if(vcFunct == 'AVG') then
s = 0
for i,v in ipairs(valListTable) do
s = s + v
end
calcVal = s / numRec
elseif(vcFunct == 'POINT') then
calcVal = valListTable[numRec]
elseif(vcFunct == 'MEDIAN') then
table.sort(valListTable)
calcVal = valListTable[numRec/2]
elseif(vcFunct == 'MIN') then
table.sort(valListTable)
calcVal = valListTable[1]
elseif(vcFunct == 'MAX') then
table.sort(valListTable)
calcVal = valListTable[numRec]
end
calcOk = true
else
calcVal = -999999
numRec = 1
calcOk = false
end
end
local function displayTestInfo()
if (callMode ~= 'NLua') then
print('------------------------------')
print('calcOk: ' .. tostring(calcOk) .. ' | vcFunct: ' .. vcFunct)
for i,val in pairs(valList) do
print("v_"..i.." | "..val)
end
print('calcVal: ' .. calcVal)
print('------------------------------')
end
end
-- MAIN
function doProcess()
-- variabile semaforo callMode (locali o remote da NLua)
callMode = callMode or ''
calcVal = -999
vcFunct = vcFunct or ''
valList = valList or {}
numRec = numRec or 1
calcOk = false
valListTable = {}
checkInit()
setupTable()
doCalc()
displayTestInfo()
end
if (callMode ~= 'NLua') then
doProcess()
end
+3 -2
View File
@@ -495,11 +495,12 @@ namespace MP.MONO.Data.Controllers
/// Recupero record DataLog data condizione filtro
/// </summary>
/// <param name="machineId"></param>
/// <param name="dataType">Tipologia di dato richiesto da enum</param>
/// <param name="fluxType"></param>
/// <param name="inizio"></param>
/// <param name="fine"></param>
/// <returns></returns>
public List<DataLogModel> DataLogGetFilt(int machineId, string fluxType, DateTime inizio, DateTime fine)
public List<DataLogModel> DataLogGetFilt(int machineId, DataLogType dataType, string fluxType, DateTime inizio, DateTime fine)
{
List<DataLogModel> dbResult = new List<DataLogModel>();
using (MapoMonoContext localDbCtx = new MapoMonoContext())
@@ -508,7 +509,7 @@ namespace MP.MONO.Data.Controllers
{
dbResult = localDbCtx
.DbSetDataLog
.Where(x => x.MachineId == machineId && x.FluxType == fluxType && x.DtRif >= inizio && x.DtRif <= fine)
.Where(x => (x.MachineId == machineId) && (x.FluxType == fluxType) && (x.DataType == dataType || dataType == DataLogType.ND) && (x.DtRif >= inizio && x.DtRif <= fine))
.Include(m => m.MachineNav)
.OrderByDescending(x => x.DataLogId)
.ToList();
+2 -1
View File
@@ -513,7 +513,8 @@ void simTools()
// recupero uno stato simulato
var newVal = currSimGen.getTools();
string rawData = JsonConvert.SerializeObject(newVal);
saveAndSendMessage(Constants.TOOLS_CURR_KEY, Constants.TOOLS_M_QUEUE, rawData);
saveAndSendMessage(Constants.TOOLS_CURR_KEY, Constants.TOOLS_RAW_QUEUE, rawData);
//saveAndSendMessage(Constants.TOOLS_CURR_KEY, Constants.TOOLS_M_QUEUE, rawData);
// attesa random
Thread.Sleep(rand.Next(minPeriod, maxPeriod));
+13 -4
View File
@@ -235,11 +235,20 @@ namespace MP.MONO.UI.Data
return await Task.FromResult(dbResult);
}
public async Task<List<DataLogModel>> DataLogGetFilt(int machineId, string fluxType, DateTime inizio, DateTime fine)
/// <summary>
/// TimeSearie in formato DataLogModel
/// </summary>
/// <param name="machineId">ID macchina</param>
/// <param name="dataType">Tipologia di dato richiesto da enum</param>
/// <param name="fluxType">Tipo di Flusso</param>
/// <param name="inizio">DT Inizio estrazione</param>
/// <param name="fine">DT Fine estrazione</param>
/// <returns></returns>
public async Task<List<DataLogModel>> DataLogGetFilt(int machineId, DataLogType dataType, string fluxType, DateTime inizio, DateTime fine)
{
string source = "DB";
List<DataLogModel> dbResult = new List<DataLogModel>();
string currKey = $"{Constants.DATA_LOG_KEY}:{machineId}:{fluxType.Replace(" ", "_")}:{inizio:yyyyMMdd}:{fine:yyyyMMdd}";
string currKey = $"{Constants.DATA_LOG_KEY}:{machineId}:{dataType}:{fluxType.Replace(" ", "_")}:{inizio:yyyyMMdd}:{fine:yyyyMMdd}";
Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();
string rawData = await redisDb.StringGetAsync(currKey);
@@ -258,14 +267,14 @@ namespace MP.MONO.UI.Data
}
else
{
dbResult = dbController.DataLogGetFilt(machineId, fluxType, inizio, fine);
dbResult = dbController.DataLogGetFilt(machineId, dataType, fluxType, inizio, fine);
// salvo per 2 min...
rawData = JsonConvert.SerializeObject(dbResult);
await redisDb.StringSetAsync(currKey, rawData, TimeSpan.FromSeconds(120));
}
stopWatch.Stop();
TimeSpan ts = stopWatch.Elapsed;
Log.Info($"DataLogGetFilt | {machineId} | {fluxType} | {inizio:yyyyMMdd}-{fine:yyyyMMdd} | {source} | {ts.TotalMilliseconds} ms | {rawData.Length / 1024} kb");
Log.Info($"DataLogGetFilt | {machineId} | {dataType} | {fluxType} | {inizio:yyyyMMdd}-{fine:yyyyMMdd} | {source} | {ts.TotalMilliseconds} ms | {rawData.Length / 1024} kb");
return dbResult;
}
/// <summary>