Skip to content

Commit 90d0efc

Browse files
authored
Merge pull request #38 from basecubedev/maintenance/update-documentation
documentation update
2 parents d9d777b + c6744d7 commit 90d0efc

11 files changed

Lines changed: 100 additions & 41 deletions

README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -337,9 +337,11 @@ When `dashboard.enabled=true`, the EMS starts a local dashboard server:
337337
http://<ems-host>:8080
338338
```
339339

340-
The dashboard shows live flow, device state, rule state, and short-term history
341-
from local SQLite storage. It is read-only and does not expose EMS control
342-
endpoints.
340+
The built-in standalone dashboard has Aggregated, Devices, Control, and Energy
341+
views. The Energy view includes Today, Yesterday, rolling periods,
342+
monthly/yearly totals, and Lifetime with since date.
343+
344+
It is read-only and does not expose EMS control endpoints.
343345

344346
More: [docs/dashboard.md](docs/dashboard.md).
345347

@@ -351,15 +353,15 @@ Home Assistant can be used for:
351353

352354
- monitoring
353355
- optional runtime-state helper controls
354-
- dashboard visualization
356+
- optional Home Assistant dashboard visualization
355357

356-
Dashboard example:
358+
Home Assistant dashboard example:
357359

358360
```text
359361
homeassistant-dashboard/dashboard.yaml
360362
```
361363

362-
Dashboard preview:
364+
Home Assistant dashboard preview:
363365

364366
```text
365367
homeassistant-dashboard/dashboard-preview.jpg
@@ -454,7 +456,7 @@ Safety checks: [docs/safety.md](docs/safety.md).
454456
| `config.template.json` | Versioned config template |
455457
| `config.json` | Local config, ignored by Git |
456458
| `runtime-state.json` | Mutable runtime state, ignored by Git |
457-
| `homeassistant-dashboard/dashboard.yaml` | HA dashboard example |
459+
| `homeassistant-dashboard/dashboard.yaml` | Optional HA dashboard example |
458460
| `homeassistant-dashboard/dashboard-preview.jpg` | HA dashboard preview image |
459461
| `scripts/check_log_events.py` | Structured log validator |
460462
| `docs/` | Public documentation |

config.template.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
"enabled": true,
8686
"price_per_kwh": 0.0,
8787
"currency": "EUR",
88-
"max_sample_delta_seconds": 60,
88+
"max_sample_delta_seconds": 20,
8989
"timezone": "Europe/Berlin"
9090
},
9191

dashboard/sqlite_store.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"enabled": True,
1111
"price_per_kwh": 0.0,
1212
"currency": "EUR",
13-
"max_sample_delta_seconds": 60,
13+
"max_sample_delta_seconds": 20,
1414
"timezone": "Europe/Berlin",
1515
}
1616

docs/configuration-examples.md

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -36,18 +36,35 @@ Use this for standalone EMS operation without Home Assistant.
3636
"max_device_power": 800,
3737
"deadband": 10,
3838
"runtime_state_path": "runtime-state.json",
39-
"min_output_limit": 30,
40-
"loop_interval": 5,
39+
"min_output_limit": 35,
40+
"loop_interval": 3,
4141
"redistribute_clamped_power": true,
4242
"pv_kwp_weighting": true,
4343
"pv_charge_balance_enabled": true,
44-
"pv_charge_balance_deadband_percent": 5,
44+
"pv_charge_balance_deadband_percent": 1,
4545
"pv_charge_balance_full_bias_percent": 15,
46-
"pv_charge_balance_strength": 1.0,
46+
"pv_charge_balance_strength": 0.7,
4747
"battery_kwh_weighting": true,
4848
"soc_reconcile_interval": 10
4949
},
5050

51+
"dashboard": {
52+
"enabled": true,
53+
"host": "0.0.0.0",
54+
"port": 8080,
55+
"database_path": "data/ems_dashboard.sqlite",
56+
"history_hours": 48,
57+
"write_interval_seconds": 5
58+
},
59+
60+
"energy_savings": {
61+
"enabled": true,
62+
"price_per_kwh": 0.0,
63+
"currency": "EUR",
64+
"max_sample_delta_seconds": 20,
65+
"timezone": "Europe/Berlin"
66+
},
67+
5168
"winter": {
5269
"enabled": false,
5370
"months": [10, 11, 12, 1, 2, 3],
@@ -86,6 +103,10 @@ Change:
86103
- `shelly.ip`
87104
- `pv_kwp`
88105
- `battery_kwh`
106+
- `dashboard.port` or `dashboard.database_path` only when needed
107+
- `energy_savings.price_per_kwh`
108+
- `energy_savings.currency`
109+
- `energy_savings.timezone` only when you do not want Europe/Berlin calendar days
89110

90111
Run:
91112

@@ -97,7 +118,8 @@ python3 -B ems-solarflow-api-control.py --preflight
97118
## Example 2: Two Zendure Devices With Home Assistant
98119

99120
Use this when Home Assistant should receive EMS sensors and optionally provide
100-
runtime helper controls.
121+
runtime helper controls. The values below intentionally override some
122+
single-device template values for a two-inverter installation.
101123

102124
```json
103125
{
@@ -119,8 +141,8 @@ runtime helper controls.
119141
"max_total_power": 1600,
120142
"max_device_power": 800,
121143
"runtime_state_path": "runtime-state.json",
122-
"min_output_limit": 30,
123-
"loop_interval": 5
144+
"min_output_limit": 35,
145+
"loop_interval": 3
124146
},
125147

126148
"devices": [

docs/control-logic.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,8 @@ The hold uses:
118118
standby_total_w = min_output_limit * active_online_device_count
119119
```
120120

121-
With two active devices and `min_output_limit=30`, the global target is held at
122-
`60W` instead of integrating toward `800W`. Once PV, discharge capability, or
121+
With two active devices and `min_output_limit=35`, the global target is held at
122+
`70W` instead of integrating toward `800W`. Once PV, discharge capability, or
123123
current output is observed again, the normal fast output controller resumes.
124124

125125
## PV-First Allocation

docs/dashboard.md

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,19 +41,29 @@ The dashboard section in `config.json` controls startup:
4141
"enabled": true,
4242
"price_per_kwh": 0.0,
4343
"currency": "EUR",
44-
"max_sample_delta_seconds": 60
44+
"max_sample_delta_seconds": 20,
45+
"timezone": "Europe/Berlin"
4546
}
4647
}
4748
```
4849

4950
`database_path` is relative to the project directory unless an absolute path is
50-
used. The SQLite store is local and only keeps short-term dashboard history.
51-
`write_interval_seconds` keeps database writes low even when the EMS loop runs
52-
with a short interval.
51+
used. The SQLite database stores short-term live dashboard snapshots and
52+
telemetry. Those short-term rows are cleaned according to
53+
`dashboard.history_hours`. `write_interval_seconds` keeps database writes low
54+
even when the EMS loop runs with a short interval.
5355

54-
Energy statistics are stored in the same SQLite database as daily aggregates.
55-
They integrate measured inverter AC output over real elapsed time and skip
56-
intervals longer than `max_sample_delta_seconds`.
56+
Daily energy statistics are stored in `daily_energy_stats` in the same database.
57+
They are persistent daily aggregates and are not removed by the short-term
58+
snapshot/telemetry cleanup.
59+
60+
Energy statistics integrate measured inverter AC output over real elapsed time.
61+
Intervals above `energy_savings.max_sample_delta_seconds` are skipped and the
62+
integration baseline is advanced. This avoids false energy jumps after
63+
restarts, downtime, or longer outages.
64+
65+
`energy_savings.timezone` defines the calendar timezone used for daily
66+
statistics and period lookups such as Today and Yesterday.
5767

5868
## API
5969

@@ -63,8 +73,27 @@ Live snapshot:
6373
GET /api/live
6474
```
6575

66-
The live snapshot includes `energy_stats` with today, rolling windows, best
67-
day, current-year monthly totals, yearly totals, and lifetime totals.
76+
The live snapshot includes `energy_stats` with:
77+
78+
```text
79+
energy_stats.enabled
80+
energy_stats.currency
81+
energy_stats.price_per_kwh
82+
energy_stats.today
83+
energy_stats.yesterday
84+
energy_stats.last_7_days
85+
energy_stats.last_4_weeks
86+
energy_stats.last_12_months
87+
energy_stats.best_day
88+
energy_stats.monthly_current_year
89+
energy_stats.yearly
90+
energy_stats.lifetime
91+
energy_stats.lifetime.since_date
92+
```
93+
94+
`lifetime.since_date` is the first date in `daily_energy_stats` with
95+
`sample_count > 0`. It is day-accurate and uses the stored local statistics
96+
date, not the current runtime timestamp.
6897

6998
Energy statistics only:
7099

docs/home-assistant.md

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ The EMS can run standalone with `config.json` and `runtime-state.json`.
66
The template default keeps Home Assistant disabled with `ha.enabled=false` and
77
`ha.control_enabled=false`.
88

9+
This page documents the optional Home Assistant integration and the optional HA
10+
dashboard example. The built-in standalone read-only dashboard is documented in
11+
`docs/dashboard.md`.
12+
913
## Roles
1014

1115
Home Assistant has two independent roles:
@@ -155,22 +159,23 @@ sensor.ems_solarflow_wr1_winter_min_soc_target
155159
sensor.ems_solarflow_wr1_winter_estimated_ramp_days
156160
```
157161

158-
## Dashboard
162+
## Home Assistant Dashboard Example
159163

160-
The repository contains a dashboard example:
164+
The repository contains an optional Home Assistant dashboard example:
161165

162166
```text
163167
homeassistant-dashboard/dashboard.yaml
164168
```
165169

166-
Dashboard preview:
170+
Home Assistant dashboard preview:
167171

168172
```text
169173
homeassistant-dashboard/dashboard-preview.jpg
170174
```
171175

172176
It includes EMS control, runtime device control, winter status, device state,
173-
battery status, PV details, and power-flow visualization.
177+
battery status, PV details, and power-flow visualization. This is separate from
178+
the built-in standalone dashboard documented in `docs/dashboard.md`.
174179

175180
Troubleshooting stale, unavailable, or ignored HA values:
176181
[troubleshooting.md](troubleshooting.md).

docs/quickstart.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,8 +150,8 @@ The template already uses this live-control-ready system policy:
150150
"reconcile_ac_mode_on_start": true,
151151
"reconcile_smart_mode": true,
152152
"max_total_power": 800,
153-
"loop_interval": 5,
154-
"min_output_limit": 0
153+
"loop_interval": 3,
154+
"min_output_limit": 35
155155
}
156156
}
157157
```

docs/runtime-state.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@ Example:
2020
"system": {
2121
"enabled": true,
2222
"max_total_power": 800,
23-
"loop_interval": 5,
24-
"min_output_limit": 30
23+
"loop_interval": 3,
24+
"min_output_limit": 35
2525
},
2626
"ha": {
2727
"enabled": false,
@@ -56,9 +56,10 @@ Example:
5656
| `loop_interval` | Runtime loop interval |
5757
| `min_output_limit` | Runtime guard against very low enabled `outputLimit` writes |
5858

59-
`min_output_limit=30` is useful on installations where `outputLimit=0` behaves
60-
like a stop, idle, or sleep state. The guard is applied before deadband handling
61-
and only while EMS control is enabled.
59+
`min_output_limit=35` is the current template default and is useful on
60+
installations where `outputLimit=0` behaves like a stop, idle, or sleep state.
61+
The guard is applied before deadband handling and only while EMS control is
62+
enabled.
6263

6364
The same value is also used as the standby/wakeup `outputLimit` for strict
6465
night/minSoc idle. When all active online devices report exactly no PV, no

docs/troubleshooting.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ Important runtime fields:
8484
"enabled": true,
8585
"max_total_power": 800,
8686
"loop_interval": 2,
87-
"min_output_limit": 30
87+
"min_output_limit": 35
8888
},
8989
"ha": {
9090
"enabled": false,
@@ -406,7 +406,7 @@ Check:
406406
```json
407407
{
408408
"system": {
409-
"min_output_limit": 30
409+
"min_output_limit": 35
410410
}
411411
}
412412
```

0 commit comments

Comments
 (0)