docs: update README for all features added since initial commit
- Forecast config: fetch_interval, fetch_window_start/end, base_load_w, min_surplus_w — 3x daily refresh within daylight window - EMS config: override_max_import_w — hard-stop override on excess import - Decision logic: charging advice concept and surplus window algorithm - Decision logic: override hard-stop conditions (SOC brake + import limit) - Web interface: charging advice card, PM live power badges, phase display, compressor power, override duration selector (30m/1h/2h/4h) - Makefile: note that make install skips config if file already exists Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
51
README.md
51
README.md
@@ -148,14 +148,35 @@ If SOC drops below its allowed threshold, the consumer is shut off immediately (
|
||||
|
||||
The heat pump's own hysteresis fires the compressor when DHW drops 5°C below target.
|
||||
|
||||
### PV forecast cadence
|
||||
|
||||
The forecast is fetched from forecast.solar up to 3 times per day, within the configured `fetch_window_start`/`fetch_window_end` and spaced by `fetch_interval`. Outside the window the last result is reused. The free tier allows ~12 requests per day; 3 fetches per day leaves ample headroom.
|
||||
|
||||
### Early release conditions
|
||||
|
||||
- **SG-Ready**: released early if `CompressorPowerW < 50 W` for 3 consecutive cycles (~6 min). The heat pump has finished its boost cycle.
|
||||
- **Wallbox A/B**: released early if Shelly PM reads `< 50 W` for 3 consecutive cycles. Car is full or unplugged.
|
||||
|
||||
### Charging advice
|
||||
|
||||
The status page shows a **"Plug in car"** advisory when:
|
||||
- No wallbox is currently active
|
||||
- The PV forecast predicts a surplus window (net PV output > `min_surplus_w`) later today
|
||||
- The window has not yet started
|
||||
|
||||
The advisory shows the recommended plug-in time (window start − 30 min) so the car is ready when surplus charging begins.
|
||||
|
||||
The surplus window is computed from the hourly forecast (`watts` array) minus `base_load_w`. The first contiguous block of hours where `pv_w − base_load_w ≥ min_surplus_w` becomes the charging window.
|
||||
|
||||
### Manual override detection
|
||||
|
||||
Every cycle the EMS reads back actual Shelly relay states. If the hardware state differs from the engine's expected state, a manual override is detected. The consumer is locked from EMS control for 1 hour (configurable). Shown on the status page.
|
||||
Every cycle the EMS reads back actual Shelly relay states. If the hardware state differs from the engine's expected state, a manual override is detected. The consumer is locked from EMS control for a configurable duration (default 1 h). Shown on the status page.
|
||||
|
||||
### Override hard-stop conditions
|
||||
|
||||
Active overrides are cancelled immediately (without waiting for the duration to expire) if:
|
||||
- **SOC emergency brake** — battery SOC drops below the consumer's allowed SOC threshold
|
||||
- **Import hard-stop** — grid import exceeds `override_max_import_w` (e.g. 800 W) — prevents runaway grid consumption when a car is force-started at night or on a cloudy day
|
||||
|
||||
---
|
||||
|
||||
@@ -246,6 +267,11 @@ forecast:
|
||||
declination: <panel tilt degrees>
|
||||
azimuth: <degrees from south: 0=south, 90=west, -90=east>
|
||||
kwp: <installed peak power kWp>
|
||||
fetch_interval: "4h" # re-fetch during the day (free tier: max ~12 req/day)
|
||||
fetch_window_start: "07:00" # only fetch within this window
|
||||
fetch_window_end: "19:00"
|
||||
base_load_w: 450 # steady-state house consumption for surplus estimate (W)
|
||||
min_surplus_w: 1800 # min net surplus to consider wallbox charging viable (W)
|
||||
|
||||
ems:
|
||||
poll_interval: "2m"
|
||||
@@ -254,6 +280,7 @@ ems:
|
||||
state_file: "/run/ems/heartbeat"
|
||||
recovery_timeout: "1h" # ignore Shelly state if EMS was down longer than this
|
||||
override_timeout: "1h" # how long a manual Shelly change is respected
|
||||
override_max_import_w: 800 # cancel active override if grid import exceeds this (0 = disabled)
|
||||
```
|
||||
|
||||
---
|
||||
@@ -286,9 +313,11 @@ make build # Build binary → ./ems
|
||||
make test # Run unit tests
|
||||
make dry-run # Run without executing actions (log only)
|
||||
make run # Run with live switching (foreground)
|
||||
make install # Build + install binary, config, systemd unit
|
||||
make install # Build + install binary, config (first time only), systemd unit
|
||||
```
|
||||
|
||||
> **Note:** `make install` only copies `configs/ems-config.yaml` to `/etc/ems/ems-config.yaml` if that file does not already exist. Subsequent installs will not overwrite your passwords or local settings.
|
||||
|
||||
### Config file locations (when installed)
|
||||
|
||||
| File | Purpose |
|
||||
@@ -318,12 +347,20 @@ Available at `http://<pi-ip>:9099/`
|
||||
|
||||
Shows:
|
||||
- Current grid power, battery SOC, PV production
|
||||
- Per-phase grid power (L1/L2/L3)
|
||||
- Each consumer: state, manual override status, Shelly PM live power
|
||||
- Today's PV forecast
|
||||
- Manual override buttons for Shelly consumers (SG-Ready, Wallbox A, Wallbox B)
|
||||
- Per-phase grid power (L1/L2/L3) — helps identify which phase has the most export
|
||||
- Heat pump compressor power — shows whether the heat pump is actively running
|
||||
- Each consumer: state, manual override status, live power (W) from Shelly PM variants
|
||||
- Today's PV forecast (total kWh, charging surplus window if predicted)
|
||||
- **Charging advice card** — "Plug in car by HH:MM" when surplus charging is expected later today
|
||||
- Manual override controls for each consumer (SG-Ready, Wallbox A, Wallbox B)
|
||||
|
||||
Manual overrides via the web UI switch the hardware directly. The EMS detects the change next cycle via state read-back and applies the override lockout automatically.
|
||||
### Manual override controls
|
||||
|
||||
Each consumer has **Ein** (on) and **Aus** (off) buttons. A duration selector lets you choose how long the override lasts: **30 min / 1 h / 2 h / 4 h**.
|
||||
|
||||
Overrides applied via the web UI take effect immediately (the relay switches at once) and the lockout is active before the next EMS cycle. The EMS will not fight the override until the duration expires — unless a hard-stop condition is triggered (SOC emergency brake or import threshold exceeded).
|
||||
|
||||
Overrides applied via the **Shelly app or physical button** are detected on the next cycle (within 2 min) and automatically locked for the configured `override_timeout`.
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user