From a46be046e4d3ee8285d986cb622f63197dd562cb Mon Sep 17 00:00:00 2001 From: tomquist <528585+tomquist@users.noreply.github.com> Date: Sat, 27 Jun 2026 15:02:31 +0000 Subject: [PATCH 1/9] docs: add FAQ entry for SoC-based load distribution via HA automation Explains how to find the Distribution Weight entity for each battery (AstraMeter Consumer device in MQTT), locate the SoC sensor, and wire up a Home Assistant automation that sets each battery's weight inversely proportional to its SoC so emptier batteries are prioritised. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01Vmp95JCXMxff12vamwJLQT --- docs/faq.md | 81 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/docs/faq.md b/docs/faq.md index 1a9b26c5..94425717 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -198,6 +198,87 @@ answer the app's polls via MQTT. See ## Advanced +### How can I distribute load based on each battery's State of Charge (SoC)? + +A: AstraMeter exposes a **Distribution Weight** entity for every battery in a +CT002/CT003 fleet (requires [MQTT Insights](mqtt-insights.md) with HA discovery +enabled). Raising the weight on a battery makes it receive a larger share of the +charging or discharging target; you can adjust these weights dynamically from a +Home Assistant automation so that emptier batteries are prioritised and fuller +ones are throttled back. + +#### Step 1 — Find the Distribution Weight entity for each battery + +1. In Home Assistant go to **Settings → Devices & Services → MQTT** and open the + **Devices** tab. +2. Look for devices named **AstraMeter Consumer …** (one per battery). Open each + one. +3. Under **Controls** you will find a **Distribution Weight** slider. Note its + entity ID — it looks like + `number.astrameter_consumer__distribution_weight`, where `` is the + battery's MAC address with all non-alphanumeric characters replaced by `_` + (e.g. a battery with MAC `AA:BB:CC:DD:EE:FF` produces + `number.astrameter_consumer_aabbccddeeff_distribution_weight`). + + You can also find the entity ID by opening the entity's detail page and + clicking the gear icon → the entity ID is shown at the top of the settings + dialog. + +#### Step 2 — Find the SoC sensor for each battery + +The SoC sensor comes from your battery's native integration (e.g. hm2mqtt, +hame-relay, or any other source). Open the battery device in Home Assistant, +find the **State of Charge** sensor, and note its entity ID +(e.g. `sensor.marstek_b2500_aabbccddeeff_soc`). + +#### Step 3 — Create the automation + +The formula below maps SoC to weight so that an empty battery (0 %) gets weight +2.0 and a full battery (100 %) gets weight 0.0, linearly. Adjust the formula to +taste — for example clamp the minimum above 0 if you never want a battery fully +excluded. + +Go to **Settings → Automations & Scenes → Create Automation → Start with an +empty automation** and paste the following YAML (switch to YAML mode with the +three-dot menu): + +```yaml +alias: AstraMeter – SoC-based distribution weights +description: > + Adjust each battery's distribution weight inversely proportional to its SoC + so that the emptiest battery is charged first. +triggers: + - trigger: state + entity_id: + - sensor.marstek_b2500_aabbccddeeff_soc # battery 1 SoC — replace with yours + - sensor.marstek_b2500_112233445566_soc # battery 2 SoC — replace with yours + for: + seconds: 10 +actions: + - action: number.set_value + target: + entity_id: number.astrameter_consumer_aabbccddeeff_distribution_weight + data: + value: > + {{ [0, 2.0 * (1 - states('sensor.marstek_b2500_aabbccddeeff_soc') | float(50) / 100)] | max | round(1) }} + - action: number.set_value + target: + entity_id: number.astrameter_consumer_112233445566_distribution_weight + data: + value: > + {{ [0, 2.0 * (1 - states('sensor.marstek_b2500_112233445566_soc') | float(50) / 100)] | max | round(1) }} +mode: queued +max: 2 +``` + +Replace the four entity IDs with the real ones you found in steps 1 and 2. Add +one `number.set_value` action block per additional battery. + +> **Tip:** `mode: queued` with `max: 2` ensures that a burst of rapid SoC +> updates doesn't pile up; the 10-second `for:` delay further debounces +> short-lived spikes. Increase `max` if you have more than two batteries so +> that a concurrent trigger for every battery can queue safely. + ### How do signed (positive/negative) power values work with the emulator? A: Powermeters typically report import as positive and export as negative (see From 9608f76ea224ccdf368bd660b47e097e1bdeda99 Mon Sep 17 00:00:00 2001 From: tomquist <528585+tomquist@users.noreply.github.com> Date: Sat, 27 Jun 2026 15:06:29 +0000 Subject: [PATCH 2/9] docs: fix MAC slug description in SoC FAQ (chars removed, not replaced) Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01Vmp95JCXMxff12vamwJLQT --- docs/faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq.md b/docs/faq.md index 94425717..5fd2341b 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -216,7 +216,7 @@ ones are throttled back. 3. Under **Controls** you will find a **Distribution Weight** slider. Note its entity ID — it looks like `number.astrameter_consumer__distribution_weight`, where `` is the - battery's MAC address with all non-alphanumeric characters replaced by `_` + battery's MAC address lowercased with all non-alphanumeric characters removed (e.g. a battery with MAC `AA:BB:CC:DD:EE:FF` produces `number.astrameter_consumer_aabbccddeeff_distribution_weight`). From c0c914532288a6b732c0f178a095cbff7107520e Mon Sep 17 00:00:00 2001 From: tomquist <528585+tomquist@users.noreply.github.com> Date: Sat, 27 Jun 2026 15:09:59 +0000 Subject: [PATCH 3/9] docs: add three FAQ entries from post-2.0 discussions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Firmware: note HMA-1 requires 226+ for CT002/CT003 (#524) - Config: HA Supervisor API key rotates on restart; use a static long-lived token against the regular HA API instead (#498) - Troubleshooting: asymmetric battery capacities — use MIN_EFFICIENT_POWER + distribution weights together for proportional load splitting (#351) Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01Vmp95JCXMxff12vamwJLQT --- docs/faq.md | 33 ++++++++++++++++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/docs/faq.md b/docs/faq.md index 5fd2341b..6cee2068 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -85,6 +85,22 @@ import, negative for export), put it in `POWER_INPUT_ALIAS` (or import/export sensors can update at different moments and get read out of sync, causing drift and oscillation; a single signed value avoids that. +### I keep getting authentication errors in the Home Assistant powermeter logs after restarting. + +A: If you configured the Home Assistant powermeter using the Supervisor internal endpoint +(`http://supervisor/core/api` or `http://homeassistant/api`), the token associated with +that endpoint rotates on every Home Assistant or add-on restart, which invalidates the +credentials AstraMeter cached at startup. The fix is to generate a **static long-lived +access token**: + +1. In Home Assistant, go to your profile page (click your name in the sidebar). +2. Scroll to **Long-Lived Access Tokens** and create a new one. +3. In `config.ini` (or the add-on options), set `API_KEY` to the generated token and + point `HOST` at the regular HA API (`http://:8123`) instead of the + Supervisor URL. + +The static token never rotates and survives restarts on both sides. + ### Should I use Shelly emulation or CT002/CT003 for multiple batteries? A: Prefer CT002/CT003 (set `DEVICE_TYPE = ct002` or `ct003`) for multi-battery @@ -100,7 +116,7 @@ distribution. See [CT002 / CT003 steering](ct002.md). A: - **Venus:** Firmware 120+ for Shelly support, 152+ for improved regulation -- **B2500:** Firmware 108+ (HMJ devices) or 224+ (all others) +- **B2500:** Firmware 108+ (HMJ devices) or 224+ (all others); **HMA-1 devices require 226+** for CT002/CT003 support ### How do I handle the different ports for Shelly Pro 3EM? @@ -185,6 +201,21 @@ setpoint; pure DC battery pools can't be steered to exactly zero the same way. I second unit won't engage, lower `MIN_EFFICIENT_POWER`; for DC-only setups, set it to `0`. See [Battery efficiency optimization](ct002.md#battery-efficiency-optimization). +### I have batteries of different capacities and the smaller one drains much faster. + +A: By default AstraMeter splits the load equally, so a 5 kWh battery receives the same +share as a 15 kWh one and saturates first. Two settings work together to fix this: + +- **`MIN_EFFICIENT_POWER`** is a *per-battery* threshold, not a total. If you set it + to, say, 900 W, AstraMeter won't activate a second battery until demand is high + enough for each battery to handle at least 900 W. For asymmetric packs, lower this + value so both batteries run together across a wider demand range rather than the + smaller one absorbing everything alone. +- **Distribution Weight** (the per-battery slider exposed via MQTT Insights) lets you + split load proportionally to capacity once both batteries are active. For example, a + 15 kWh battery paired with a 5 kWh one might use weights of `3.0` and `1.0` + respectively for a 75:25 split. See [CT002 / CT003 steering](ct002.md) for details. + ### The Marstek app shows the meter offline or doesn't display my real meter values. A: This is expected for purely local operation — the emulated meter typically From 01ee037d0c49e032c2495c14869cdf81246b9f51 Mon Sep 17 00:00:00 2001 From: tomquist <528585+tomquist@users.noreply.github.com> Date: Sat, 27 Jun 2026 15:11:40 +0000 Subject: [PATCH 4/9] docs: remove unconfirmed HMA-1 226+ firmware requirement Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01Vmp95JCXMxff12vamwJLQT --- docs/faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq.md b/docs/faq.md index 6cee2068..3d5d0b1c 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -116,7 +116,7 @@ distribution. See [CT002 / CT003 steering](ct002.md). A: - **Venus:** Firmware 120+ for Shelly support, 152+ for improved regulation -- **B2500:** Firmware 108+ (HMJ devices) or 224+ (all others); **HMA-1 devices require 226+** for CT002/CT003 support +- **B2500:** Firmware 108+ (HMJ devices) or 224+ (all others) ### How do I handle the different ports for Shelly Pro 3EM? From c4b0c03375141ff573c4889b2bd0a9784926d06f Mon Sep 17 00:00:00 2001 From: tomquist <528585+tomquist@users.noreply.github.com> Date: Sat, 27 Jun 2026 15:13:27 +0000 Subject: [PATCH 5/9] docs: add efficiency_window_weight to asymmetric battery FAQ entry Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01Vmp95JCXMxff12vamwJLQT --- docs/faq.md | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 3d5d0b1c..cc074c1d 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -204,7 +204,7 @@ to `0`. See [Battery efficiency optimization](ct002.md#battery-efficiency-optimi ### I have batteries of different capacities and the smaller one drains much faster. A: By default AstraMeter splits the load equally, so a 5 kWh battery receives the same -share as a 15 kWh one and saturates first. Two settings work together to fix this: +share as a 15 kWh one and saturates first. Three settings work together to fix this: - **`MIN_EFFICIENT_POWER`** is a *per-battery* threshold, not a total. If you set it to, say, 900 W, AstraMeter won't activate a second battery until demand is high @@ -212,9 +212,17 @@ share as a 15 kWh one and saturates first. Two settings work together to fix thi value so both batteries run together across a wider demand range rather than the smaller one absorbing everything alone. - **Distribution Weight** (the per-battery slider exposed via MQTT Insights) lets you - split load proportionally to capacity once both batteries are active. For example, a - 15 kWh battery paired with a 5 kWh one might use weights of `3.0` and `1.0` - respectively for a 75:25 split. See [CT002 / CT003 steering](ct002.md) for details. + split load proportionally to capacity once both batteries are active simultaneously. + For example, a 15 kWh battery paired with a 5 kWh one might use weights of `3.0` + and `1.0` respectively for a 75:25 split. +- **Efficiency Window Weight** (also a per-battery slider via MQTT Insights, shown only + when `MIN_EFFICIENT_POWER > 0`) controls what fraction of the efficiency-rotation + active time each battery holds. When demand is low and only one battery runs at a + time, a larger battery should hold a proportionally bigger slice of the rotation + window — e.g. `75` % and `25` % for the same 3:1 capacity ratio — so it handles + more of the cumulative energy over time. + +See [CT002 / CT003 steering](ct002.md) for details on all three settings. ### The Marstek app shows the meter offline or doesn't display my real meter values. From cfb53e08fa76287dea2c8566738d1513966414dd Mon Sep 17 00:00:00 2001 From: tomquist <528585+tomquist@users.noreply.github.com> Date: Sat, 27 Jun 2026 15:14:09 +0000 Subject: [PATCH 6/9] docs: fix TOKEN config key in HA Supervisor API FAQ entry (not API_KEY) Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01Vmp95JCXMxff12vamwJLQT --- docs/faq.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq.md b/docs/faq.md index cc074c1d..27b16449 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -95,7 +95,7 @@ access token**: 1. In Home Assistant, go to your profile page (click your name in the sidebar). 2. Scroll to **Long-Lived Access Tokens** and create a new one. -3. In `config.ini` (or the add-on options), set `API_KEY` to the generated token and +3. In `config.ini` (or the add-on options), set `TOKEN` to the generated token and point `HOST` at the regular HA API (`http://:8123`) instead of the Supervisor URL. From 0e5ec3815337cd438466339e748e07f3c8e17a5a Mon Sep 17 00:00:00 2001 From: tomquist <528585+tomquist@users.noreply.github.com> Date: Sat, 27 Jun 2026 15:25:41 +0000 Subject: [PATCH 7/9] feat: re-fetch Supervisor token on every HA connection attempt When IP=supervisor in the [HOMEASSISTANT] section, the token is now read from the SUPERVISOR_TOKEN environment variable on every WebSocket auth and REST fetch, rather than cached once at startup. This means a Home Assistant restart that rotates the Supervisor token is recovered automatically on the next reconnect (5 s later) without any manual intervention or config change. For non-supervisor setups the behaviour is unchanged: a static ACCESSTOKEN from config.ini is used as before. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01Vmp95JCXMxff12vamwJLQT --- docs/faq.md | 19 +++++++++++-------- src/astrameter/config/config_loader.py | 17 +++++++++++++++-- src/astrameter/config/config_loader_test.py | 19 +++++++++++++++++++ src/astrameter/powermeter/homeassistant.py | 9 +++++---- .../powermeter/homeassistant_test.py | 2 +- 5 files changed, 51 insertions(+), 15 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index 27b16449..ebff4485 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -87,17 +87,20 @@ causing drift and oscillation; a single signed value avoids that. ### I keep getting authentication errors in the Home Assistant powermeter logs after restarting. -A: If you configured the Home Assistant powermeter using the Supervisor internal endpoint -(`http://supervisor/core/api` or `http://homeassistant/api`), the token associated with -that endpoint rotates on every Home Assistant or add-on restart, which invalidates the -credentials AstraMeter cached at startup. The fix is to generate a **static long-lived -access token**: +A: When running as a Home Assistant add-on with `IP = supervisor` in the +`[HOMEASSISTANT]` section, AstraMeter reads the Supervisor token from the environment +on every connection attempt, so token rotation on a Home Assistant restart is handled +automatically — no manual token management is required. + +If you are running AstraMeter **outside** the add-on (e.g. as a standalone Python +script or in your own Docker container) and point it at the Supervisor API, the +Supervisor token won't be available. In that case, generate a **static long-lived +access token** instead: 1. In Home Assistant, go to your profile page (click your name in the sidebar). 2. Scroll to **Long-Lived Access Tokens** and create a new one. -3. In `config.ini` (or the add-on options), set `TOKEN` to the generated token and - point `HOST` at the regular HA API (`http://:8123`) instead of the - Supervisor URL. +3. In `config.ini`, set `ACCESSTOKEN` to the generated token and point `IP` at your + Home Assistant host directly (e.g. `IP = 192.168.1.x`, `PORT = 8123`). The static token never rotates and survives restarts on both sides. diff --git a/src/astrameter/config/config_loader.py b/src/astrameter/config/config_loader.py index 2ad44e60..8b9f40f5 100644 --- a/src/astrameter/config/config_loader.py +++ b/src/astrameter/config/config_loader.py @@ -1,6 +1,7 @@ from __future__ import annotations import configparser +import os from dataclasses import dataclass from ipaddress import IPv4Address, IPv4Network from typing import TYPE_CHECKING @@ -592,11 +593,23 @@ def parse_entities(value: str) -> str | list[str]: config.get(section, "POWER_OUTPUT_ALIAS", fallback="") ) + ip = config.get(section, "IP", fallback="") + if ip == "supervisor": + + def token_getter() -> str: + return os.environ.get("SUPERVISOR_TOKEN", "") + + else: + _static_token = config.get(section, "ACCESSTOKEN", fallback="") + + def token_getter() -> str: # type: ignore[no-redef] + return _static_token + return HomeAssistant( - config.get(section, "IP", fallback=""), + ip, config.get(section, "PORT", fallback=""), config.getboolean(section, "HTTPS", fallback=False), - config.get(section, "ACCESSTOKEN", fallback=""), + token_getter, current_power_entity, config.getboolean(section, "POWER_CALCULATE", fallback=False), power_input_alias, diff --git a/src/astrameter/config/config_loader_test.py b/src/astrameter/config/config_loader_test.py index 96430e45..1b33018c 100644 --- a/src/astrameter/config/config_loader_test.py +++ b/src/astrameter/config/config_loader_test.py @@ -191,6 +191,25 @@ def test_create_homeassistant_powermeter(): raise +def test_create_homeassistant_powermeter_supervisor_token(monkeypatch): + """IP=supervisor reads SUPERVISOR_TOKEN from env at call time, not from config.""" + import configparser as _cp + + monkeypatch.setenv("SUPERVISOR_TOKEN", "initial-token") + config = _cp.ConfigParser() + config["HA"] = { + "IP": "supervisor", + "PORT": "80", + "CURRENT_POWER_ENTITY": "sensor.power", + "ACCESSTOKEN": "stale-token", + } + pm = create_homeassistant_powermeter("HA", config) + assert pm._token() == "initial-token" + + monkeypatch.setenv("SUPERVISOR_TOKEN", "rotated-token") + assert pm._token() == "rotated-token" + + def test_create_vzlogger_powermeter(): """Test VZLogger powermeter creation.""" config = configparser.ConfigParser() diff --git a/src/astrameter/powermeter/homeassistant.py b/src/astrameter/powermeter/homeassistant.py index 8805fd88..283585d5 100644 --- a/src/astrameter/powermeter/homeassistant.py +++ b/src/astrameter/powermeter/homeassistant.py @@ -2,6 +2,7 @@ import contextlib import json import logging +from collections.abc import Callable from typing import Any import aiohttp @@ -27,7 +28,7 @@ def __init__( ip: str, port: str, use_https: bool, - access_token: str, + token: Callable[[], str], current_power_entity: str | list[str], power_calculate: bool, power_input_alias: str | list[str], @@ -37,7 +38,7 @@ def __init__( self.ip = ip self.port = port self.use_https = use_https - self.access_token = access_token + self._token = token self.current_power_entity = ( [current_power_entity] if isinstance(current_power_entity, str) @@ -216,7 +217,7 @@ async def _handle_message( if msg_type == "auth_required": logger.debug("Home Assistant: auth required, sending token") - await ws.send_json({"type": "auth", "access_token": self.access_token}) + await ws.send_json({"type": "auth", "access_token": self._token()}) elif msg_type == "auth_ok": logger.info("Home Assistant: authenticated") self._connected = True @@ -261,7 +262,7 @@ async def _handle_message( async def _fetch_initial_states(self) -> None: if not self._session: return - headers = {"Authorization": f"Bearer {self.access_token}"} + headers = {"Authorization": f"Bearer {self._token()}"} for eid in sorted(self._tracked_entities): if self._entity_values.get(eid) is not None: continue diff --git a/src/astrameter/powermeter/homeassistant_test.py b/src/astrameter/powermeter/homeassistant_test.py index dbbc183d..28a78541 100644 --- a/src/astrameter/powermeter/homeassistant_test.py +++ b/src/astrameter/powermeter/homeassistant_test.py @@ -12,7 +12,7 @@ def _create_powermeter(**overrides): ip="192.168.1.8", port="8123", use_https=False, - access_token="token", + token=lambda: "token", current_power_entity="sensor.current_power", power_calculate=False, power_input_alias="", From 0b1067cd7af0b84e21921f6f044d1bfe543012a6 Mon Sep 17 00:00:00 2001 From: tomquist <528585+tomquist@users.noreply.github.com> Date: Sat, 27 Jun 2026 16:32:34 +0000 Subject: [PATCH 8/9] docs: remove supervisor auth FAQ entry; fix SoC formula unavailable default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The supervisor token FAQ is no longer needed — IP=supervisor now re-reads the token automatically on every connection. Also fix the SoC automation formula: float default changed from 50 to 100 so an unavailable sensor is treated as full (weight 0) rather than silently getting a mid-range weight. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01Vmp95JCXMxff12vamwJLQT --- docs/faq.md | 23 ++--------------------- 1 file changed, 2 insertions(+), 21 deletions(-) diff --git a/docs/faq.md b/docs/faq.md index ebff4485..0444c416 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -85,25 +85,6 @@ import, negative for export), put it in `POWER_INPUT_ALIAS` (or import/export sensors can update at different moments and get read out of sync, causing drift and oscillation; a single signed value avoids that. -### I keep getting authentication errors in the Home Assistant powermeter logs after restarting. - -A: When running as a Home Assistant add-on with `IP = supervisor` in the -`[HOMEASSISTANT]` section, AstraMeter reads the Supervisor token from the environment -on every connection attempt, so token rotation on a Home Assistant restart is handled -automatically — no manual token management is required. - -If you are running AstraMeter **outside** the add-on (e.g. as a standalone Python -script or in your own Docker container) and point it at the Supervisor API, the -Supervisor token won't be available. In that case, generate a **static long-lived -access token** instead: - -1. In Home Assistant, go to your profile page (click your name in the sidebar). -2. Scroll to **Long-Lived Access Tokens** and create a new one. -3. In `config.ini`, set `ACCESSTOKEN` to the generated token and point `IP` at your - Home Assistant host directly (e.g. `IP = 192.168.1.x`, `PORT = 8123`). - -The static token never rotates and survives restarts on both sides. - ### Should I use Shelly emulation or CT002/CT003 for multiple batteries? A: Prefer CT002/CT003 (set `DEVICE_TYPE = ct002` or `ct003`) for multi-battery @@ -302,13 +283,13 @@ actions: entity_id: number.astrameter_consumer_aabbccddeeff_distribution_weight data: value: > - {{ [0, 2.0 * (1 - states('sensor.marstek_b2500_aabbccddeeff_soc') | float(50) / 100)] | max | round(1) }} + {{ [0, 2.0 * (1 - states('sensor.marstek_b2500_aabbccddeeff_soc') | float(100) / 100)] | max | round(1) }} - action: number.set_value target: entity_id: number.astrameter_consumer_112233445566_distribution_weight data: value: > - {{ [0, 2.0 * (1 - states('sensor.marstek_b2500_112233445566_soc') | float(50) / 100)] | max | round(1) }} + {{ [0, 2.0 * (1 - states('sensor.marstek_b2500_112233445566_soc') | float(100) / 100)] | max | round(1) }} mode: queued max: 2 ``` From a22c60970342abb67c7cb9eb900742eac57e6019 Mon Sep 17 00:00:00 2001 From: tomquist <528585+tomquist@users.noreply.github.com> Date: Sat, 27 Jun 2026 16:33:21 +0000 Subject: [PATCH 9/9] chore(ha_addon): drop ACCESSTOKEN from generated config.ini MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit IP=supervisor now reads SUPERVISOR_TOKEN from the environment on every connection, so writing the token into config.ini is both unnecessary and harmful — it bakes in a value that goes stale if HA restarts while the add-on keeps running, which was the original source of auth errors when users copy the generated config as a starting point. Co-Authored-By: Claude Sonnet 4.6 Claude-Session: https://claude.ai/code/session_01Vmp95JCXMxff12vamwJLQT --- ha_addon/run.sh | 1 - 1 file changed, 1 deletion(-) diff --git a/ha_addon/run.sh b/ha_addon/run.sh index 1b93fefe..0a416915 100644 --- a/ha_addon/run.sh +++ b/ha_addon/run.sh @@ -260,7 +260,6 @@ else echo "IP=supervisor" echo "PORT=80" echo "API_PATH_PREFIX=/core" - echo "ACCESSTOKEN=$SUPERVISOR_TOKEN" echo "WAIT_FOR_NEXT_MESSAGE=$(bashio::config 'wait_for_next_message')" if bashio::config.has_value 'power_output_alias'; then echo "POWER_CALCULATE=True"