From 2d8ec835c6de4fdad394626034f14ddb161ed1f2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thomas=20M=C3=BCller?= Date: Thu, 14 May 2026 07:34:59 +0200 Subject: [PATCH] =?UTF-8?q?Eing=C3=A4nge=20werden=20angezeigt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dist/sternwarte-card.js | 188 +++++++++++++++--- .../custom_components/sternwarte/sensor.py | 6 + 2 files changed, 171 insertions(+), 23 deletions(-) diff --git a/sternwarte-homeassistant-card/dist/sternwarte-card.js b/sternwarte-homeassistant-card/dist/sternwarte-card.js index 7d685ac..771daf6 100644 --- a/sternwarte-homeassistant-card/dist/sternwarte-card.js +++ b/sternwarte-homeassistant-card/dist/sternwarte-card.js @@ -70,14 +70,14 @@ class SternwarteCard extends HTMLElement { } getCardSize() { - return 8; + return 10; } getGridOptions() { return { - rows: 8, + rows: 10, columns: 18, - min_rows: 7, + min_rows: 9, }; } @@ -420,6 +420,35 @@ class SternwarteCard extends HTMLElement { return "unknown"; } + _inputPanelStates() { + const roofStatus = this._state(this.config.roofStatus); + const rawInputs = Array.isArray(roofStatus?.attributes?.inputs) + ? roofStatus.attributes.inputs + : []; + const knownInputs = { + 7: { label: "Regen", entityId: this.config.rain, accent: "warn" }, + 9: { label: "Dach bewegt", entityId: this.config.roofMoving, accent: "motion" }, + 10: { label: "Dach zu", entityId: this.config.roofClosed, accent: "ok" }, + 11: { label: "Dach offen", entityId: this.config.roofOpen, accent: "ok" }, + }; + + return Array.from({ length: 12 }, (_, index) => { + const known = knownInputs[index] || {}; + const entityState = known.entityId ? this._state(known.entityId) : null; + const rawValue = typeof rawInputs[index] === "boolean" ? rawInputs[index] : null; + const entityValue = entityState?.state === "on" ? true : entityState?.state === "off" ? false : null; + const on = rawValue ?? entityValue; + + return { + key: `input-${index}`, + label: known.label || "", + shortLabel: `IN ${index}`, + accent: known.accent || "neutral", + on, + }; + }); + } + _windIndicatorState() { const wind = this._state(this.config.wind); const value = Number(wind?.state); @@ -770,7 +799,6 @@ class SternwarteCard extends HTMLElement { const powerEntityId = this._powerEntityId(); const powerIndicatorClassName = this._powerIndicatorClassName(); - const rain = this._state(this.config.rain); const openScheduleEntityId = this._scheduleOpenEntityId(); const closeScheduleEntityId = this._scheduleCloseEntityId(); const openSchedule = this._state(openScheduleEntityId); @@ -787,7 +815,7 @@ class SternwarteCard extends HTMLElement { } const roofPosition = this._roofPositionValue(); const windIndicator = this._windIndicatorState(); - const rainOn = rain?.state === "on"; + const inputPanelStates = this._inputPanelStates(); const movingOn = this._state(this.config.roofMoving)?.state === "on"; const openOn = this._state(this.config.roofOpen)?.state === "on"; const closedOn = this._state(this.config.roofClosed)?.state === "on"; @@ -881,22 +909,6 @@ class SternwarteCard extends HTMLElement { font-size: 13px; opacity: 0.78; } - .alert { - border-radius: 14px; - padding: 12px 14px; - border: 1px solid rgba(198, 40, 40, 0.35); - background: linear-gradient(180deg, rgba(198, 40, 40, 0.18), rgba(198, 40, 40, 0.08)); - color: var(--primary-text-color); - font-size: 14px; - font-weight: 600; - } - .alert-sub { - display: block; - margin-top: 4px; - font-size: 12px; - font-weight: 400; - opacity: 0.82; - } .stats { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); @@ -1221,6 +1233,115 @@ class SternwarteCard extends HTMLElement { background: rgba(255,255,255,0.04); border: 1px solid rgba(255,255,255,0.08); } + .input-panel { + position: relative; + border-radius: 16px; + padding: 7px; + border: 1px solid rgba(120, 220, 255, 0.18); + background: + radial-gradient(circle at top, rgba(120, 220, 255, 0.12), transparent 42%), + linear-gradient(180deg, rgba(7, 16, 18, 0.98), rgba(3, 8, 10, 0.96)); + box-shadow: + inset 0 1px 0 rgba(255,255,255,0.06), + inset 0 -14px 28px rgba(0,0,0,0.35), + 0 10px 24px rgba(0,0,0,0.18); + } + .input-panel::before { + content: ""; + position: absolute; + inset: 5px; + border-radius: 10px; + border: 1px solid rgba(255,255,255,0.035); + pointer-events: none; + } + .input-panel-grid { + display: grid; + grid-template-columns: repeat(12, minmax(0, 1fr)); + gap: 4px; + } + .input-led { + position: relative; + display: grid; + grid-template-columns: 1fr; + grid-template-rows: 8px 1fr; + gap: 1px; + align-items: center; + justify-items: center; + padding: 2px; + aspect-ratio: 1 / 1; + min-height: 28px; + border-radius: 4px; + border: 1px solid rgba(255,255,255,0.06); + background: + linear-gradient(180deg, rgba(255,255,255,0.05), rgba(255,255,255,0.01)), + rgba(0,0,0,0.26); + } + .input-led.warn.is-on { + border-color: rgba(255, 96, 96, 0.38); + background: + linear-gradient(180deg, rgba(255, 96, 96, 0.16), rgba(255, 96, 96, 0.04)), + rgba(0,0,0,0.28); + } + .input-led.ok.is-on, + .input-led.motion.is-on, + .input-led.neutral.is-on { + border-color: rgba(120, 255, 180, 0.28); + background: + linear-gradient(180deg, rgba(120, 255, 180, 0.14), rgba(120, 255, 180, 0.04)), + rgba(0,0,0,0.28); + } + .input-led-light { + width: 7px; + height: 7px; + border-radius: 50%; + background: #162126; + border: 1px solid rgba(255,255,255,0.14); + box-shadow: + inset 0 1px 2px rgba(255,255,255,0.08), + inset 0 -2px 4px rgba(0,0,0,0.45); + } + .input-led.is-on .input-led-light { + background: #78ffb4; + border-color: rgba(210,255,230,0.9); + box-shadow: + 0 0 12px rgba(120,255,180,0.8), + 0 0 24px rgba(120,255,180,0.42), + inset 0 0 4px rgba(255,255,255,0.55); + } + .input-led.warn.is-on .input-led-light { + background: #ff6767; + border-color: rgba(255, 220, 220, 0.95); + box-shadow: + 0 0 12px rgba(255, 96, 96, 0.82), + 0 0 24px rgba(255, 96, 96, 0.46), + inset 0 0 4px rgba(255,255,255,0.5); + } + .input-led.is-unknown .input-led-light { + background: #49545a; + border-color: rgba(255,255,255,0.18); + box-shadow: + inset 0 0 4px rgba(255,255,255,0.08); + } + .input-led-meta { + min-width: 0; + align-self: center; + text-align: center; + } + .input-led-index { + display: block; + font-size: 7px; + line-height: 1; + font-weight: 700; + opacity: 0.92; + } + .input-led-state { + display: block; + margin-top: 1px; + font-size: 0; + letter-spacing: 0; + text-transform: uppercase; + opacity: 0; + } .schedule-label { display: block; font-size: 12px; @@ -1259,12 +1380,18 @@ class SternwarteCard extends HTMLElement { .schedule-overview { grid-template-columns: 1fr; } + .input-panel-grid { + grid-template-columns: repeat(6, minmax(0, 1fr)); + } + } + @media (max-width: 480px) { + .input-panel-grid { + grid-template-columns: repeat(4, minmax(0, 1fr)); + } }
- ${rainOn ? `
Regen erkanntDas Dach wird bei Regen nicht \u00f6ffnet und bei Bedarf automatisch geschlossen.
` : ""} -
@@ -1381,6 +1508,21 @@ class SternwarteCard extends HTMLElement {
+ +
+
Eing\u00e4nge
+
+ ${inputPanelStates.map((input) => ` +
+ +
+ ${input.shortLabel} + ${input.on === true ? "AN" : input.on === false ? "AUS" : "UNBEKANNT"} +
+
+ `).join("")} +
+
`; diff --git a/sternwarte-homeassistant-integration/custom_components/sternwarte/sensor.py b/sternwarte-homeassistant-integration/custom_components/sternwarte/sensor.py index 34e1511..c32b799 100644 --- a/sternwarte-homeassistant-integration/custom_components/sternwarte/sensor.py +++ b/sternwarte-homeassistant-integration/custom_components/sternwarte/sensor.py @@ -74,6 +74,12 @@ class SternwarteRoofStatusSensor(SternwarteEntity, SensorEntity): return "sensorfehler" return "unbekannt" + @property + def extra_state_attributes(self) -> dict[str, object]: + return { + "inputs": list(self.coordinator.data.inputs), + } + class SternwarteWindSpeedSensor(SternwarteWindBaseSensor): _attr_name = "Windgeschwindigkeit"