Skip to content

Commit 0b5a7b9

Browse files
Merge release v2.0.2
2 parents cc8d94d + 336df32 commit 0b5a7b9

7 files changed

Lines changed: 29 additions & 5 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
# Changelog
22

3+
## 2.0.2
4+
5+
- **Fixed** EMA smoother slowing down across zero-crossings when `SMOOTH_TARGET_ALPHA` was configured above 0.5: the sign-flip "catchup" branch capped the effective alpha at 0.5, which actually reduced responsiveness for users who picked a larger alpha (e.g. 1.0 for near-instant tracking). The catchup boost now never drops below the configured alpha ([#371](https://github.com/tomquist/astrameter/issues/371)).
6+
37
## 2.0.1
48

59
- **Fixed** false "Home Assistant sensor is stale" errors for sensors that update infrequently or push only on value changes — including constant readings (e.g. solar production at night) and push-based integrations. The Home Assistant powermeter now treats a sensor as stale only when Home Assistant itself marks it `unavailable`/`unknown` or the websocket connection is lost ([#363](https://github.com/tomquist/astrameter/issues/363)).

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,8 @@ A: Ports below 1024 require root privileges on Linux. Solutions:
10121012
- Use `setcap` to grant permissions
10131013
- Run as root (not recommended)
10141014

1015+
Note: the Docker image runs as a non-root user, so binding port 1010 (used by `shellypro3em_old` and the combined `shellypro3em`, which starts both listeners) still fails with `PermissionError: [Errno 13]` under `network_mode: host`. Port 2220 (`shellypro3em_new`) is unaffected. Either lower the host's privileged-port range (`sudo sysctl -w net.ipv4.ip_unprivileged_port_start=1010`, persist via `/etc/sysctl.d/`) or run the container as root (`user: "0:0"` in compose). Publishing the port via bridge networking does **not** work, because the Marstek discovery packets are UDP broadcasts to the subnet address and aren't forwarded by Docker's port mapping.
1016+
10151017
### I get parsing errors on startup or the app crashes.
10161018

10171019
A: Common causes:

ha_addon/config.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: "AstraMeter"
2-
version: "2.0.1"
2+
version: "2.0.2"
33
slug: b2500_meter
44
description: >-
55
"Replicates a Smart Meter device for Marstek energy storage systems (formerly B2500 Meter) while allowing integration with various smart meters."

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
44

55
[project]
66
name = "astrameter"
7-
version = "2.0.1"
7+
version = "2.0.2"
88
description = "Power-meter monitoring for Marstek battery inverters (formerly b2500-meter)"
99
readme = "README.md"
1010
requires-python = ">=3.10"

src/astrameter/ct002/balancer.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -907,7 +907,8 @@ def _compute_auto_target(
907907
if all_dc_under_surplus and not self._all_dc_surplus_warned:
908908
logger.info(
909909
"CT002: %.0f W surplus but no AC-chargeable battery "
910-
"reporting — holding all at 0 W. Reporting device_types: %s",
910+
"reporting — nothing here can absorb it. Reporting "
911+
"device_types: %s",
911912
-grid_total,
912913
sorted({reports[cid].get("device_type", "") or "?" for cid in reports}),
913914
)

src/astrameter/powermeter/wrappers/smoothing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ async def get_powermeter_watts(self) -> list[float]:
7474

7575
catchup_alpha = self._alpha
7676
if (raw_total > 0) != (self._value > 0):
77-
catchup_alpha = min(0.5, self._alpha * 4)
77+
catchup_alpha = max(self._alpha, min(0.5, self._alpha * 4))
7878
delta = catchup_alpha * (raw_total - self._value)
7979

8080
if self._max_step > 0:

src/astrameter/powermeter/wrappers/smoothing_test.py

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,27 @@ async def test_sign_change_catchup(self):
8282
# Sign flip: raw goes negative
8383
fake.set([-100.0])
8484
await sm.get_powermeter_watts()
85-
# catchup_alpha = min(0.5, 0.1 * 4) = 0.4
85+
# catchup_alpha = max(0.1, min(0.5, 0.1 * 4)) = 0.4
8686
# delta = 0.4 * (-100 - 100) = -80 → new = 20
8787
assert sm.smoothed_value == pytest.approx(20.0)
8888

89+
@pytest.mark.asyncio
90+
async def test_sign_change_does_not_slow_high_alpha(self):
91+
fake = FakePowermeter([1.0])
92+
sm = SmoothedPowermeter(fake, alpha=1.0)
93+
94+
await sm.get_powermeter_watts()
95+
assert sm.smoothed_value == 1.0
96+
97+
# Sign flip: the catchup branch must not reduce alpha below the
98+
# configured value, otherwise large user-chosen alphas (e.g. 1.0)
99+
# respond slower across zero-crossings than they do anywhere else.
100+
fake.set([-99.0])
101+
await sm.get_powermeter_watts()
102+
# catchup_alpha = max(1.0, min(0.5, 4.0)) = 1.0
103+
# delta = 1.0 * (-99 - 1) = -100 → new = -99
104+
assert sm.smoothed_value == pytest.approx(-99.0)
105+
89106
@pytest.mark.asyncio
90107
async def test_max_step_limits_delta(self):
91108
fake = FakePowermeter([100.0])

0 commit comments

Comments
 (0)