Skip to content

Develop - #263

Merged
ohAnd merged 67 commits into
mainfrom
develop
Jun 23, 2026
Merged

Develop#263
ohAnd merged 67 commits into
mainfrom
develop

Conversation

@ohAnd

@ohAnd ohAnd commented Jun 23, 2026

Copy link
Copy Markdown
Owner

Release v0.3.35: Built-in Local EVOPT, EVCC Multi-Source Integration, and Production Refinements

Overview

61 new commits post-web-config-UI (PR #241) adding: built-in EVOPT optimizer, extended EVCC data sources, dynamic feed-in pricing, expanded hot-reload, and comprehensive bug fixes.

Key Features

1. Local EVOPT Built-in Optimizer

  • Full MILP solver implementation (811 lines) — no external dependency required
  • Default backend option alongside EOS (Akkudoktor) backend
  • Smart day/night cycle handling with forecast extension
  • Commits: 776fbb0, 23fd39a, eceb015
  • Tests: 677 new test cases
  • Status: Production ready

2. EVCC as Data Source Hub (Expansion)

Extended existing EVCC support from basic charge control to full optimization data:

  • Feed-in price source (358d7f8) — Fallback to fixed price on disconnect
  • Dynamic price source (a7c6c81) — Grid price integration with fallback strategy
  • PV forecast source (e352140) — Real data correction option
  • Fully backward compatible — Existing EVCC configs unchanged
  • Status: 3 new data sources, no breaking changes

3. Dynamic Feed-In Pricing

  • Multi-source support: Fixed, EVCC, EPEX-Spot, Elpris DK
  • Negative price switch support
  • Hot-reload capable
  • Commit: f88cc30
  • Status: Complete

4. Comprehensive Hot-Reload Expansion

21 total fields now live-reloadable (+682 lines improvements):

  • Feed-in price changes (hot reload on next run)
  • Battery price configuration
  • Optimizer settings (timeout, discharge override, PV charge control)
  • All PV forecast fields with debounced coalescing
  • Status: Fully tested

5. Fully Configurable HA Inverter Service Calls

  • Custom service name mapping per inverter state
  • Flexible payload structures for different HA integrations
  • 258 new test cases (test_ha_inverter_config.py)
  • Commit: a99543e
  • Status: Tested on real systems

6. SSL Certificate Ignore Support

7. Startup Error Handling & Diagnostics

  • Graceful degradation on startup errors (DEGRADED mode)
  • Scoped alerts with actionable config links
  • Two-tier PV validation (lenient startup, strict hot-reload)
  • Commits: 81bff39, e7c058c, 882b459
  • Status: Improved UX

8. Bug Fixes

Issue Fix Commit
#243 PV installations lost in config UI ee53006
#252 MQTT EVCC discharge mode labels 3627500
#255 negative_price_switch in FeedInPrice 74b4193
#253 HA inverter service call config a99543e
PV forecast fallback caching 4ba4cba
Pylint compliance (8.98 → 10/10) 0c8dc0c

Stats

Metric Value
New Commits 61
Files Modified 65+
Lines Added 10,000+
New Tests 1,000+ assertions
Bug Fixes 10
New Modules 3

Technical Changes

New Files:

  • src/interfaces/optimization_backends/local_evopt/optimizer.py (811 lines)
  • src/interfaces/optimization_backends/optimization_backend_local_evopt.py (482 lines)
  • src/interfaces/feed_in_price_interface.py (680 lines)
  • tests/config_web/test_ha_inverter_config.py (258 lines)
  • tests/interfaces/test_optimization_backend_local_evopt.py (677 lines)

Major Updates:

  • src/config_web/hot_reload.py: +682 lines
  • src/config_web/schema.py: +688 lines
  • src/interfaces/price_interface.py: +713 lines
  • docs/user-guide/configuration.html: +3,411 lines

Testing

  • 698+ unit tests passing
  • 1,000+ new test assertions
  • 258 HA inverter config tests
  • 677 local EVOPT tests
  • All hot-reload fields validated
  • Migration path verified

Issues Closed

#219, #243, #252, #253, #254, #255, #258

Checklist

  • All tests passing
  • Code passes pylint (10/10)
  • Documentation updated (3.4K lines)
  • Schema export working
  • Hot reload tested (21 fields)
  • EVOPT backend validated
  • Migration path verified
  • Backward compatibility maintained

Production-ready refinements and feature additions to the web-config system. Local EVOPT optimizer as built-in default eliminates external dependencies. EVCC extends to full data source hub. No breaking changes.

ohAnd and others added 30 commits May 1, 2026 08:39
…urce

Implement auxiliary Akkudoktor stock price fetching when using fixed_24h
prices with negative_price_switch enabled. This allows feed-in prices to be
set to 0 during negative stock price periods, while maintaining user-provided
fixed_24h prices for grid cost calculations.

Fixes #228 - Fester Stromtarif und Einspeisevergütung=0 bei negativem Strompreis

Co-authored-by: Copilot <copilot@github.com>
Files changed:
M	src/version.py
…inks

- Add startup timestamp filtering to /logs/alerts endpoint
- Implement alert deduplication and severity sorting in startup panel
- Add metadata markers (Config link, ACTION REQUIRED) to error sources
- Create InterfaceFactory for centralized interface creation with error handling
- Create StartupValidator facade for startup error registration
- Document architecture in developer guide and copilot instructions

Enables users to see only startup-relevant errors with direct config fix links.

Improve Error Handling / Enable User to troubleshoot
Fixes #251
Files changed:
M	src/version.py
- Price interface: add Config metadata to Tibber fetch errors
- Battery interface: add Config metadata to state update errors
- Properly handle NoneType errors in Tibber price responses

Enables users to see data fetch failures in startup panel instead of HA logs.
Fixes #251 - improves error visibility for troubleshooting.
Files changed:
M	src/version.py
Fix incorrect MQTT state display that showed "Avoid Discharge" instead of
"Discharge Allowed" for states 4 & 5 (EVCC PV modes).

Changes:
- mqtt_interface.py: Corrected value_template for states 4 & 5
  - State 4: "Avoid Discharge EVCC PV" → "Discharge Allowed EVCC PV"
  - State 5: "Avoid Discharge EVCC MIN+PV" → "Discharge Allowed EVCC MIN+PV"
- mqtt_interface.py: Fixed command_template mapping to enable manual selection
  - State 4: -2 (Auto) → 4 (actual state)
  - State 5: -2 (Auto) → 5 (actual state)
- mqtt_interface.py: Updated options list to match corrected labels
- README_OLD.md: Updated documentation to reflect correct state descriptions

Fixes:
- HomeAssistant MQTT now displays correct state matching EOS Connect dashboard
- Users can now manually select "Discharge Allowed EVCC" modes in HomeAssistant
- Documentation is consistent with actual behavior
- Internal discharge allowed logic was already correct; only display labels were wrong

Verified:
- base_control.py correctly identifies states 4 & 5 as discharge_allowed_modes
- eos_connect.py correctly sends set_mode_allow_discharge() commands
- Fronius inverter control unaffected; already working correctly
Implement dynamic battery export pricing with support for:
- Fixed prices (user-configured)
- Elpris DK spot prices (Denmark)
- EPEX-Spot prices via Akkudoktor API

Key Changes:
- FeedInPriceInterface: 500-line multi-source manager with background updates
- Standardized all prices to ct/kWh for user consistency
- Schema: 5 new hot-reload-capable config fields
- Web UI: Generalized subsection grouping (reusable for other sections)
- Test suite: 26 tests covering all sources

Breaking Change: Config key renamed (backward compatible)
- Old: static_adder_oere → New: static_adder_ct_kwh

Fixes #219
Files changed:
M	src/version.py
Allow users to disable SSL certificate verification for Home Assistant and
OpenHAB connections with self-signed or private CA certificates. Adds config
field, passes verify parameter to all HTTP requests, and logs security warnings.

- New `data_source.ssl_ignore` config field (expert level)
- LoadInterface respects setting in __request_with_retries()
- Added tests for SSL verify behavior (all 22 existing tests pass)
Introduces a fully self-contained MILP optimizer (PuLP/CBC) as a new
`local_evopt` optimizer source, eliminating the need for an external
EOS or EVopt server for most home setups.

## New files
- `src/interfaces/optimization_backends/local_evopt/optimizer.py`
  Bundled MILP engine derived from evcc-io/optimizer (MIT licence).
  Solves the 2-day energy dispatch problem in-process via PuLP/CBC.
  Supports charging strategies: charge_before_export,
  maximize_self_consumption, attenuate_grid_peaks, discharge_before_import.
  Supports discharging strategies: discharge_before_import,
  emergency_reserve (end-of-horizon SOC floor).
- `src/interfaces/optimization_backends/optimization_backend_local_evopt.py`
  Bridge between EOS request/response format and the MILP engine.
  Extends EVOptBackend for format transformation; runs the solver in-process.
  Truncates MILP horizon to valid future slots only, preventing stale
  wrapped past-data (e.g. today's noon p_N=0) from corrupting results.
- `tests/interfaces/optimization_backends/test_optimization_backend_local_evopt.py`
  560-line test suite covering request/response transformation, truncation
  fix, strategy routing, infeasible fallback, and edge cases.

## Dependencies
- `requirements.txt`: added `pulp>=2.7.0`

## Config schema (`src/config_web/schema.py`)
- `eos.source`: added `local_evopt` choice; set as new default
- `eos.server` / `eos.port`: hidden unless source is eos_server or evopt
- New `local_evopt`-specific fields (all hot-reloadable or restart_required):
  - `local_evopt_charging_strategy` (hot_reload)
  - `local_evopt_discharging_strategy` (hot_reload)
  - `local_evopt_emergency_reserve_pct` (hot_reload)
  - `local_evopt_max_grid_import_w` (restart_required)
  - `local_evopt_max_grid_export_w` (restart_required)
  - `local_evopt_num_threads` (restart_required)
  - `local_evopt_time_limit` (restart_required)

## Hot-reload (`src/config_web/hot_reload.py`)
- `_LOCAL_EVOPT_FIELD_MAP`: maps strategy keys to backend attributes
- `_apply_local_evopt()`: applies strategy changes to the running backend
- `_fire_run_trigger()`: generic helper that calls an optional `on_run_trigger`
  callback after strategy changes; reusable for any future hot-reload handler
- `HotReloadAdapter`: new `on_run_trigger` parameter

## Immediate re-run on strategy change (`src/eos_connect.py`)
- `OptimizationScheduler._immediate_run_event`: threading.Event that
  interrupts the inter-run sleep when set
- `OptimizationScheduler.request_immediate_run()`: public method, safe to
  call from any thread
- `hot_reload_adapter.on_run_trigger = optimization_scheduler.request_immediate_run`
  wired after both objects are created

## Bug fixes
- `config.js` / `wizard.js`: `_isDependencyHidden` / `_isDependencyMet` were
  missing the plain-string case in the `depends_on` comparison; fields with
  `depends_on: {"eos.source": "local_evopt"}` were always shown regardless of
  the current source setting
- `maximize_self_consumption` strategy: previous implementation penalised
  grid import (already zero during PV surplus); replaced with an export
  penalty + charging reward proportional to 15% of the feed-in tariff,
  lowering the charging break-even from ~9.8 ct/kWh to ~7.6 ct/kWh
- Startup PV forecast race: poll up to 30 s after init_time for the PV
  forecast to populate before the first optimization run
- `max_charge_power` fallback: if battery data has not been fetched yet
  (first run), fall back to configured fixed value instead of passing 0 W
- 15-min mode gating: `local_evopt` is now allowed alongside `evopt` for
  `time_frame_base=900`; load profile uses `slots_per_hour` scaling

## Docs / schema export
- `docs/assets/data/config_schema.json`: regenerated (99 fields)
- `docs/user-guide/configuration.html`: local_evopt section added
- `docs/what-is/index.html`: updated feature list
- `README.md`: updated optimizer options

## Tests
782 passing (was 774); 8 new tests in `TestHotReloadLocalEVopt`
…e hot-reload

When the user toggles 'dyn_override_discharge_allowed_pv_greater_load'
via the web UI, the change now fires an immediate optimization run in
addition to updating the live attribute — same behaviour as the
local_evopt strategy fields.

Implementation:
- hot_reload.py: add _OPTIMIZER_RUN_TRIGGERS set; _apply_optimizer calls
  _fire_run_trigger when the key is in that set
- Extensible: any future optimizer hot-reload key that should trigger a
  run just needs to be added to _OPTIMIZER_RUN_TRIGGERS

Tests (test_hot_reload.py):
- test_dyn_override_fires_run_trigger: toggle fires the trigger
- test_timeout_does_not_fire_run_trigger: eos.timeout change does not"
Remove all language describing EOS Connect as a platform that relies on
external optimization engines. The built-in local_evopt is now the
default and works out of the box — no external server required.

what-is/index.html:
- Hero subtitle: 'built-in optimizer — and optional external backends'
- Intro paragraph: rewritten to lead with built-in MILP optimizer
- Removed the orange 'Important Understanding: primary role is
  integration' warning alert; replaced with a neutral info alert

docs/index.html:
- Hero subtitle updated
- 'Important: bridges your energy system with external engines' alert
  rewritten to 'what EOS Connect does' with local_evopt as default
- Backends list now lists local_evopt first (default, built-in)
- Key Features section updated to 3 backends, local_evopt first

user-guide/index.html:
- Section 'EOS/EVopt Server Setup' → 'External Backend Setup (Optional)'
- Opening sentence no longer says a backend is required
- Alert rewritten to list all three options with local_evopt as default"
hot_reload.py:
- Add _PRICE_RUN_TRIGGERS = {price.feed_in_price, price.feed_in_static_adder}
- _apply_price: fire run trigger after _recalculate_feedin for feed-in price
- _apply_feed_in_price: fire run trigger after update_prices for static adder
- Add _sync_feed_in_fixed_price(): update FeedInPriceInterface.fixed_price_ct_kwh
  and refresh its price array when price.feed_in_price changes hot — this is the
  interface the optimizer actually reads (price_interface was legacy-only)

eos_connect.py:
- Pass feed_in_price_interface to HotReloadAdapter (was missing — caused
  _sync_feed_in_fixed_price to silently no-op)

feed_in_price_interface.py:
- _fetch_fixed_price: apply static_adder_ct_kwh and multiplier (was silently
  ignored for fixed source; dynamic sources already applied them)

schema.py:
- feed_in_static_adder: add depends_on fixed source hidden (only relevant for
  elpris_dk / epex_spot — fixed users set price directly)
- feed_in_multiplier: same depends_on, hidden for fixed source

tests (793 pass):
- TestHotReloadFeedInPrice: test_feed_in_price_syncs_fixed_price_ct_kwh
- TestHotReloadPrice: test_feed_in_price_fires_run_trigger,
  test_fixed_price_adder_does_not_fire_run_trigger
- TestHotReloadFeedInPrice: static_adder fires run, multiplier does not,
  no-interface no-crash
- test_feed_in_price_interface: test_fixed_price_with_static_adder,
  test_fixed_price_with_multiplier

docs:
- configuration.html: hot-reload rows + depends_on notes for static_adder and
  multiplier; fixed source note added to both fields
- config_schema.json: regenerated (99 fields)
hot_reload.py:
- _apply_feed_in_price: narrow 'except Exception' to specific types (W0718)
- _sync_feed_in_fixed_price: same narrow exception catch (W0718)
- docstring: split long line (C0301)

tests/config_web/test_hot_reload.py:
- Move 'from zoneinfo import ZoneInfo' before pytest import (C0411)
- Remove trailing newline at end of file (C0305)

tests/interfaces/test_feed_in_price_interface.py:
- Move stdlib imports before third-party imports (C0411)
- Remove false startup warning for inverter.type="default" (display-only mode)
- Fix C0301 (line-too-long) violations by restructuring long lines
- Fix W0718 (broad-exception-caught) by catching specific exception types

Pylint: 10.00/10
- Fix misleading "unlimited" wording for max_grid_import_w and max_grid_export_w
- Clarify that 0 means "no additional constraint" (battery/inverter limits still apply)
- Update schema descriptions and regenerate config_schema.json
- Fix 22 line length violations (100 char limit)
- Add missing docstrings to 4 dataclass definitions
- Add type annotation for variables dictionary

No functional changes.
Add smart forecast extension to local optimizer that synthetically extends
the forecast with morning PV pattern when forecast ends during night hours.

This prevents expensive grid charging at end-of-horizon by teaching the
optimizer: "After night comes day with PV". The extension activates when:
- Forecast ends during nighttime (19:00-05:00)
- Last 6 slots contain <100 Wh (confirming nighttime)
- Adds 6 hours of conservative morning ramp [10-50%] at 06:00-12:00

PV capacity is extracted from the forecast data and used to scale the
morning pattern generation, ensuring realistic expectations aligned with
site history.

Implemented methods:
- _extend_forecast_with_morning_pv(): Detection & array extension logic
- _generate_morning_pv_pattern(): Conservative morning ramp generation

Test coverage: 4 new tests for extension logic, integration test with
optimize() flow, 24 tests validate pattern generation and skip conditions.

Also includes code quality improvements: attribute initialization, removed
unused imports/parameters, added class docstrings. All 34 tests passing.
Port the negative_price_switch logic from PriceInterface to the new
FeedInPriceInterface. When enabled, negative market prices are clamped
to 0 instead of being passed through to the optimizer.

Fixes: #255
The dashboard chart logic only recognized the "evopt" backend but not
"local_evopt", causing incorrect grid bar visualization during charging-only
periods. When local_evopt was active, the chart used EOS calculation logic
instead of EVopt logic, resulting in unwanted grid bars alongside charge bars.

Updated the backend detection to include both "evopt" (remote) and "local_evopt"
(in-process) backends, ensuring correct calculation:
- EVopt backends: gridValue = Netzbezug - ac_charge (charge bars only)
- EOS backends: gridValue = Netzbezug - (response_load - household_load)
…tream

penalty_base was accidentally changed to np.min() during the pylint
C0301 refactoring (0c8dc0c), capping instead of flooring the value.
This could silently zero all soft-constraint penalties when electricity
prices are near zero.

Restores upstream semantics:
  penalty_base = np.max([max_import_price, 0.1e-3])

Also expands the modifications docstring to enumerate all 7 actual
divergences from evcc-io/optimizer for licence traceability.
- Update README.md and documentation to reflect the shift from a "data gateway" to a self-contained optimization solution.
- Highlight the advantages of local_evopt (performance, privacy, reliability).
- Refine the "Intelligent Control Cycle" architecture description.
- Restored learning links for key features in README.md.
- Synchronized version display to v0.3.35 across all doc pages.
Files changed:
M	src/version.py
- Implement two-tier validation: lenient startup (logs warnings), strict hot-reload (logs errors)
- Remove sys.exit(1) calls on config validation errors in PvInterface and EOSBackend
- Add configuration_state and configuration_valid tracking across all interfaces
- Graceful degradation: start in DEGRADED mode instead of crashing
- Fix 10 pylint line-too-long violations (100 char limit compliance)
- Add 21 comprehensive two-tier validation tests, update 4 existing tests
- Resolves web config migration dead-loop: users can now access web UI to fix incomplete config
- Pylint: 10.00/10 ✓ | Tests: 60/60 passing ✓ | No regressions

Fixes: #259 (and prevents dead-loop from web config migration)
ohAnd and others added 21 commits June 11, 2026 19:28
…lls (issue #253)

- Remove deprecated inverter.url/token fields from schema
- Consolidate HA credentials at data_source level via merger injection
- Add three JSON-type fields for mode-sequence service call definitions
- Implement cross-field dependencies (inverter depends on data_source)
- Add JSON textarea field type with on-blur validation to web UI
- Extend CSS with dark-theme JSON field styling
- Update InverterHA to parse JSON service call sequences
- Fix address logging bug (override schema default with actual HA URL)
- Add comprehensive test suite (14 new tests, all 289 passing)
- Update documentation with user-facing configuration guide

Fixes: #253
Files changed:
M	src/version.py
Allow users to disable SSL certificate verification for Home Assistant and
OpenHAB connections with self-signed or private CA certificates. Adds config
field, passes verify parameter to all HTTP requests, and logs security warnings.

- New `data_source.ssl_ignore` config field (expert level)
- LoadInterface respects setting in __request_with_retries()
- Added tests for SSL verify behavior (all 22 existing tests pass)
Extend ssl_ignore feature from LoadInterface to BatteryInterface and
InverterHA, enabling self-signed certificate support across all HTTPS
connections to Home Assistant and OpenHAB.

Implementation:
- Add ssl_ignore extraction and injection in merger.py
  (both _apply_data_source_inheritance and _apply_inverter_data_source_injection)
- Read ssl_ignore config and control requests.get/post verify parameter
  in BatteryInterface and InverterHA
- Add comprehensive test coverage (23 new tests)
- Add proof-of-concept tests demonstrating verify parameter behavior

All 853 tests passing. Documentation already in place (README.md, GitHub Pages).

Fixes: #254
Add SSL Certificate Verification Control
Files changed:
M	src/version.py
Implement flexible timeseries support for both electricity prices and PV forecasts,
enabling integration with Home Assistant sensors and custom HTTP APIs without source-
specific configuration duplication.

**New Features:**
- Add "timeseries" as price source with HTTP endpoint support
- Add "timeseries" as PV forecast source with HTTP endpoint support
- Implement central Home Assistant data source reuse (avoid credential repetition)
- Add pre-flight validation for Home Assistant sensor existence

**Configuration:**
- 10 new schema fields: price.use_ha_central_data_source, price.ha_sensor_name,
  price.data_url, price.data_path, price.data_token + PV equivalents
- All timeseries fields support hot-reload (changes apply without restart)
- Standardized JSON format for both sources: [{start, end, value}, ...]

**Hot-Reload Behavior:**
- Immediate price fetch when switching TO timeseries
- Deferred fetch when switching FROM timeseries (prevents incomplete config errors)
- Immediate PV reload for summarized sources (timeseries, evcc)
- Debounced reload for per-installation sources (akkudoktor, openmeteo, etc.)

**Implementation Details:**
- PriceInterface: __retrieve_prices_from_url() with timeseries parsing
- Automatic resolution detection (900s vs 3600s) with conversion
- Value range validation and clamping (-0.5 to 1.0 EUR/Wh)
- Support for both Home Assistant sensors and custom APIs
- Pre-flight validation checks sensor existence before saving

**Documentation:**
- Updated GitHub Pages with  timeseries configuration guide
- Added JSON path reference for custom API responses
- Included Home Assistant integration examples
- Updated README.md with timeseries mention

**Testing:**
- 42 new timeseries parsing tests covering format, resolution, averaging, validation
- 8 new hot-reload behavior tests for price/PV sources
- 3 new merger tests for central HA data source injection
- Pre-flight validation test for sensor name changes

Fixes: timeseries support for users with Home Assistant or custom price/PV APIs -> #214
Files changed:
M	src/version.py
Move resource_id from pv_forecast array entries to pv_forecast_source
section and reclassify sources as location-based vs non-location-based.

Architecture:
- Added LOCATION_BASED_PV_SOURCES constant for code reuse
- resource_id now in pv_forecast_source (solcast, victron only)
- Simplified depends_on rules via constant references

Configuration:
- Location-based sources (4): akkudoktor, openmeteo, forecast_solar,
  openmeteo_local — require PV Installations array
- Non-location-based sources (5): default (built-in), solcast (resource ID),
  victron (resource ID), evcc (from EVCC instance), timeseries (HTTP/HA)

UX:
- Added source-specific messages in config panel
- Each source explains where its data is configured
- Updated documentation with requirements matrix
Files changed:
M	src/version.py
… price switching

- Implement EVCC /api/tariff/grid price fetching with 3-tier fallback
  (energyforecast.de smart prediction → yesterday prices → today repetition)
- Fix hot-reload: properly update price_interface.src on config changes
- Add cross-field validation: EVCC source requires EVCC URL configured
- Add comprehensive test suite (11 new tests, all passing)
- Update docs: EVCC configuration guide (164 lines)

fix allow EVCC as price source (part 1)
Fixes #176
Add EVCC as new feed-in (export) price source option:
- Users can now configure EVCC's /api/tariff/feedin for battery discharge optimization
- Supports 4 feed-in sources: fixed, elpris_dk, epex_spot, evcc
- Proper tariff parsing and EUR/kWh → EUR/Wh conversion
- Prices used as-is (no adder/multiplier applied, like grid EVCC)

Bonus: Enable hot reload for feed-in source/zone switching:
- Users can switch sources live without app restart
- Immediate price fetch on source change
- Same UX pattern as grid price source switching

Changes:
- schema.py: Add "evcc" option, enable hot_reload for source/zone
- feed_in_price_interface.py: Implement _fetch_evcc_prices(), fix API endpoint
- hot_reload.py: Implement _schedule_feedin_reload() for live switching
- Configuration docs: Mark fields hot-reloadable, add EVCC setup guide
- Tests: 11 EVCC integration + 5 hot reload tests

fix allow EVCC as price source (part 2)
Fixes #176
- Rename display groups for clearer user intent:
  - "Grid Price Provider" (source selection)
  - "Grid Price - Adjustments" (cost modifications)
  - "Grid Price - Forecast (Advanced)" (smart prediction)
  - "Feed-In Price" (export pricing, green-themed)
- Remove duplicate subsection headers
- Preserve green styling for Feed-In Price section
- No functional changes; config behavior unchanged
…ental label

- Remove "experimental" label from energyforecast fields (enabled, token, market_zone)
- Update documentation to reflect production-ready status
- Feature has been well-tested over extended period
Files changed:
M	src/version.py
…nfig

- Remove 450+ lines of old full config generation code
- config.yaml now manages ONLY 3 bootstrap keys (eos_connect_web_port, time_zone, log_level)
- All other settings (111 fields) are managed via web UI + SQLite store
- Improves maintainability and aligns with web-based config architecture

Includes:
- config.yaml creation on fresh install
- Fix pv_forecast list format in defaults
- Update tests to match bootstrap-only architecture
- All 914 tests pass
Files changed:
M	src/version.py
The dashboard Info menu was missing support for the local_evopt backend
and would show "EOS@akkudoktor" regardless of which backend was selected.

Now correctly displays:
- "Local EVOpt (built-in)" when local_evopt is active
- "EVOpt @ EVCC" when evopt is selected
- "EOS@akkudoktor" when eos_server is active
Files changed:
M	src/version.py
Comment thread src/config_web/api.py Fixed
Comment thread src/interfaces/pv_interface.py Dismissed
Comment thread src/interfaces/pv_interface.py Dismissed
Comment thread src/interfaces/pv_interface.py Dismissed
Comment thread src/interfaces/pv_interface.py Dismissed
Comment thread src/interfaces/pv_interface.py Dismissed
@ohAnd
ohAnd merged commit be567d3 into main Jun 23, 2026
7 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants