From 9b250c5385ea13aeb8991fa2a81bf71f17262d03 Mon Sep 17 00:00:00 2001 From: lumapu Date: Tue, 15 Aug 2023 02:35:31 +0200 Subject: [PATCH] 0.7.33 * add alarms overview to WebGui #608 * fix webGui total values #1084 --- src/CHANGES.md | 4 ++ src/defines.h | 2 +- src/hms/hmsRadio.h | 4 +- src/web/RestApi.h | 6 ++- src/web/html/api.js | 30 ++++++++++++++ src/web/html/style.css | 72 +++++++++++++++++++++++++++++++++ src/web/html/visualization.html | 35 +++++++++++++++- 7 files changed, 146 insertions(+), 7 deletions(-) diff --git a/src/CHANGES.md b/src/CHANGES.md index dc428fe3e..17cb5243d 100644 --- a/src/CHANGES.md +++ b/src/CHANGES.md @@ -1,5 +1,9 @@ # Development Changes +## 0.7.33 - 2023-08-15 +* add alarms overview to WebGui #608 +* fix webGui total values #1084 + ## 0.7.32 - 2023-08-14 * fix colors of live view #1091 diff --git a/src/defines.h b/src/defines.h index 7ce144f21..c9af16435 100644 --- a/src/defines.h +++ b/src/defines.h @@ -13,7 +13,7 @@ //------------------------------------- #define VERSION_MAJOR 0 #define VERSION_MINOR 7 -#define VERSION_PATCH 32 +#define VERSION_PATCH 33 //------------------------------------- typedef struct { diff --git a/src/hms/hmsRadio.h b/src/hms/hmsRadio.h index eaf063284..dc79afcba 100644 --- a/src/hms/hmsRadio.h +++ b/src/hms/hmsRadio.h @@ -98,10 +98,10 @@ class CmtRadio { initPacket(ivId, reqfld, ALL_FRAMES); mTxBuf[10] = cmd; CP_U32_LittleEndian(&mTxBuf[12], ts); - if (cmd == AlarmData ) { //cmd == RealTimeRunData_Debug || + /*if (cmd == AlarmData ) { //cmd == RealTimeRunData_Debug || mTxBuf[18] = (alarmMesId >> 8) & 0xff; mTxBuf[19] = (alarmMesId ) & 0xff; - } + }*/ sendPacket(24, isRetransmit); } diff --git a/src/web/RestApi.h b/src/web/RestApi.h index 34918dc9e..861e8994f 100644 --- a/src/web/RestApi.h +++ b/src/web/RestApi.h @@ -366,6 +366,7 @@ class RestApi { obj[F("ts_last_success")] = rec->ts; obj[F("generation")] = iv->ivGen; obj[F("status")] = (uint8_t)iv->status; + obj[F("alarm_cnt")] = iv->alarmCnt; JsonArray ch = obj.createNestedArray("ch"); @@ -406,8 +407,9 @@ class RestApi { record_t<> *rec = iv->getRecordStruct(RealTimeRunData_Debug); - obj["cnt"] = iv->alarmCnt; - obj["last_id"] = iv->getChannelFieldValue(CH0, FLD_EVT, rec); + obj[F("iv_id")] = id; + obj[F("cnt")] = iv->alarmCnt; + obj[F("last_id")] = iv->getChannelFieldValue(CH0, FLD_EVT, rec); JsonArray alarm = obj.createNestedArray(F("alarm")); for(uint8_t i = 0; i < 10; i++) { diff --git a/src/web/html/api.js b/src/web/html/api.js index 917b1f700..1548190c4 100644 --- a/src/web/html/api.js +++ b/src/web/html/api.js @@ -126,6 +126,10 @@ function toIsoDateStr(d) { return new Date(d.getTime() + (d.getTimezoneOffset() * -60000)).toISOString().substring(0, 19).replace('T', ', '); } +function toIsoTimeStr(d) { + return new Date(d.getTime() + (d.getTimezoneOffset() * -60000)).toISOString().substring(11, 19).replace('T', ', '); +} + function setHide(id, hide) { var elm = document.getElementById(id); if(hide) { @@ -272,3 +276,29 @@ function svg(data=null, w=24, h=24, cl=null, tooltip=null) { } return s; } + +function modal(title, body) { + if(null == document.getElementById("modal")) { + document.getElementById("wrapper").append( + ml("div", {id: "modal-wrapper", class: "modal", onclick: modalClose}), + ml("div", {id: "modal", class: "modal"}, + ml("div", {class: "modal-content"}, [ + ml("div", {class: "modal-header"}, [ + ml("h5", {}, title), + ml("button", {class: "close", type: "button", onclick: modalClose}, "×") + ]), + ml("div", {class: "modal-body"}, body) + ] + ) + ) + ); + } +} + +function modalClose() { + var e = document.getElementById("modal"); + if(null != e) { + e.remove(); + document.getElementById("modal-wrapper").remove(); + } +} diff --git a/src/web/html/style.css b/src/web/html/style.css index f4fda4271..1b7940188 100644 --- a/src/web/html/style.css +++ b/src/web/html/style.css @@ -651,3 +651,75 @@ div.hr { margin-left: -5px; transform: translate(0,0px); } + +#modal { + max-width: 700px; + margin: 1.75rem auto; +} + +.modal { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 1072; + display: block; +} + +#modal-wrapper { + background-color: #000; + opacity: 0.5; + bottom: 0; +} + +.modal-content { + border-radius: .3rem; + position: relative; + display: flex; + width: 100%; + background-color: var(--nav-active); + background-clip: padding-box; + border: 1px solid rgba(0,0,0,.2); + flex-direction: column; +} + +.modal-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + padding: 1rem; + border-bottom: 1px solid #e9ecef; +} + +.modal-header .close { + padding: 0.7rem; + margin: -1rem -1rem -1rem auto; +} + +.modal-body { + padding: 1rem 1rem 2rem 1rem; +} + +.close { + font-size: 2rem; + opacity: 0.5; + font-family: inherit; + cursor: pointer; + padding: 0; +} + +button.close { + background-color: transparent; + border: 0; +} + +h5 { + font-size: 1.25rem; + margin-top: 0; + margin-bottom: 0.5rem; + font-weight: 500; +} + +.pointer { + cursor: pointer; +} diff --git a/src/web/html/visualization.html b/src/web/html/visualization.html index 81b63b5a4..f207f68cf 100644 --- a/src/web/html/visualization.html +++ b/src/web/html/visualization.html @@ -89,11 +89,12 @@ function ivHead(obj) { if(0 != obj.status) { // only add totals if inverter is online total[0] += obj.ch[0][2]; // P_AC - total[1] += obj.ch[0][7]; // YieldDay - total[2] += obj.ch[0][6]; // YieldTotal total[3] += obj.ch[0][8]; // P_DC total[4] += obj.ch[0][10]; // Q_AC } + total[1] += obj.ch[0][7]; // YieldDay + total[2] += obj.ch[0][6]; // YieldTotal + var t = span(" °C"); var clh = (0 == obj.status) ? "iv-h-dis" : "iv-h"; var clbg = (0 == obj.status) ? "iv-bg-dis" : "iv-bg"; @@ -103,6 +104,9 @@ ml("div", {class: "row"}, [ ml("div", {class: "col mx-2 mx-md-1"}, obj.name), ml("div", {class: "col a-c"}, "Power limit " + ((obj.power_limit_read == 65535) ? "n/a" : (obj.power_limit_read + " %"))), + ml("div", {class: "col a-c"}, ml("span", { class: "pointer", onclick: function() { + getAjax("/api/inverter/alarm/" + obj.id, parseIvAlarm); + }}, ("Alarms: " + obj.alarm_cnt))), ml("div", {class: "col a-r mx-2 mx-md-1"}, String(obj.ch[0][5]) + t.innerText) ]) ), @@ -200,6 +204,7 @@ ]) ); + var last = true; for(var i = obj.id + 1; i < ivEn.length; i++) { if((i != ivEn.length) && ivEn[i]) { @@ -215,6 +220,32 @@ } } + function parseIvAlarm(obj) { + var html = []; + html.push( + ml("div", {class: "row"}, [ + ml("div", {class: "col"}, ml("strong", {}, "String")), + ml("div", {class: "col"}, ml("strong", {}, "ID")), + ml("div", {class: "col"}, ml("strong", {}, "Start")), + ml("div", {class: "col"}, ml("strong", {}, "End")) + ]) + ); + + for(a of obj.alarm) { + if(a.code != 0) { + html.push( + ml("div", {class: "row"}, [ + ml("div", {class: "col mt-3"}, String(a.str)), + ml("div", {class: "col mt-3"}, String(a.code)), + ml("div", {class: "col mt-3"}, String(toIsoTimeStr(new Date(a.start * 1000)))), + ml("div", {class: "col mt-3"}, String(toIsoTimeStr(new Date(a.end * 1000)))) + ]) + ); + } + } + modal("Alarms of inverter #" + obj.iv_id, ml("div", {}, html)); + } + function parse(obj) { if(null != obj) { parseGeneric(obj["generic"]);