diff --git a/haos-addon/config.yaml b/haos-addon/config.yaml index 98b429a..0eedbfc 100644 --- a/haos-addon/config.yaml +++ b/haos-addon/config.yaml @@ -1,5 +1,5 @@ name: ShineBridge -version: "1.8.12" +version: "1.8.13" slug: shinebridge description: Growatt Wechselrichter lokal in Home Assistant — Modbus TCP via ShineLAN-X, MQTT Discovery, Web UI url: https://gitea.bitfire.work/retr0/shinebridge diff --git a/haos-addon/src/surplus_devices.py b/haos-addon/src/surplus_devices.py index 01bf06f..d9353d6 100644 --- a/haos-addon/src/surplus_devices.py +++ b/haos-addon/src/surplus_devices.py @@ -36,12 +36,17 @@ class SurplusDeviceController: threshold = float(dev.get("threshold_w", 500)) hysteresis = float(dev.get("hysteresis_w", 150)) min_on_s = float(dev.get("min_on_minutes", 0)) * 60 + inverted = bool(dev.get("inverted", False)) currently_on = self._states.get(name, False) - if not currently_on and surplus_w >= threshold: + # Invertiert: EIN bei Netzbezug (kein Überschuss), AUS bei Überschuss + should_turn_on = not currently_on and (surplus_w >= threshold if not inverted else surplus_w < (threshold - hysteresis)) + should_turn_off = currently_on and (surplus_w < (threshold - hysteresis) if not inverted else surplus_w >= threshold) + + if should_turn_on: self._send(name, True) self._on_since[name] = now - elif currently_on and surplus_w < (threshold - hysteresis): + elif should_turn_off: on_since = self._on_since.get(name, 0.0) if now - on_since >= min_on_s: self._send(name, False) diff --git a/haos-addon/src/web/index.html b/haos-addon/src/web/index.html index 941acd1..0fbb321 100644 --- a/haos-addon/src/web/index.html +++ b/haos-addon/src/web/index.html @@ -988,19 +988,31 @@ async function importConfig(input) { let surplusDevices = []; +function field(label, input) { + return `
+ ${label} + ${input} +
`; +} + function renderSurplusDeviceRow(dev) { const id = dev.id || ('sd_' + Math.random().toString(36).slice(2)); return `
-
- - - - - - - +
+ ${field('Name', ``)} + ${field('Z2M Friendly Name', ``)} + ${field('Schwellwert (W)', ``)} + ${field('Hysterese (W)', ``)} + ${field('Min. Laufzeit (min)', ``)} +
+ + +
+
`; } @@ -1044,6 +1056,7 @@ function _collectSurplusDevices() { threshold_w: parseFloat(row.querySelector('[data-field=threshold_w]').value) || 0, hysteresis_w: parseFloat(row.querySelector('[data-field=hysteresis_w]').value) || 0, min_on_minutes: parseFloat(row.querySelector('[data-field=min_on_minutes]').value) || 0, + inverted: row.querySelector('[data-field=inverted]').checked, enabled: row.querySelector('[data-field=enabled]').checked, })); } @@ -1086,7 +1099,7 @@ function renderSurplusStatus(surplusData) { return `
${dot} ${esc(d.name||d.z2m_name)} - ab ${d.threshold_w}W + ${d.inverted ? '↓' : '↑'} ${d.threshold_w}W ${info} ${on?'EIN':'AUS'}
`;