From 15e390b6933cedc40247ccaf4275f855e600afa2 Mon Sep 17 00:00:00 2001 From: Dejan R Date: Sun, 19 Apr 2026 09:22:16 +0200 Subject: [PATCH] added digital gauge and config for disable/enable it --- main.go | 142 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 99 insertions(+), 43 deletions(-) diff --git a/main.go b/main.go index 4e2e58e..b6fb4cc 100644 --- a/main.go +++ b/main.go @@ -30,7 +30,7 @@ import ( //go:embed static var staticFiles embed.FS -const version = "0.8.1" +const version = "0.8.2" // --------------------------------------------------------------------------- // Config structs @@ -100,6 +100,7 @@ type ModulesConfig struct { ShowIntelligence *bool `yaml:"show_intelligence,omitempty"` ShowAlarmTimeline *bool `yaml:"show_alarm_timeline,omitempty"` ShowGauges *bool `yaml:"show_gauges,omitempty"` + ShowGaugeDigital *bool `yaml:"show_gauge_digital,omitempty"` ShowTrendChart *bool `yaml:"show_trend_chart,omitempty"` } @@ -171,6 +172,7 @@ func defaultConfig() Config { ShowIntelligence: boolPtr(true), ShowAlarmTimeline: boolPtr(true), ShowGauges: boolPtr(true), + ShowGaugeDigital: boolPtr(false), ShowTrendChart: boolPtr(true), }, DB: DBConfig{ @@ -272,6 +274,7 @@ func normalizeConfig(cfg *Config) { setIfNilBool(&cfg.Modules.ShowIntelligence, boolValue(def.Modules.ShowIntelligence, true)) setIfNilBool(&cfg.Modules.ShowAlarmTimeline, boolValue(def.Modules.ShowAlarmTimeline, true)) setIfNilBool(&cfg.Modules.ShowGauges, boolValue(def.Modules.ShowGauges, true)) + setIfNilBool(&cfg.Modules.ShowGaugeDigital, boolValue(def.Modules.ShowGaugeDigital, false)) setIfNilBool(&cfg.Modules.ShowTrendChart, boolValue(def.Modules.ShowTrendChart, true)) setIfEmpty(&cfg.DB.Path, def.DB.Path) @@ -443,6 +446,7 @@ type PageData struct { ShowIntelligence bool ShowAlarmTimeline bool ShowGauges bool + ShowGaugeDigital bool ShowTrendChart bool } @@ -1608,6 +1612,7 @@ func initCachedUI() { ShowIntelligence: boolValue(cfg.Modules.ShowIntelligence, true), ShowAlarmTimeline: boolValue(cfg.Modules.ShowAlarmTimeline, true), ShowGauges: boolValue(cfg.Modules.ShowGauges, true), + ShowGaugeDigital: boolValue(cfg.Modules.ShowGaugeDigital, false), ShowTrendChart: boolValue(cfg.Modules.ShowTrendChart, true), } @@ -1857,14 +1862,60 @@ const uiHTML = ` .soft-glow-yellow { box-shadow: 0 0 0 1px rgba(234,179,8,0.28), 0 0 38px rgba(234,179,8,0.08); } .soft-glow-red { box-shadow: 0 0 0 1px rgba(239,68,68,0.28), 0 0 38px rgba(239,68,68,0.08); } + .gauge-header-row { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 24px; + margin-bottom: 10px; + } + + .gauge-head { + display: flex; + align-items: center; + justify-content: center; + gap: 16px; + text-align: center; + margin-bottom: 10px; + } + + .gauge-head.with-digital { + justify-content: flex-start; + text-align: left; + margin-bottom: 0; + } + + .gauge-head-copy { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + } + + .gauge-head-copy.with-digital { + align-items: flex-start; + } + + .gauge-digital { + text-align: right; + flex-shrink: 0; + } + .gauge-container { position: relative; width: 100%; - max-width: 500px; - height: 360px; + max-width: 720px; margin: 0 auto; } + .gauge-container.no-digital { + height: clamp(430px, 48vw, 560px); + } + + .gauge-container.with-digital { + height: clamp(360px, 42vw, 500px); + } + .gauge-canvas { width: 100%; height: 100%; @@ -2296,46 +2347,66 @@ const uiHTML = ` {{if .ShowGauges}}
-
-
-
+
+ {{if .ShowGaugeDigital}} +
+
-
+

{{.LeftLabel}}

NORMAL
-
+
0.0
{{.UnitPct}}
0.0 {{.UnitForce}}
+ {{else}} +
+
+
+

{{.LeftLabel}}

+
NORMAL
+
+
+ {{end}} -
+
-
-
-
+
+ {{if .ShowGaugeDigital}} +
+
-
+

{{.RightLabel}}

NORMAL
-
+
0.0
{{.UnitPct}}
0.0 {{.UnitForce}}
+ {{else}} +
+
+
+

{{.RightLabel}}

+
NORMAL
+
+
+ {{end}} -
+
@@ -2394,6 +2465,7 @@ const uiHTML = ` const SHOW_INTELLIGENCE = {{if .ShowIntelligence}}true{{else}}false{{end}}; const SHOW_ALARM_TIMELINE = {{if .ShowAlarmTimeline}}true{{else}}false{{end}}; const SHOW_GAUGES = {{if .ShowGauges}}true{{else}}false{{end}}; + const SHOW_GAUGE_DIGITAL = {{if .ShowGaugeDigital}}true{{else}}false{{end}}; const SHOW_TREND_CHART = {{if .ShowTrendChart}}true{{else}}false{{end}}; const START_ANGLE = Math.PI * 0.75; @@ -2429,11 +2501,6 @@ const uiHTML = ` if (el) el.textContent = text; } - function setTextBySelector(selector, text) { - const el = document.querySelector(selector); - if (el) el.textContent = text; - } - function colorMix(c1, c2, t) { return { r: Math.round(lerp(c1.r, c2.r, t)), @@ -2530,18 +2597,18 @@ const uiHTML = ` const light = isLightTheme(); const cx = w / 2; - const cy = h * 0.57; - const radius = Math.min(w, h) * 0.34; - const trackWidth = Math.max(18, radius * 0.16); + const radius = Math.min(w * 0.35, h * 0.42); + const cy = h * 0.58; + const trackWidth = Math.max(20, radius * 0.17); const value = clamp(Number(percentValue) || 0, 0, GAUGE_MAX_PERCENT); const valueAngle = valueToAngle(value); ctx.save(); ctx.beginPath(); - ctx.arc(cx, cy, radius + 22, 0, Math.PI * 2); + ctx.arc(cx, cy, radius + 24, 0, Math.PI * 2); ctx.fillStyle = light ? 'rgba(15,23,42,0.04)' : 'rgba(255,255,255,0.015)'; ctx.shadowColor = light ? 'rgba(15,23,42,0.12)' : 'rgba(0,0,0,0.45)'; - ctx.shadowBlur = 30; + ctx.shadowBlur = 32; ctx.fill(); ctx.restore(); @@ -2632,9 +2699,9 @@ const uiHTML = ` ctx.stroke(); const valueText = value.toFixed(1); - let valueFontPx = 52; - if (value >= 100) valueFontPx = 46; - if (w < 420) valueFontPx -= 4; + let valueFontPx = 58; + if (value >= 100) valueFontPx = 50; + if (w < 420) valueFontPx -= 6; ctx.textAlign = 'center'; ctx.textBaseline = 'middle'; @@ -2644,12 +2711,12 @@ const uiHTML = ` ctx.fillText(valueText, cx, cy - 6); ctx.fillStyle = sideAccent; - ctx.font = '700 18px system-ui, sans-serif'; - ctx.fillText(UNIT_PCT, cx, cy + 28); + ctx.font = '700 19px system-ui, sans-serif'; + ctx.fillText(UNIT_PCT, cx, cy + 30); ctx.fillStyle = light ? '#334155' : '#a1a1aa'; - ctx.font = '600 16px system-ui, sans-serif'; - ctx.fillText((Number(knValue) || 0).toFixed(1) + ' ' + UNIT_FORCE, cx, cy + 54); + ctx.font = '600 17px system-ui, sans-serif'; + ctx.fillText((Number(knValue) || 0).toFixed(1) + ' ' + UNIT_FORCE, cx, cy + 58); } function getZone(percentValue) { @@ -2664,8 +2731,6 @@ const uiHTML = ` return 'ok'; } - - function setProcessVisualState(connected) { const el = document.getElementById('process-content'); if (!el) return; @@ -3051,8 +3116,6 @@ const uiHTML = ` const connected = !!d.connected; const leftPercent = Number(d.sila_l) || 0; const rightPercent = Number(d.sila_r) || 0; - const leftKN = Number(d.sila_l_kn) || 0; - const rightKN = Number(d.sila_r_kn) || 0; const sumPercent = Number(d.sum_percent) || 0; const sumKN = Number(d.sum_kn) || 0; const imbalance = Number(d.imbalance_percent) || 0; @@ -3069,13 +3132,6 @@ const uiHTML = ` setConnectionIndicator(connected, stale); setProcessVisualState(connected && !stale); - if (SHOW_GAUGES) { - setTextBySelector('#digital-l .percent', leftPercent.toFixed(1)); - setTextBySelector('#digital-l .kn', leftKN.toFixed(1) + ' ' + UNIT_FORCE); - setTextBySelector('#digital-r .percent', rightPercent.toFixed(1)); - setTextBySelector('#digital-r .kn', rightKN.toFixed(1) + ' ' + UNIT_FORCE); - } - if (SHOW_OVERVIEW) { setTextById('sum-percent', sumPercent.toFixed(1)); setTextById('sum-kn', sumKN.toFixed(1));