Data & sensors

Where EOS Connect reads your house from — the home-automation connection, the sensors it measures consumption with, and the plain-array format for anything it has no integration for.

What this is for

  • I want EOS Connect to read my house — what it draws, what the battery is doing — from Home Assistant or openHAB.
  • I want to hand it numbers it has no integration for, as a plain array.
  • My history has gaps and I want to know what it does with them.

Two settings groups live here: data_source.*, the connection to your home automation, and load.*, the sensors it reads your household consumption from.

Where the measurements come from

One connection, used for every sensor you name anywhere in EOS Connect. Home Assistant and openHAB are read over their REST APIs; see Home Assistant and openHAB for what each needs at its end, and Testing one sensor for checking an entity before you save it.

Household consumption

The load forecast is built from what the same weekday drew 7 and 14 days ago, so these sensors are what every plan is measured against. Appliances that forecast cannot follow belong under Managed loads instead — including the two settings that bound them all together, which are in this group.

Data quality and gaps

Optimization needs a complete array of values for every slot in the horizon. Real sensor history has holes — a restart, a network blip, an integration that stopped recording.

EOS Connect detects incomplete data and forward-fills it, carrying the last known value across the gap rather than passing a null through to the optimizer. The log names what it filled, so a persistent gap is visible instead of silently degrading your plan.

If a sensor is missing entirely, EOS Connect falls back to a built-in default and says so in the log — it never quietly polls an entity you did not configure. Use the Test button beside any sensor field to read it and see the current value.

Unified Timeseries Data Source Guide

EOS Connect supports a unified timeseries source for both electricity prices and PV forecasts. It fetches data from Home Assistant, custom HTTP APIs, or any endpoint that returns timeseries data in the expected format.

The expected format is EVCC's format. That is deliberate: it is the format you most likely already have. An EVCC endpoint such as /api/tariff/grid can be used as-is, and a Home Assistant template sensor written to feed EVCC works unchanged. Home Assistant is the transport here (state API, entity attributes, bearer token) — the format comes from EVCC.

EOS Connect accepts exactly this one format and does not try to guess foreign attribute names. Where an integration uses different names, you shape it once with a Home Assistant template sensor — see Home Assistant Template Snippets for ready-made examples.

Changed in this release: The unit of value now matches what EVCC and the common Home Assistant integrations actually deliver: EUR/kWh for prices and W for PV. Previously EOS Connect expected EUR/Wh and Wh-per-slot — units no real source provides.

If you already run a timeseries source, check it after updating: set price.value_unit / pv_forecast_source.value_unit to whatever your source actually delivers. Selecting EUR/Wh resp. Wh restores the previous behaviour exactly. Use Test connection to see the resulting values before saving.

Timeseries Data Format

The timeseries source expects JSON data in this format:

{
  "data": [
{
  "start": "2026-08-23T00:00:00+02:00",
  "end": "2026-08-23T00:15:00+02:00",
  "value": 0.3811
},
{
  "start": "2026-08-23T00:15:00+02:00",
  "end": "2026-08-23T00:30:00+02:00",
  "value": 0.3727
}
  ]
}
Field Description Format
start Required. Start timestamp of the timeslot. Always include the UTC offset — a timestamp without one is read as local time, which silently shifts every slot. ISO8601 (e.g., "2026-08-23T00:00:00+02:00" or "…Z"), or Unix timestamp
end Optional. If absent, EOS Connect derives it from the next entry's start (and the last entry from the preceding interval), so a source that only publishes start times is accepted. ISO8601 or Unix timestamp
value Required.
For Prices: price per slot, by default in EUR/kWh (e.g. 0.3811 for 38.11 ct/kWh) — as EVCC's rates deliver it.
For PV: generated power per slot, by default in W — as EVCC's solar forecast delivers it.
Use value_unit if your source uses a different unit.
Number (float)

Value Unit

If your source does not use the default unit, select the matching one instead of building a conversion into your template:

Setting Options Default
price.value_unit EUR/kWh, ct/kWh, EUR/Wh EUR/kWh
pv_forecast_source.value_unit W, kW, Wh, kWh W
Power vs. energy for PV: W and kW are power readings and are integrated over the slot length — 4000 W across a 15-minute slot becomes 1000 Wh. Wh and kWh are taken as the energy of that slot directly. Picking the wrong one is a factor-of-four error on 15-minute data, so use Test connection if you are unsure.
Time Resolution: EOS Connect auto-detects whether the timeseries is 15-minute (900s) or hourly (3600s) from the timestamp differences. 15-minute data is converted to hourly automatically — prices are averaged, PV energy is summed. An hourly source cannot serve a system configured for 15-minute slots; the connection test reports that rather than letting it fail at runtime.
All-or-nothing parsing: if a single entry is malformed — a null value, an unparseable timestamp, a missing field — the whole payload is rejected and EOS Connect keeps using the last good data. Skipping just the bad entry would shift every following hourly price by one slot, which is not visible anywhere in the UI. The log names the offending entry by index.

Home Assistant Integration

Home Assistant entity attributes can be accessed using the dot notation in data_path.

Price Example (Home Assistant)

Configuration Value
price.source timeseries
price.data_url http://homeassistant.local:8123/api/states/sensor.grid_prices
price.data_path attributes.data
price.data_token Your HA Long-Lived Access Token (optional if local)

HA Entity Response Example:

{
  "entity_id": "sensor.grid_prices",
  "attributes": {
"data": [
  {"start": "2024-06-12T14:00:00Z", "end": "2024-06-12T15:00:00Z", "value": 0.25},
  {"start": "2024-06-12T15:00:00Z", "end": "2024-06-12T16:00:00Z", "value": 0.28}
]
  }
}

PV Forecast Example (Home Assistant)

Configuration Value
pv_forecast_source.source timeseries
pv_forecast_source.data_url http://homeassistant.local:8123/api/states/sensor.solar_forecast
pv_forecast_source.data_path attributes.forecast
pv_forecast_source.data_token Your HA Long-Lived Access Token (optional if local)

Custom HTTP API Integration

Connect to custom HTTP endpoints that return timeseries data. Supports authentication via Bearer tokens.

Example: Custom REST API

Configuration Value
price.source timeseries
price.data_url https://api.example.com/v1/prices/current
price.data_path prices (or nested path like result.data)
price.data_token Your API token (if required)

API Response Example:

{
  "prices": [
{"start": "2024-06-12T14:00:00Z", "end": "2024-06-12T15:00:00Z", "value": 0.25},
{"start": "2024-06-12T15:00:00Z", "end": "2024-06-12T16:00:00Z", "value": 0.28}
  ]
}

Home Assistant Template Snippets

Home Assistant integrations name their attributes differently — Tibber and EPEX use start_time and price_per_kwh, Solcast uses period_start and pv_estimate. EOS Connect does not guess these names. Instead you publish one template sensor in the expected format; adapting to a different provider then means editing the template, not reconfiguring EOS Connect.

Because end is derived automatically, the templates only need start and value.

Prices: Tibber Price Information / EPEX Spot (HACS)

Both provide a data attribute with start_time and price_per_kwh (EUR/kWh):

template:
  - trigger:
  - platform: time_pattern
    minutes: "/5"
sensor:
  - name: eos_grid_prices
    state: "ok"
    attributes:
      data: >
        {% set src = state_attr('sensor.YOUR_PRICE_SENSOR', 'data') %}
        [
        {%- for e in src %}
          {"start": "{{ e.start_time }}", "value": {{ e.price_per_kwh }}}
          {%- if not loop.last %},{% endif %}
        {%- endfor %}
        ]

Then set price.data_url to http://homeassistant.local:8123/api/states/sensor.eos_grid_prices, price.data_path to attributes.data and price.value_unit to EUR/kWh.

Prices: Tibber core integration (via action)

The built-in Tibber integration no longer exposes the price list as a sensor attribute. Its action response is keyed by address and uses start_time and price, so fetch it in an automation and feed the result into a trigger-based template sensor built the same way as above:

{% set src = prices['YOUR_ADDRESS'] %}
[
{%- for e in src %}
  {"start": "{{ e.start_time }}", "value": {{ e.price }}}
  {%- if not loop.last %},{% endif %}
{%- endfor %}
]

PV forecast: Solcast

Based on the template shared by @bennobiber in discussion #214, which already feeds EVCC. value stays in W, matching the default pv_forecast_source.value_unit.

template:
  - trigger:
  - platform: time_pattern
    minutes: "/5"
sensor:
  - name: eos_pv_forecast
    state: "ok"
    attributes:
      data: >
        {% set today = state_attr('sensor.solcast_pv_forecast_forecast_today', 'detailedForecast') %}
        {% set tomorrow = state_attr('sensor.solcast_pv_forecast_forecast_tomorrow', 'detailedForecast') %}
        {% set all = (today if today else []) + (tomorrow if tomorrow else []) %}
        [
        {%- for e in all %}
          {"start": "{{ e.period_start.isoformat() }}", "value": {{ (e.pv_estimate * 1000) | round(0) }}}
          {%- if not loop.last %},{% endif %}
        {%- endfor %}
        ]
Use .isoformat(), not | timestamp_utc: timestamp_utc renders UTC wall-clock time without an offset. EOS Connect then reads it as local time and every slot is shifted by your UTC offset. period_start.isoformat() keeps the offset. If you already use such a template for EVCC, adjust this one line.

Testing Your Timeseries Configuration

Use Test connection in the configuration UI, next to the timeseries settings. It fetches the endpoint, resolves data_path, parses the payload and shows the first slots converted into the unit the schedule uses — so a wrong value_unit shows up as an absurd number before you save, rather than hours later in the schedule. It tests the values currently in the form, including unsaved ones.

The same check runs automatically when you save a timeseries setting; a hard failure blocks the save and is reported on the field that caused it, while a plausibility warning does not block.

HTTP Request:

POST /api/config/test-timeseries
Content-Type: application/json

{
  "domain": "price",
  "price.data_url": "http://homeassistant.local:8123/api/states/sensor.eos_grid_prices",
  "price.data_path": "attributes.data",
  "price.value_unit": "EUR/kWh"
}

All keys are optional — anything omitted falls back to the stored configuration. domain is price (default) or pv.

Response (Success):

{
  "ok": true,
  "entry_count": 192,
  "resolution_seconds": 900,
  "value_unit": "EUR/kWh",
  "slots": [
{"start": "2026-08-23T00:00:00+02:00", "end": "2026-08-23T00:15:00+02:00",
 "value": 38.11, "unit": "ct/kWh"}
  ],
  "warnings": []
}

Response (Format mismatch): the message names the fields the payload actually contained, so you can see what to map in your template:

{
  "ok": false,
  "field": "price.data_path",
  "error": "missing required field 'start' in the first entry (available fields:
        'start_time', 'price_per_kwh'). The expected format is {start, end, value}
        - shape the source with a Home Assistant template sensor, see
        configuration.html#timeseries-templates"
}

Error Handling & Retries

EOS Connect automatically handles transient API failures:

  • Automatic Retries: Up to 3 attempts with exponential backoff (0.5s → 2s → 4s)
  • Cache Fallback: If API fails, uses the last successfully fetched data
  • Graceful Degradation: Continues running with cached data if available
  • Error Logging: Issues are logged with timestamps for troubleshooting

Hot-Reload Support

All timeseries configuration fields support hot-reload — changes take effect immediately without restarting the application:

  • price.data_url, price.data_path, price.data_token, price.value_unit
  • pv_forecast_source.data_url, pv_forecast_source.data_path, pv_forecast_source.data_token, pv_forecast_source.value_unit

Changes are applied within 1-2 seconds on the next update cycle.

JSON Path Reference

Examples of how to specify data_path for different response structures:

Response Structure data_path Notes
{"data": [...]} data Top-level array
{"attributes": {"data": [...]}} attributes.data Nested object (Home Assistant pattern)
{"result": {"prices": [...]}} result.prices Multiple levels of nesting
{"forecast": [{"data": [...]}]} forecast[0].data Array with indexed access