diff --git a/Sviluppo_MP_MON.md b/Sviluppo_MP_MON.md new file mode 100644 index 00000000..e3c98cd4 --- /dev/null +++ b/Sviluppo_MP_MON.md @@ -0,0 +1,401 @@ +# Appunti sviluppo + +Appunti vari sviluppo progetto MAPO + +## MP/MON + +Attualmente è un applicazione MVC asp.net c#, NON interattiva (display distribuiti stato produzione), effettua refresh timer-based. + +NON ottimizzata (per diminuire le chiamate) e genera traffico e carico sul server + +Parzialmente mitigato il carico su server con + +- caching tramite redis dei dati elaborati +- ottimizzaizone stored +- caching a livello DB dei dati x stored + +### Obiettivi + +Si prefigge di migliorare l'applicazione per 2 motivi + +- performances +- reattività (logica push e non pull) +- semplificazione del metodo di peronalizzazione dei dati mostrati ai singoli clienti + +Per i primi 2 punti si intende lavorare con un prototipo VUE.JS / REACT con cui valutare un approccio differente per l'applicazione che preveda di pubblicare, in modalità push dal server, i dati in modo che siano aggiornati sul client AL MOMENTO DELLA PRODUZIONE degli stessi (o nel minor tempo possibile/col minor carico possibile sul server) + +Si intendeo fornire i dati (push o pull) tramite un a api REST cehceh alla chiamata fornisca un traccaito di TUTTI i valori di tutte le macchine (o in alternativa dell'unica macchina richiesta,a seconda del VERB usato) + +A livello di configurazione, si vuole passare dall'attuale datamodel "tipizzato" in cui ogni variabile è indicata con il nome esatto proveniente dalla abse dati ad un insieme id variabili indicate da un dizionario KVP (chiave/valore) in cui l'oggetto della view da mostrare utilizzerà dei generici segnaposti (es: da NumPezzi --> label02) e a livello di configurazione backend, tramite LUT (lookupTable) andrà a mappare, per il singolo cliente, valori e label desiderate (tramite un file json serializzato sul DB, personalizzabile per SINGOLA MACCHINA) + +### WebAPI recupero dati + +Per il recupero dei dati di una SINGOLA macchina si intende impiegare il seguente metodo: + +``` +CALL: http://{server_url}/MSE/getData/{cod_macchina} +``` + +che fornirà in risposta una stringa JSon (per singola macchina): + +``` +[{ + "RowNum": 1, + "lastUpdate": "2019-04-03T18:33:14.24", + "IdxMacchina": "SIM_DP_01", + "CodMacchina": "SIMDP1", + "Nome": "IOB SimDP1", + "url": "Steamware.png", + "idxODL": 2208, + "CodArticolo": "027309", + "NumPezzi": 500, + "TCAssegnato": 1.08300000, + "DataInizioODL": "2019-03-25T18:41:36.657", + "Semaforo": "sVe", + "idxStato": 13, + "DescrizioneStato": "lavorazione", + "durata": 557.0, + "PezziProd": 20956, + "PezziConf": 0, + "TempoOn": 0.00000000, + "TempoAuto": 0.00000000, + "TempoRun": 0.00000000, + "TCMedio": 0.00000000, + "TCLav": 0.00000000, + "TCEff": 0.00000000, + "TCMedioRT": 0.00000000, + "TCLavRT": 0.00000000, + "TCEffRT": 0.00000000, + "Disegno": "" +}] +``` +--- + +Per il recupero dei dati si intende impiegare il seguente metodo (per ottenere TUTTE le macchine): + +``` +CALL: http://{server_url}/MSE/getData +``` + +che fornirà in risposta una stringa JSon di tipo array: + +``` +[{ + "RowNum": 1, + "lastUpdate": "2019-04-03T18:33:14.24", + "IdxMacchina": "SIM_DP_01", + "CodMacchina": "SIMDP1", + "Nome": "IOB SimDP1", + "url": "Steamware.png", + "idxODL": 2208, + "CodArticolo": "027309", + "NumPezzi": 500, + "TCAssegnato": 1.08300000, + "DataInizioODL": "2019-03-25T18:41:36.657", + "Semaforo": "sVe", + "idxStato": 13, + "DescrizioneStato": "lavorazione", + "durata": 557.0, + "PezziProd": 20956, + "PezziConf": 0, + "TempoOn": 0.00000000, + "TempoAuto": 0.00000000, + "TempoRun": 0.00000000, + "TCMedio": 0.00000000, + "TCLav": 0.00000000, + "TCEff": 0.00000000, + "TCMedioRT": 0.00000000, + "TCLavRT": 0.00000000, + "TCEffRT": 0.00000000, + "Disegno": "" +}, { + "RowNum": 2, + "lastUpdate": "2019-04-03T18:33:50.167", + "IdxMacchina": "SIM_DP_02", + "CodMacchina": "SIMDP2", + "Nome": "IOB SimDP2", + "url": "Steamware.png", + "idxODL": 2211, + "CodArticolo": "005123", + "NumPezzi": 100000, + "TCAssegnato": 1.00000000, + "DataInizioODL": "2019-03-25T18:44:37.3", + "Semaforo": "sRo", + "idxStato": 15, + "DescrizioneStato": "allarme CN", + "durata": 547.0, + "PezziProd": 24151, + "PezziConf": 1954, + "TempoOn": 0.00000000, + "TempoAuto": 0.00000000, + "TempoRun": 0.00000000, + "TCMedio": 0.00000000, + "TCLav": 0.00000000, + "TCEff": 0.00000000, + "TCMedioRT": 0.00000000, + "TCLavRT": 0.00000000, + "TCEffRT": 0.00000000, + "Disegno": "" +}, { + "RowNum": 3, + "lastUpdate": "2019-04-03T18:33:28.75", + "IdxMacchina": "SIMUL_01", + "CodMacchina": "SIM05", + "Nome": "IOB SIM 01", + "url": "Steamware.png", + "idxODL": 2220, + "CodArticolo": "020293", + "NumPezzi": 15000, + "TCAssegnato": 0.00000000, + "DataInizioODL": "2019-03-25T18:54:57.877", + "Semaforo": "sVe", + "idxStato": 13, + "DescrizioneStato": "lavorazione", + "durata": 568.0, + "PezziProd": 63929, + "PezziConf": 0, + "TempoOn": 0.00000000, + "TempoAuto": 0.00000000, + "TempoRun": 0.00000000, + "TCMedio": 0.00000000, + "TCLav": 0.00000000, + "TCEff": 0.00000000, + "TCMedioRT": 0.18630215, + "TCLavRT": 0.18499994, + "TCEffRT": 0.00000000, + "Disegno": "179L1000" +}] +``` + + +### Attuale struttura pagina SINGOLA macchina + +Ogni singolo impianto è attualmente mostrato con una pagina razor + +- che si adatta alla larghezza dello schermo +- che permette di specificare il NUM MAX di colonne da visualizzare tra 1 e 6 +- che utilizza un criterio di flashing (tramite 2 css alternati ogni secondo quando il colore NON E' verde) + +... così composta: + +``` javascript + +@model IEnumerable + +
+ + @{ + // salvo variabili num blocchi x riga + int numBlock = 0; + int maxCol = 6; + try + { + maxCol = ViewBag.maxCol; + } + catch + { + maxCol = 6; + } + if (maxCol == 0) + { + maxCol = 6; + } + } + + + @foreach (var item in Model) + { + // fix codice semaforo: sVe -> Ve, sRo ->Ro... + string codSemaf = item.Semaforo; + if (codSemaf.Length == 3) + { + codSemaf = codSemaf.Substring(1, 2); + } + string cssStatus = ViewBag.baseCss + codSemaf; + // calcolo durata... + TimeSpan TCAss = TimeSpan.FromMinutes((double)item.TCAssegnato); + TimeSpan TCLav = TimeSpan.FromMinutes((double)item.TCLavRT); + // converto a stringa! + string TCAssegnato = TCAss.ToString(@"mm\:ss"); + string TCLavorato = TCLav.ToString(@"mm\:ss"); + + + // verifico se mostrare articolo o disegno... + string sArticolo = ""; + if (SteamWare.memLayer.ML.CRS("sART") == "CodArticolo") + { + sArticolo = item.CodArticolo; + } + else + { + sArticolo = item.Disegno; + } + // se fosse vuoto mostro cmq codArt tra parentesi... + if (sArticolo == "") + { + sArticolo = string.Format("[{0}]", item.CodArticolo); + } + // se NON trova update da oltre "keepAliveMin" / 2 minuti rosso lo status comunicazione + string cssComStatus = cssStatus; + string showComErr = "invisible"; + if (DateTime.Now.Subtract((DateTime)item.lastUpdate).TotalSeconds > SteamWare.memLayer.ML.CRI("keepAliveMin") * 60 / 2) + { + cssComStatus = ViewBag.baseCss + "Ro"; + showComErr = "visible"; + } + // verifico SE è disabilitata modalità animazione -> blink a stati (e refresh 1s) + if (SteamWare.memLayer.ML.CRS("doAnimate") == "1") + { + // blink se secondo pari... + DateTime adesso = DateTime.Now; + int resto = 0; + Math.DivRem(adesso.Second, 2, out resto); + if (resto == 0) + { + cssStatus += "_b"; + if (cssComStatus.EndsWith("Ro")) + { + cssComStatus += "_b"; + } + } + } +
+
+
+
+
@Html.DisplayFor(modelItem => item.Nome)
+
+
+
+
Art.
+
@sArticolo
+
+
+
@Html.DisplayFor(modelItem => item.DescrizioneStato)
+
@item.durata'
+ @*
OEE
+
xx%
*@ +
T.Ciclo
+
std: @TCAssegnato
+
act: @TCLavorato
+
Pezzi(prod/ord)
+
@Html.DisplayFor(modelItem => item.PezziProd) / @Html.DisplayFor(modelItem => item.NumPezzi)
+
+
+
+
+
+ +
+
+
+
+ // controllo se ho resto zero --> uso NUOVA riga... + if ((numBlock % maxCol) == maxCol - 1) + { + @Html.Raw("
"); + } + // incremento contatore + numBlock++; + } + @{ + // controllo se NON SONO arrivao in fondo --> aggiungo blocchi! + int currNum = (numBlock % maxCol); + while (currNum < (maxCol)) + { + @Html.Raw("
aaa
"); + currNum++; + } + } +
+``` + +con il seguente estratto css + +``` css + +/* area semafori*/ +.semBlinkVe, +.semFixVe, +.semFixVe_b, +.semVe, +.semVe_b { + background: #009036; + background: rgba(0,255,80,.6); + color: #FFFFAA; +} + +.semBlinkGr, +.semFixGr, +.semFixGr_b, +.semGr, +.semGr_b { + background-color: #bcbcbc; + background: rgba(180,180,180,.6); +} + +.semGi { + text-align: left; + background: #8a8d27; + background: rgba(230,210,0,.6); + padding: 0px 4px 0px 4px; + color: #000; +} + +.semGi_b, +.semFixGi, +.semFixGi_b { + text-align: left; + background: #f9ff18; + background: rgba(255,255,0,.8); + padding: 0px 4px 0px 4px; + color: #333; +} + +.semBl { + text-align: left; + background: #000E7A; + background: rgba(0,5,200,.6); + padding: 0px 4px 0px 4px; + color: #959500; +} + +.semBl_b, +.semFixBl, +.semFixBl_b { + text-align: left; + background: #243FFF; + background: rgba(60,80,255,.8); + padding: 0px 4px 0px 4px; + color: #ffff32; +} + +.semRo { + text-align: left; + background-color: #7a000e; + background: rgba(200,0,5,.6); + padding: 0px 4px 0px 4px; + color: #959500; +} + +.semRo_b, +.semFixRo, +.semFixRo_b { + text-align: left; + background-color: #ff243f; + background: rgba(255,60,80,.8); + padding: 0px 4px 0px 4px; + color: #ffff32; +} + + +``` \ No newline at end of file diff --git a/Sviluppo_MP_MON.pdf b/Sviluppo_MP_MON.pdf new file mode 100644 index 00000000..5f91cbb9 Binary files /dev/null and b/Sviluppo_MP_MON.pdf differ