From 4eb88f7fdac6429ef2fd3ed7cdcf73dbda9983f0 Mon Sep 17 00:00:00 2001 From: glenn schrooyen Date: Wed, 14 Oct 2026 17:03:05 +0200 Subject: [PATCH] PRICE-01: migration note, and the tests drive the real control cycle - DOCS: the migration note said markup and taxes do not matter; with the provider they are added to the wholesale price. Step 4 and 5 now say what they set and what static_profile does while no source has a price. - The gap tests run the notification through cycle(), where the check is called, so a check that is never called goes red. - test header: the real-transport checks are section 11. Co-Authored-By: Claude Claude-Session: https://claude.ai/code/session_01Bdqr7PiaHcBnzPituu2yTC --- goodwe_controller/DOCS.md | 11 +++++++---- goodwe_controller/test_price_service.py | 11 ++++++++--- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/goodwe_controller/DOCS.md b/goodwe_controller/DOCS.md index db3102d..89b1ee7 100644 --- a/goodwe_controller/DOCS.md +++ b/goodwe_controller/DOCS.md @@ -2320,11 +2320,14 @@ Do this on the Configuration tab, in one save, and restart once: 3. **Clear** **Current price entity** (`price_now_entity`) and **Average price entity** (`price_avg_entity`). The add-on refuses to start with a price source and these two together. -4. Keep **Supplier markup** and **Distribution, levies and VAT** as they are - for a wholesale price. If the Home Assistant sensors already included them, - the figures were never in these two options, so nothing else changes. +4. Check **Supplier markup** and **Distribution, levies and VAT**. With the + Home Assistant pair they decided nothing about the maintenance charge. With + the provider they are added to the wholesale price, so they set the prices + shown on the page and, if battery modes or trading are on, the prices those + decide on. The maintenance charge gate does not depend on them. 5. Keep **Fixed or day/night tariff** (`static_profile`) if you have one. It - stays the fallback for trading when no source answers. + is still the tariff used, marked as estimated and without trading, while no + source has a price. 6. Remove the `price_service` REST and template sensors from Home Assistant when you are satisfied. They are no longer read. diff --git a/goodwe_controller/test_price_service.py b/goodwe_controller/test_price_service.py index 87cd687..3fd1bc3 100644 --- a/goodwe_controller/test_price_service.py +++ b/goodwe_controller/test_price_service.py @@ -21,7 +21,7 @@ THE SERVER IS A MOCK. This session holds no token, so it cannot ask the real one for a price. `Server` below answers the layout the design's API section gives (`unix_seconds`, `price`, `unit`, `zone`, `covers`, `source`, `fetched_at`), over a transport with the same contract as `price.https_get`. -Section 12 drives the REAL `https_get` against a local aiohttp server, for the +Section 11 drives the REAL `https_get` against a local aiohttp server, for the parts a mock transport cannot show: the header on the wire, the status words, the timeout, a refused connection. @@ -637,6 +637,9 @@ class FakeHass: async def number(self, entity, invert=False): return self.values.get(entity) + async def set_number(self, entity, value): + return True + async def call(self, domain, service, data): self.calls.append((domain, service, data)) return True @@ -730,11 +733,13 @@ class Wired: await asyncio.wait_for(task, timeout=5) async def tick(self, now=None): - """One 30 s tick: read inputs, then the price-gap check.""" + """One control tick as `run_control` makes it: read inputs, then the + cycle, which is where the price-gap check is called from.""" if now is not None: self.clock.now = now + self.ctl.auto = True await self.ctl.read_inputs() - await self.ctl.check_price_gap() + await self.ctl.cycle() def notes(self): return [(s, d) for dom, s, d in self.ctl.hass.calls