From af780ca23a71059b0084700c17c44b5e613b5d66 Mon Sep 17 00:00:00 2001 From: Samuele Locatelli Date: Mon, 7 Mar 2022 19:17:06 +0100 Subject: [PATCH] Aggiunta bozza simulazione statistiche macchina (OEE) --- MP.MONO.UI/Components/MachStatsOverview.razor | 34 +++++ .../Components/MachStatsOverview.razor.cs | 52 +++++++ MP.MONO.UI/Components/ParamOverview.razor | 2 +- MP.MONO.UI/Components/ParamOverview.razor.cs | 46 +++--- MP.MONO.UI/Components/StatsOverview.razor | 67 --------- MP.MONO.UI/Data/CurrentDataService.cs | 2 + MP.MONO.UI/Pages/Index.razor | 16 +- .../Pages/{Stats.razor => MachStats.razor} | 6 +- MP.MONO.UI/Shared/NavMenu.razor | 2 +- MachineSim/MachineSim.csproj | 3 + MachineSim/Program.cs | 23 ++- MachineSim/SimMachStat.json | 14 ++ MachineSim/Simulator.cs | 138 +++++++++++------- 13 files changed, 246 insertions(+), 159 deletions(-) create mode 100644 MP.MONO.UI/Components/MachStatsOverview.razor create mode 100644 MP.MONO.UI/Components/MachStatsOverview.razor.cs delete mode 100644 MP.MONO.UI/Components/StatsOverview.razor rename MP.MONO.UI/Pages/{Stats.razor => MachStats.razor} (65%) create mode 100644 MachineSim/SimMachStat.json diff --git a/MP.MONO.UI/Components/MachStatsOverview.razor b/MP.MONO.UI/Components/MachStatsOverview.razor new file mode 100644 index 0000000..b0c7f6a --- /dev/null +++ b/MP.MONO.UI/Components/MachStatsOverview.razor @@ -0,0 +1,34 @@ +@using MP.MONO.UI.Components +@using MP.MONO.Core.DTO +@using MP.MONO.UI.Data + +@inject CurrentDataService MMDataService + +@if (ListRecords != null && ListRecords.Count>0) +{ + + +} +else +{ + + +} + + diff --git a/MP.MONO.UI/Components/MachStatsOverview.razor.cs b/MP.MONO.UI/Components/MachStatsOverview.razor.cs new file mode 100644 index 0000000..8a33575 --- /dev/null +++ b/MP.MONO.UI/Components/MachStatsOverview.razor.cs @@ -0,0 +1,52 @@ +using MP.MONO.Core.DTO; +using MP.MONO.Data; +using Newtonsoft.Json; + +namespace MP.MONO.UI.Components +{ + public partial class MachStatsOverview + { + #region Private Properties + + private List? ListRecords { get; set; } = null; + + #endregion Private Properties + + #region Private Methods + + private void MachStatsPipe_EA_NewMessage(object? sender, EventArgs e) + { + PubSubEventArgs currArgs = (PubSubEventArgs)e; + if (!string.IsNullOrEmpty(currArgs.newMessage)) + { + try + { + ListRecords = JsonConvert.DeserializeObject>(currArgs.newMessage); + } + catch + { } + } + InvokeAsync(() => + { + StateHasChanged(); + }); + } + + #endregion Private Methods + + #region Protected Methods + + protected override async Task OnInitializedAsync() + { + await ReloadData(); + MMDataService.machStatsPipe.EA_NewMessage += MachStatsPipe_EA_NewMessage; + } + + protected async Task ReloadData() + { + ListRecords = await MMDataService.MachineDisplay(); + } + + #endregion Protected Methods + } +} \ No newline at end of file diff --git a/MP.MONO.UI/Components/ParamOverview.razor b/MP.MONO.UI/Components/ParamOverview.razor index 5aa1994..ad2284c 100644 --- a/MP.MONO.UI/Components/ParamOverview.razor +++ b/MP.MONO.UI/Components/ParamOverview.razor @@ -4,7 +4,7 @@ @inject CurrentDataService MMDataService -@if (@dataLoaded && ListRecords != null) +@if (ListRecords != null && ListRecords.Count>0) {
    @foreach (var item in ListRecords) diff --git a/MP.MONO.UI/Components/ParamOverview.razor.cs b/MP.MONO.UI/Components/ParamOverview.razor.cs index 77828d3..6fc3850 100644 --- a/MP.MONO.UI/Components/ParamOverview.razor.cs +++ b/MP.MONO.UI/Components/ParamOverview.razor.cs @@ -1,35 +1,18 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.AspNetCore.Components; -using System.Net.Http; -using Microsoft.AspNetCore.Authorization; -using Microsoft.AspNetCore.Components.Authorization; -using Microsoft.AspNetCore.Components.Forms; -using Microsoft.AspNetCore.Components.Routing; -using Microsoft.AspNetCore.Components.Web; -using Microsoft.AspNetCore.Components.Web.Virtualization; -using Microsoft.JSInterop; using MP.MONO.Core.DTO; using MP.MONO.Data; -using MP.MONO.UI; -using MP.MONO.UI.Shared; -using MP.MONO.UI.Components; -using MP.MONO.UI.Data; using Newtonsoft.Json; namespace MP.MONO.UI.Components { public partial class ParamOverview { - protected bool dataLoaded = false; + #region Private Properties + private List? ListRecords { get; set; } = null; - protected override async Task OnInitializedAsync() - { - await ReloadData(); - MMDataService.parametersPipe.EA_NewMessage += ParametersPipe_EA_NewMessage; - } + + #endregion Private Properties + + #region Private Methods private void ParametersPipe_EA_NewMessage(object? sender, EventArgs e) { @@ -49,12 +32,23 @@ namespace MP.MONO.UI.Components }); } + #endregion Private Methods + + #region Protected Methods + + protected override async Task OnInitializedAsync() + { + await ReloadData(); + MMDataService.parametersPipe.EA_NewMessage += ParametersPipe_EA_NewMessage; + } + protected async Task ReloadData() { - await Task.Delay(10); + await Task.Delay(1); ListRecords = await MMDataService.MachineDisplay(); - await Task.Delay(500); - dataLoaded = true; + await Task.Delay(1); } + + #endregion Protected Methods } } \ No newline at end of file diff --git a/MP.MONO.UI/Components/StatsOverview.razor b/MP.MONO.UI/Components/StatsOverview.razor deleted file mode 100644 index 660a17e..0000000 --- a/MP.MONO.UI/Components/StatsOverview.razor +++ /dev/null @@ -1,67 +0,0 @@ -@using MP.MONO.UI.Components -@using MP.MONO.Core.DTO -@using MP.MONO.UI.Data - -@inject CurrentDataService MMDataService - -@if (@dataLoaded && ListRecords != null) -{ -
      - @foreach (var item in ListRecords) - { -
    • -
      -
      @item.Title
      -
      -
      @item.Value
      -
      -
      -
    • - } -
    - -} -else -{ -
      -
    • OEE%
    • -
    • Stats Details
    • -
    • Graph & Analytics
    • -
    - - - - -} -@code { - protected bool dataLoaded = false; - private List? ListRecords { get; set; } = null; - - private string _newMessage { get; set; } = ""; - - #if false - public string newMessage - { - get => _newMessage; - set - { - _newMessage = value; - MMDataService.alarmPipe.sendMessage(value); - } - } - #endif - - protected override async Task OnInitializedAsync() - { - await ReloadData(); - } - - protected async Task ReloadData() - { - //await Task.Delay(10); - //ListRecords = await MMDataService.MachineDisplay(); - await Task.Delay(500); - dataLoaded = true; - } - -} diff --git a/MP.MONO.UI/Data/CurrentDataService.cs b/MP.MONO.UI/Data/CurrentDataService.cs index 7f7265d..f2b1296 100644 --- a/MP.MONO.UI/Data/CurrentDataService.cs +++ b/MP.MONO.UI/Data/CurrentDataService.cs @@ -57,6 +57,7 @@ namespace MP.MONO.UI.Data public MessagePipe parametersPipe { get; set; } = null!; public MessagePipe statusPipe { get; set; } = null!; public MessagePipe productionPipe { get; set; } = null!; + public MessagePipe machStatsPipe { get; set; } = null!; #region Public Constructors @@ -73,6 +74,7 @@ namespace MP.MONO.UI.Data parametersPipe = new MessagePipe(redisConn, "parameters"); statusPipe = new MessagePipe(redisConn, "status"); productionPipe = new MessagePipe(redisConn, "production"); + machStatsPipe = new MessagePipe(redisConn, "machstats"); // conf cache this.distributedCache = distributedCache; diff --git a/MP.MONO.UI/Pages/Index.razor b/MP.MONO.UI/Pages/Index.razor index 868ffdd..f8e60fa 100644 --- a/MP.MONO.UI/Pages/Index.razor +++ b/MP.MONO.UI/Pages/Index.razor @@ -9,9 +9,9 @@
    -
    STATS
    +
    MACHINE STATS
    - +
    @@ -19,7 +19,7 @@
    -
    PRODUCTION
    +
    PRODUCTION
    @@ -29,7 +29,7 @@
    -
    PARAMETERS
    +
    PARAMETERS
    @@ -39,7 +39,7 @@
    -
    ALARMS
    +
    ALARMS
    @@ -49,7 +49,7 @@
    -
    MAINTENANCE
    +
    MAINTENANCE
    @@ -59,7 +59,7 @@
    -
    TOOLS
    +
    TOOLS
    @@ -69,7 +69,7 @@
    -
    EVENT HISTORY
    +
    EVENT HISTORY
    diff --git a/MP.MONO.UI/Pages/Stats.razor b/MP.MONO.UI/Pages/MachStats.razor similarity index 65% rename from MP.MONO.UI/Pages/Stats.razor rename to MP.MONO.UI/Pages/MachStats.razor index 4097b04..94fb65e 100644 --- a/MP.MONO.UI/Pages/Stats.razor +++ b/MP.MONO.UI/Pages/MachStats.razor @@ -1,13 +1,13 @@ -@page "/Stats" +@page "/MachStats"
    -

    Stats

    +

    Machine Stats

    - +
    diff --git a/MP.MONO.UI/Shared/NavMenu.razor b/MP.MONO.UI/Shared/NavMenu.razor index 75fe493..c61feb2 100644 --- a/MP.MONO.UI/Shared/NavMenu.razor +++ b/MP.MONO.UI/Shared/NavMenu.razor @@ -16,7 +16,7 @@
    diff --git a/MachineSim/MachineSim.csproj b/MachineSim/MachineSim.csproj index de17984..82a98b7 100644 --- a/MachineSim/MachineSim.csproj +++ b/MachineSim/MachineSim.csproj @@ -21,6 +21,9 @@ + + Always + Always diff --git a/MachineSim/Program.cs b/MachineSim/Program.cs index 7ef8281..ed08d3e 100644 --- a/MachineSim/Program.cs +++ b/MachineSim/Program.cs @@ -30,11 +30,13 @@ Thread threadStatus = new Thread(simStatus); Thread threadAlarms = new Thread(simAlarms); Thread threadParams = new Thread(simParameters); Thread threadProd = new Thread(simProd); +Thread threadMachStat = new Thread(simMachStat); threadStatus.Start(); threadAlarms.Start(); threadParams.Start(); threadProd.Start(); +threadMachStat.Start(); /// /// Hash Redis contenente i dati MP di una specifico TYPE (es StatusMacchina, StateMachineIngressi, ...) @@ -105,7 +107,7 @@ void simStatus() do { // recupero uno stato simulato - var newStatus = currSimGen.MachineGetStatus(); + var newStatus = currSimGen.getStatus(); string rawData = JsonConvert.SerializeObject(newStatus); saveAndSendMessage(mHash("Machine:Status:Current"), rawData, "status", rawData); @@ -122,10 +124,27 @@ void simProd() do { // recupero uno stato simulato - var newStatus = currSimGen.MachineGetProd(); + var newStatus = currSimGen.getProd(); string rawData = JsonConvert.SerializeObject(newStatus); saveAndSendMessage(mHash("Machine:Production:Current"), rawData, "production", rawData); + // attesa random + Thread.Sleep(rand.Next(minPeriod, maxPeriod)); + } while (true); +} + +void simMachStat() +{ + int minPeriod = 3000; + int maxPeriod = 5000; + + do + { + // recupero uno stato simulato + var newVal = currSimGen.getProdStats(); + string rawData = JsonConvert.SerializeObject(newVal); + saveAndSendMessage(mHash("Machine:MachStats:Current"), rawData, "machstats", rawData); + // attesa random Thread.Sleep(rand.Next(minPeriod, maxPeriod)); } while (true); diff --git a/MachineSim/SimMachStat.json b/MachineSim/SimMachStat.json new file mode 100644 index 0000000..702cc02 --- /dev/null +++ b/MachineSim/SimMachStat.json @@ -0,0 +1,14 @@ +[ + { + "Order": 0, + "Type": "OEE-75-90", + "Title": "OEE", + "Value": "0.5", + "ValueNum": 0.5, + "MinVal": 0.4, + "MaxVal": 1, + "SimMean": 0.2, + "SimStd": 0.2, + "DisplFormat": "P1" + } +] \ No newline at end of file diff --git a/MachineSim/Simulator.cs b/MachineSim/Simulator.cs index 7380025..0932610 100644 --- a/MachineSim/Simulator.cs +++ b/MachineSim/Simulator.cs @@ -2,11 +2,6 @@ using MP.MONO.Core; using MP.MONO.Core.DTO; using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace MachineSim { @@ -15,13 +10,18 @@ namespace MachineSim /// public class Simulator { - protected string basePath = ""; - protected string paramFileName = "SimParams.json"; + #region Protected Fields + protected string basePath = ""; + protected List currSimMachStat = new List(); + protected List currSimPar = new List(); + protected string paramFileName = "SimParams.json"; protected Random rand = new Random(); - protected List? currSimPar = new List(); + #endregion Protected Fields + + #region Public Constructors public Simulator(string _basePath) { @@ -29,7 +29,11 @@ namespace MachineSim setupConfig(); } - private void setupConfig() + #endregion Public Constructors + + #region Private Methods + + private void setupConf(string paramFileName, ref List localObj) { string fullPath = Path.Combine(basePath, paramFileName); if (File.Exists(fullPath)) @@ -37,28 +41,38 @@ namespace MachineSim var rawData = File.ReadAllText(fullPath); if (!string.IsNullOrEmpty(rawData)) { - currSimPar = JsonConvert.DeserializeObject>(rawData); + localObj = JsonConvert.DeserializeObject>(rawData); } } } - /// - /// Calcola prox valore simulato dati i parametri rand configurati - /// - /// - /// - /// - /// - /// - /// - public double simNext(double CurrVal, double MinVal, double MaxVal, double sMean, double sStd) + private void setupConfig() { - double innov = Normal.Sample(sMean, sStd); - CurrVal += innov; - // verifico estremi... - CurrVal = CurrVal > MaxVal ? MaxVal : CurrVal; - CurrVal = CurrVal < MinVal ? MinVal : CurrVal; - return CurrVal; + // setup conf parametri + setupConf("SimParams.json", ref currSimPar); + // setup conf machStat + setupConf("SimMachStat.json", ref currSimMachStat); + } + + #endregion Private Methods + + #region Public Methods + + public List getAlarms() + { + List activeAlarms = new List(); + //int alarmCode = rand.Next(0, 255); + int alarmCode = rand.Next(0, 160); + // se >= 128 --> 0 (no alarm) + alarmCode = alarmCode <= 127 ? alarmCode : 0; + for (int i = 0; i < 8; i++) + { + if ((alarmCode & (1 << i)) != 0) + { + activeAlarms.Add($"Alarm {i:000}"); + } + } + return activeAlarms; } public List getParameters() @@ -134,18 +148,14 @@ namespace MachineSim Value = $"{durTCycle.Hours:00}:{durTCycle.Minutes:00}:{durTCycle.Seconds:00}", Type = "TCycle" }; - answ.Add(displ04); + answ.Add(displ04); #endif return answ; } - public ProductionDTO MachineGetProd() + public ProductionDTO getProd() { - -#if false - Random rand = new Random(); -#endif int stdCycle = 5; ProductionDTO currMachDto = new ProductionDTO() @@ -161,16 +171,38 @@ namespace MachineSim return currMachDto; } + public List getProdStats() + { + List answ = new List(); + + // genero a partire dall'elenco configurato da simulare... + answ = currSimMachStat.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 + //Value = $"{getNext(i.ValueNum, i.MinVal, i.MaxVal, i.SimMean, i.SimStd):N3}", + }).ToList(); + + foreach (var item in answ) + { + item.Value = $"{item.ValueNum.ToString(item.DisplFormat)}"; + } + + return answ; + } /// /// Restituisce stato Macchina simulato come DTO /// /// - public MachineDTO MachineGetStatus() + public MachineDTO getStatus() { -#if false - Random rand = new Random(); -#endif int maxRun = 5; int maxExe = 7; @@ -187,21 +219,25 @@ namespace MachineSim return currMachDto; } - public List getAlarms() + /// + /// Calcola prox valore simulato dati i parametri rand configurati + /// + /// + /// + /// + /// + /// + /// + public double simNext(double CurrVal, double MinVal, double MaxVal, double sMean, double sStd) { - List activeAlarms = new List(); - //int alarmCode = rand.Next(0, 255); - int alarmCode = rand.Next(0, 160); - // se >= 128 --> 0 (no alarm) - alarmCode = alarmCode <= 127 ? alarmCode : 0; - for (int i = 0; i < 8; i++) - { - if ((alarmCode & (1 << i)) != 0) - { - activeAlarms.Add($"Alarm {i:000}"); - } - } - return activeAlarms; + double innov = Normal.Sample(sMean, sStd); + CurrVal += innov; + // verifico estremi... + CurrVal = CurrVal > MaxVal ? MaxVal : CurrVal; + CurrVal = CurrVal < MinVal ? MinVal : CurrVal; + return CurrVal; } + + #endregion Public Methods } -} +} \ No newline at end of file