Summary
The "Energy Prediction" health check — shown under Settings → System tab (diagnostics/health section) and described in code as "Solar and consumption forecasting for optimization" — always validates the sensor consumption strategy, regardless of which strategy the user has actually selected (sensor / fixed / influxdb_7d_avg / ha_statistics).
As a result the health card does not reflect the chosen forecast provider. It can show a passing/flat consumption value while the optimizer is using a completely different (correct) source, or it can flag consumption as broken when the optimizer doesn't even use the checked sensor.
Where it is
- UI: Settings → System tab → health/diagnostics.
- Code:
core/bess/sensor_collector.py:745-756 (check_prediction_health):
return perform_health_check(
component_name="Energy Prediction",
description="Solar and consumption forecasting for optimization",
is_required=False,
controller=self.ha_controller,
all_methods=[
"get_estimated_consumption", # hardcoded -> 'sensor' strategy
"get_solar_forecast",
],
)
- Health-check registry entry:
core/bess/ha_api_controller.py:224-230 maps get_estimated_consumption → name "Average Hourly Power Consumption", sensor key 48h_avg_grid_import.
get_estimated_consumption itself (ha_api_controller.py:1049-1071) reads the single 48h_avg_grid_import sensor and returns a flat 96-period array — this is the sensor strategy's data source only.
Root cause
There are three consumers of consumption-forecast data, and only the health check is not strategy-aware:
| Consumer |
Source |
Strategy-aware? |
Optimizer — _get_consumption_forecast() (battery_system_manager.py:969-1023) |
dispatches on consumption_strategy |
✅ yes |
Forecast comparison view — get_consumption_forecast_comparison() (battery_system_manager.py:895-967) |
computes all 4 strategies, marks is_active |
✅ yes |
Energy Prediction health check — sensor_collector.py:745-756 |
hardcoded get_estimated_consumption (sensor) |
❌ no |
Impact / failure modes
- False positive (observed): With
ha_statistics (or fixed/influxdb_7d_avg) selected, the card shows the flat sensor value. This masks whether the chosen strategy is actually delivering a varying profile — and specifically hides the case where ha_statistics silently falls back to fixed due to insufficient HA Recorder data (battery_system_manager.py:1001-1021). This directly caused real confusion: switching to ha_statistics looked like it did nothing because the health card stayed flat.
- False negative: With
ha_statistics selected but the 48h_avg_grid_import sensor not configured, the health check flags consumption as failing even though the optimizer never uses that sensor.
In both cases a component literally described as "consumption forecasting for optimization" is validating something other than what the optimizer uses.
Proposed fix
Make the consumption portion of the Energy Prediction health check follow the active strategy — i.e. validate the same path the optimizer uses (_get_consumption_forecast()), or reuse the is_active entry from get_consumption_forecast_comparison() (which already knows all four strategies and whether each is available).
Desired behaviour:
- The card passes/fails based on the user's selected forecast provider.
- It reflects the actual forecast the optimizer will use (varying for
ha_statistics/influxdb_7d_avg, flat for sensor/fixed).
- It surfaces when
ha_statistics has fallen back to fixed (insufficient data), rather than hiding it behind a flat sensor reading.
Design considerations
- The health-check framework (
perform_health_check + the registry in ha_api_controller.py) is currently keyed by static sensor-method names. Making the consumption check strategy-aware is therefore more than a one-line swap: the consumption check needs to dispatch on the active strategy instead of pointing at a fixed method. Decide whether to:
- special-case the consumption check to call
_get_consumption_forecast() / the comparison's active entry, or
- extend the framework to support a "resolve method by active strategy" check type.
- Keep
get_solar_forecast validation as-is.
- Consider whether the registry name "Average Hourly Power Consumption" should be relabeled to reflect that it represents the active forecast, not specifically the 48h-average sensor.
Acceptance criteria
Relevant references
core/bess/sensor_collector.py:745-756
core/bess/ha_api_controller.py:224-230, :1049-1071
core/bess/battery_system_manager.py:895-967 (comparison), :969-1023 (optimizer dispatch + ha_statistics fallback)
Summary
The "Energy Prediction" health check — shown under Settings → System tab (diagnostics/health section) and described in code as "Solar and consumption forecasting for optimization" — always validates the
sensorconsumption strategy, regardless of which strategy the user has actually selected (sensor/fixed/influxdb_7d_avg/ha_statistics).As a result the health card does not reflect the chosen forecast provider. It can show a passing/flat consumption value while the optimizer is using a completely different (correct) source, or it can flag consumption as broken when the optimizer doesn't even use the checked sensor.
Where it is
core/bess/sensor_collector.py:745-756(check_prediction_health):core/bess/ha_api_controller.py:224-230mapsget_estimated_consumption→ name"Average Hourly Power Consumption", sensor key48h_avg_grid_import.get_estimated_consumptionitself (ha_api_controller.py:1049-1071) reads the single48h_avg_grid_importsensor and returns a flat 96-period array — this is thesensorstrategy's data source only.Root cause
There are three consumers of consumption-forecast data, and only the health check is not strategy-aware:
_get_consumption_forecast()(battery_system_manager.py:969-1023)consumption_strategyget_consumption_forecast_comparison()(battery_system_manager.py:895-967)is_activesensor_collector.py:745-756get_estimated_consumption(sensor)Impact / failure modes
ha_statistics(orfixed/influxdb_7d_avg) selected, the card shows the flatsensorvalue. This masks whether the chosen strategy is actually delivering a varying profile — and specifically hides the case whereha_statisticssilently falls back tofixeddue to insufficient HA Recorder data (battery_system_manager.py:1001-1021). This directly caused real confusion: switching toha_statisticslooked like it did nothing because the health card stayed flat.ha_statisticsselected but the48h_avg_grid_importsensor not configured, the health check flags consumption as failing even though the optimizer never uses that sensor.In both cases a component literally described as "consumption forecasting for optimization" is validating something other than what the optimizer uses.
Proposed fix
Make the consumption portion of the Energy Prediction health check follow the active strategy — i.e. validate the same path the optimizer uses (
_get_consumption_forecast()), or reuse theis_activeentry fromget_consumption_forecast_comparison()(which already knows all four strategies and whether each is available).Desired behaviour:
ha_statistics/influxdb_7d_avg, flat forsensor/fixed).ha_statisticshas fallen back tofixed(insufficient data), rather than hiding it behind a flat sensor reading.Design considerations
perform_health_check+ the registry inha_api_controller.py) is currently keyed by static sensor-method names. Making the consumption check strategy-aware is therefore more than a one-line swap: the consumption check needs to dispatch on the active strategy instead of pointing at a fixed method. Decide whether to:_get_consumption_forecast()/ the comparison's active entry, orget_solar_forecastvalidation as-is.Acceptance criteria
ha_statisticswith sufficient data shows a varying profile (not the flat sensor value); with insufficient data it indicates the fallback tofixed.ha_statisticswithout the48h_avg_grid_importsensor does NOT report a consumption failure (that sensor is irrelevant to the active strategy).Relevant references
core/bess/sensor_collector.py:745-756core/bess/ha_api_controller.py:224-230,:1049-1071core/bess/battery_system_manager.py:895-967(comparison),:969-1023(optimizer dispatch + ha_statistics fallback)