Update x gestione parametri con calcolo vario...

This commit is contained in:
Samuele Locatelli
2022-03-23 20:07:29 +01:00
parent 195f187ba8
commit 4bfe039623
9 changed files with 436 additions and 152 deletions
+36 -15
View File
@@ -1,6 +1,6 @@
[
{
"Order": 0,
"Order": 3,
"Type": "SPEED-5000-10000",
"Title": "SPEED",
"Value": "4000",
@@ -12,11 +12,11 @@
"EnablePlot": true,
"ShowBar": true,
"CssIcon": "fa-solid fa-gauge-high",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 0,
"Order": 2,
"Type": "FEED-3000-5000",
"Title": "FEED",
"Value": "2500",
@@ -28,10 +28,11 @@
"EnablePlot": true,
"ShowBar": true,
"CssIcon": "fa-solid fa-gauge-high",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 0,
"Order": 1,
"Type": "LOAD",
"Title": "SPINDLE LOAD",
"Value": "30",
@@ -43,10 +44,11 @@
"EnablePlot": true,
"ShowBar": true,
"CssIcon": "fa-solid fa-bolt",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 0,
"Order": 4,
"Type": "POS",
"Title": "X POS",
"Value": "1500",
@@ -57,10 +59,11 @@
"IsNumeric": true,
"EnablePlot": true,
"CssIcon": "fa-solid fa-ruler-horizontal",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 0,
"Order": 5,
"Type": "POS",
"Title": "Y POS",
"Value": "5000",
@@ -71,10 +74,11 @@
"IsNumeric": true,
"EnablePlot": true,
"CssIcon": "fa-solid fa-ruler-horizontal",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 0,
"Order": 6,
"Type": "POS",
"Title": "Z POS",
"Value": "-1500",
@@ -85,10 +89,11 @@
"IsNumeric": true,
"EnablePlot": true,
"CssIcon": "fa-solid fa-ruler-horizontal",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 0,
"Order": 7,
"Type": "POS",
"Title": "A POS",
"Value": "150",
@@ -99,6 +104,22 @@
"IsNumeric": true,
"EnablePlot": true,
"CssIcon": "fa-solid fa-rotate-right",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 8,
"Type": "POS",
"Title": "B POS",
"Value": "150",
"ValueNum": 150,
"MinVal": 0,
"MaxVal": 360,
"DisplFormat": "N3",
"IsNumeric": true,
"EnablePlot": true,
"CssIcon": "fa-solid fa-rotate-right",
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
}
]
+5
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static MP.MONO.Core.Enums;
// <Auto-Generated>
// This is here so CodeMaid doesn't reorganize this document
@@ -67,5 +68,9 @@ namespace MP.MONO.Core.DTO
/// Sample period for DB recording of min/Avg/MAX data (seconds)
/// </summary>
public double SamplePeriod { get; set; } = 60 * 3;
/// <summary>
/// Tipo di trasformazione VC da applicare ai dati al momento del raggiungimento del periodo di acquisizione
/// </summary>
public VC_func VcFunc { get; set; } = VC_func.POINT;
}
}
+4 -4
View File
@@ -170,9 +170,9 @@
AVG,
/// <summary>
/// Valore massimo del periodo
/// Calcolo MEDIANA
/// </summary>
MAX,
MEDIAN,
/// <summary>
/// Valore minimo del periodo
@@ -180,9 +180,9 @@
MIN,
/// <summary>
/// Calcolo MEDIANA
/// Valore massimo del periodo
/// </summary>
MEDIAN
MAX
}
#endregion Public Enums
+48
View File
@@ -0,0 +1,48 @@
using static MP.MONO.Core.Enums;
namespace MP.MONO.Core
{
/// <summary>
/// Configurazione per Variabili Casuali
/// </summary>
public class VCData
{
#region Public Fields
/// <summary>
/// DataOra inizio periodo di elaborazione x determinare periodo massimo
/// </summary>
public DateTime DTStart;
#endregion Public Fields
#region Public Properties
/// <summary>
/// Array dati per calcolo
/// </summary>
public List<double> dataArray { get; set; } = new List<double>();
/// <summary>
/// Tipologia di funzione da applicare
/// </summary>
public VC_func Funzione { get; set; } = VC_func.POINT;
/// <summary>
/// Periodo di riferimento in secondi (da aggiungere a DTStart x determinare scadenza x elaborazione)
/// </summary>
public double Period { get; set; } = 60.0;
#endregion Public Properties
public bool isElapsed
{
get
{
bool answ = false;
answ = DTStart.AddSeconds(Period) <= DateTime.Now;
return answ;
}
}
}
}
+22 -11
View File
@@ -1,21 +1,26 @@
using NLog;
using NLua;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.MONO.DECODER
{
public class AlarmsManager
{
protected List<string> AlarmList = new List<string>();
protected static Lua state = new Lua();
#region Protected Fields
protected static Logger Log = LogManager.GetCurrentClassLogger();
protected static string luaPath = "";
protected static Lua state = new Lua();
#endregion Protected Fields
#region Public Fields
public static string alarmStatus = "";
public static bool valueChanged = false;
protected static Logger Log = LogManager.GetCurrentClassLogger();
#endregion Public Fields
#region Public Constructors
public AlarmsManager()
{
@@ -26,16 +31,20 @@ namespace MP.MONO.DECODER
state.DoString(" callMode = 'NLua' ");
// initi 0/0
state.DoString(" lastVal = 0 ");
state.DoString(" currVal = 0 ");
state.DoString(" currVal = 0 ");
#endif
state["callMode"] = "NLua";
state["lastVal"] = 0;
state["currVal"] = 0;
state["currVal"] = 0;
Log.Info("AlarmsManager OK");
Console.WriteLine("AlarmsManager OK");
}
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Funzione chiamata LUA x calcolo status allarmi
/// </summary>
@@ -78,5 +87,7 @@ namespace MP.MONO.DECODER
}
return answ;
}
#endregion Public Methods
}
}
}
+112 -35
View File
@@ -1,60 +1,113 @@
using NLog;
using MP.MONO.Core;
using MP.MONO.Core.DTO;
using MP.MONO.Data.DbModels;
using NLog;
using NLua;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.MONO.DECODER
{
public class ParamsManager
{
protected List<string> AlarmList = new List<string>();
protected static Lua state = new Lua();
#region Private Fields
/// <summary>
/// Dizionario dei valori accumulati sulle variabili
/// </summary>
private Dictionary<string, VCData> ParamsAccumulator = 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;
protected static Logger Log = LogManager.GetCurrentClassLogger();
#endregion Public Fields
#region Public Constructors
public ParamsManager()
{
// preparo variabile x avvisare script che il modo è da NLua
luaPath = Path.Combine(Directory.GetCurrentDirectory(), "lua", "ParamsDecoder.lua");
#if false
state.DoString(" callMode = 'NLua' ");
// initi 0/0
state.DoString(" lastVal = 0 ");
state.DoString(" currVal = 0 ");
#endif
state["callMode"] = "NLua";
state["lastVal"] = 0;
state["currVal"] = 0;
state["currVal"] = 0;
Log.Info("ParamsManager OK");
Console.WriteLine("ParamsManager OK");
}
/// <summary>
/// Funzione chiamata LUA x calcolo status allarmi
/// </summary>
/// <param name="prefix"></param>
/// <param name="alarmList"></param>
/// <param name="muteMask"></param>
/// <param name="disableMask"></param>
/// <param name="lastVal"></param>
/// <param name="currVal"></param>
/// <returns></returns>
public static List<string> processData(string prefix, List<string> alarmList, uint muteMask, uint disableMask, uint lastVal, ref uint currVal)
{
state["prefix"] = prefix;
state["alarmList"] = alarmList;
state["numAlarm"] = alarmList.Count;
state["muteMask"] = muteMask;
state["disableMask"] = disableMask;
#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 (!ParamsAccumulator.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
ParamsAccumulator.Add(item.Key, newSet);
}
}
else
{
// altrimenti aggiungo
ParamsAccumulator[item.Key].dataArray.Add(item.Value);
}
// effettuo verifiche scadenza
if (ParamsAccumulator.ContainsKey(item.Key))
{
if (ParamsAccumulator[item.Key].isElapsed)
{
// se scaduto --> mando a LUA x calcolo
// FIXME TODO
var calcVal = ParamsAccumulator[item.Key].dataArray.FirstOrDefault();
#if false
// processing LUA del calcolo dei dati "scaduti"
//state["prefix"] = prefix;
//state["alarmList"] = alarmList;
//state["numAlarm"] = alarmList.Count;
//state["muteMask"] = muteMask;
//state["disableMask"] = disableMask;
List<string> answ = new List<string>();
// invio dati aggiornati a LUA
state["lastVal"] = lastVal;
state["currVal"] = currVal;
@@ -76,7 +129,31 @@ namespace MP.MONO.DECODER
answ.Add($"{allarme}");
}
}
#endif
// aggiungo alla lista finale...
var dbRecord = new DataLogModel()
{
DtRif = adesso,
FluxType = item.Key,
MachineId = 1,
ValNum = calcVal,
ValStr = $"{calcVal:N3}"
};
answ.Add(dbRecord);
// elimino dai valori accumulati...
ParamsAccumulator.Remove(item.Key);
}
}
}
return answ;
}
#endregion Public Methods
}
}
}
+17 -45
View File
@@ -202,11 +202,16 @@ void AlarmsValPipe_EA_NewMessage(object? sender, EventArgs e)
alarmsPipe.saveAndSendMessage(Constants.ALARM_CURR_KEY, serAlarms);
if (dbController != null)
{
// salvo sul DB
_ = dbController.AlarmLogInsertMany(alarmLogList).Result;
#if false
// salvo nel DB lo stato dei bank di allarme
foreach (var dbItem in alarmLogList)
{
_ = dbController.AlarmLogInsert(dbItem).Result;
}
}
#endif
}
}
}
@@ -227,37 +232,8 @@ void ParamsValPipe_EA_NewMessage(object? sender, EventArgs e)
{
try
{
// esempio conversione dati
#if false
List<DisplayDataDTO> answ = new List<DisplayDataDTO>();
// genero a partire dall'elenco configurato da simulare...
answ = currSimPar.Select(i => new DisplayDataDTO()
{
IsNumeric = i.IsNumeric,
MaxVal = i.MaxVal,
MinVal = i.MinVal,
Order = i.Order,
Title = i.Title,
Type = i.Type,
ValueNum = simNext(i.ValueNum, i.MinVal, i.MaxVal, i.SimMean, i.SimStd),
DisplFormat = i.DisplFormat,
CssIcon = i.CssIcon,
EnablePlot = i.EnablePlot,
ShowBar = i.ShowBar,
ShowGauge = i.ShowGauge,
}).ToList();
foreach (var item in answ)
{
item.Value = $"{item.ValueNum.ToString(item.DisplFormat)}";
}
return answ;
#endif
// verifico codici ricevuti
var paramsList = JsonConvert.DeserializeObject<Dictionary<string, double>>(currArgs.newMessage);
if (paramsList != null)
{
// recupero elenco parametri salvati in redis...
@@ -283,26 +259,22 @@ void ParamsValPipe_EA_NewMessage(object? sender, EventArgs e)
updatedParams.Add(currParam);
}
}
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;
}
}
}
}
//// salvo status aggiornato parametri...
//redisDb.StringSet(Constants.PARAMS_CURR_KEY, JsonConvert.SerializeObject(redisParamConf));
string updRawVal = JsonConvert.SerializeObject(redisParamConf);
// invio sulla message pipeline corretta TUTTI i parametri aggiornati serializzati
string updRawVal = JsonConvert.SerializeObject(redisParamConf);
paramsPipe.saveAndSendMessage(Constants.PARAMS_CURR_KEY, updRawVal);
if (dbController != null)
{
// effettuo update in DB se ho
//// salvo nel DB lo stato dei bank di allarme
//foreach (var dbItem in alarmLogList)
//{
// _ = dbController.AlarmLogInsert(dbItem).Result;
//}
}
}
}
catch (Exception exc)
+176 -33
View File
@@ -1,29 +1,26 @@
using Microsoft.Extensions.Configuration;
using MP.MONO.Core;
using Microsoft.EntityFrameworkCore;
using MP.MONO.Core.DTO;
using MP.MONO.Data.DbModels;
using NLog;
using System;
using System.Collections.Generic;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace MP.MONO.Data.Controllers
{
public class MpDbController : IDisposable
{
#region Private Fields
private static NLog.Logger Log = LogManager.GetCurrentClassLogger();
#endregion Private Fields
#region Public Constructors
public MpDbController()
{ }
public void Dispose()
{
// Clear database context
//Log.Info("Dispose di GWMSController");
}
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Recupero elenco allarmi (ultimi datop "skip")
@@ -82,27 +79,150 @@ namespace MP.MONO.Data.Controllers
return fatto;
}
public ProductionDTO MachineGetProd()
/// <summary>
/// Inserimento di un record AlarmLog
/// </summary>
/// <param name="newItems">Lista Record da inserire (senza ID...)</param>
/// <returns></returns>
public async Task<bool> AlarmLogInsertMany(List<AlarmLogModel> newItems)
{
// !!!FIXME TODO... è fake...
Random rand = new Random();
int stdCycle = 5;
ProductionDTO currMachDto = new ProductionDTO()
bool fatto = false;
using (MapoMonoContext localDbCtx = new MapoMonoContext())
{
Order = "ODL Test",
ItemCode = "ART.0000123",
ProgName = "P000012",
CurrQty = DateTime.Now.Minute + rand.Next(1, 40),
OrderQty = 100,
CycleTimeMin = rand.NextDouble() * stdCycle,
Message = "...simulated data..."
};
try
{
await localDbCtx
.DbSetAlarmLog
.AddRangeAsync(newItems);
await localDbCtx.SaveChangesAsync();
fatto = true;
}
catch (Exception exc)
{
Log.Error($"Eccezione durante AlarmLogInsert{Environment.NewLine}{exc}");
}
}
return fatto;
}
Task.Delay(400).Wait();
/// <summary>
/// Recupero record DataLog data condizione filtro
/// </summary>
/// <param name="MachineId"></param>
/// <param name="FluxType"></param>
/// <param name="skipRec"></param>
/// <param name="numRec"></param>
/// <returns></returns>
public List<DataLogModel> DataLogGetFilt(int MachineId, string FluxType, int skipRec, int numRec)
{
List<DataLogModel> dbResult = new List<DataLogModel>();
using (MapoMonoContext localDbCtx = new MapoMonoContext())
{
try
{
dbResult = localDbCtx
.DbSetDataLog
.Where(x => x.MachineId == MachineId && x.FluxType == FluxType)
.Include(m => m.MachineNav)
.OrderByDescending(x => x.DataLogId)
.Skip(skipRec)
.Take(numRec)
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante DataLogGetFilt{Environment.NewLine}{exc}");
}
}
return dbResult;
}
return currMachDto;
/// <summary>
/// Inserimento di un SET di record DataLog (post aggregazione base VC)
/// </summary>
/// <param name="newItems">Lista Record da inserire (senza ID...)</param>
/// <returns></returns>
public async Task<bool> DataLogInsertMany(List<DataLogModel> newItems)
{
bool fatto = false;
using (MapoMonoContext localDbCtx = new MapoMonoContext())
{
try
{
await localDbCtx
.DbSetDataLog
.AddRangeAsync(newItems);
await localDbCtx.SaveChangesAsync();
fatto = true;
}
catch (Exception exc)
{
Log.Error($"Eccezione durante DataLogInsert{Environment.NewLine}{exc}");
}
}
return fatto;
}
/// <summary>
/// Recupero record DataStAg (aggregati) data condizione filtro
/// </summary>
/// <param name="MachineId"></param>
/// <param name="FluxType"></param>
/// <param name="skipRec"></param>
/// <param name="numRec"></param>
/// <returns></returns>
public List<DataStAgModel> DataStAgGetFilt(int MachineId, string FluxType, int skipRec, int numRec)
{
List<DataStAgModel> dbResult = new List<DataStAgModel>();
using (MapoMonoContext localDbCtx = new MapoMonoContext())
{
try
{
dbResult = localDbCtx
.DbSetDataStAg
.Where(x => x.MachineId == MachineId && x.FluxType == FluxType)
.Include(m => m.MachineNav)
.OrderByDescending(x => x.DataStAgId)
.Skip(skipRec)
.Take(numRec)
.ToList();
}
catch (Exception exc)
{
Log.Error($"Eccezione durante DataLogGetFilt{Environment.NewLine}{exc}");
}
}
return dbResult;
}
/// <summary>
/// Inserimento di un record DataStAg (aggregati) - creati da ANALYZER che effettua compattazione
/// </summary>
/// <param name="newItem">Record da inserire (senza ID...)</param>
/// <returns></returns>
public async Task<bool> DataStAgInsert(DataStAgModel newItem)
{
bool fatto = false;
using (MapoMonoContext localDbCtx = new MapoMonoContext())
{
try
{
localDbCtx
.DbSetDataStAg
.Add(newItem);
await localDbCtx.SaveChangesAsync();
fatto = true;
}
catch (Exception exc)
{
Log.Error($"Eccezione durante DataStAgInsert{Environment.NewLine}{exc}");
}
}
return fatto;
}
public void Dispose()
{
// Clear database context
//Log.Info("Dispose di GWMSController");
}
public List<DisplayDataDTO> MachineGetDisplay()
@@ -185,11 +305,34 @@ namespace MP.MONO.Data.Controllers
};
answ.Add(displ06);
Task.Delay(200).Wait();
return answ;
}
}
}
public ProductionDTO MachineGetProd()
{
// !!!FIXME TODO... è fake...
Random rand = new Random();
int stdCycle = 5;
ProductionDTO currMachDto = new ProductionDTO()
{
Order = "ODL Test",
ItemCode = "ART.0000123",
ProgName = "P000012",
CurrQty = DateTime.Now.Minute + rand.Next(1, 40),
OrderQty = 100,
CycleTimeMin = rand.NextDouble() * stdCycle,
Message = "...simulated data..."
};
Task.Delay(400).Wait();
return currMachDto;
}
#endregion Public Methods
}
}
+16 -9
View File
@@ -12,8 +12,8 @@
"EnablePlot": true,
"ShowBar": true,
"CssIcon": "fa-solid fa-gauge-high",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 2,
@@ -28,7 +28,8 @@
"EnablePlot": true,
"ShowBar": true,
"CssIcon": "fa-solid fa-gauge-high",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 1,
@@ -43,7 +44,8 @@
"EnablePlot": true,
"ShowBar": true,
"CssIcon": "fa-solid fa-bolt",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 4,
@@ -57,7 +59,8 @@
"IsNumeric": true,
"EnablePlot": true,
"CssIcon": "fa-solid fa-ruler-horizontal",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 5,
@@ -71,7 +74,8 @@
"IsNumeric": true,
"EnablePlot": true,
"CssIcon": "fa-solid fa-ruler-horizontal",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 6,
@@ -85,7 +89,8 @@
"IsNumeric": true,
"EnablePlot": true,
"CssIcon": "fa-solid fa-ruler-horizontal",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 7,
@@ -99,7 +104,8 @@
"IsNumeric": true,
"EnablePlot": true,
"CssIcon": "fa-solid fa-rotate-right",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
},
{
"Order": 8,
@@ -113,6 +119,7 @@
"IsNumeric": true,
"EnablePlot": true,
"CssIcon": "fa-solid fa-rotate-right",
"SamplePeriod": 180
"SamplePeriod": 180,
"VcFunc": "MEDIAN"
}
]