Sensor templating with attributes

I’m trying to make my “car charging based on electricity prices” slightly more user friendly. Currently it looks like:


…where columns are the electricity price, the line is prediction of the price for tomorrow (real prices coming somewhere in the afternoon), and the white area is the scheduled car charging time. Note that I have asked the charging to be ready by 23:00, in real life I’d ask the charging be ready by 8am tomorrow, but then there is no feedback on when charging would occur (no white area), until the new prices come out. Wanted to illustrate here what the problem looks like.

What I would like to do is that the EV charging controller would use the real prices if they exist, and prediction if the real prices don’t exist. I.e. able the show the white area even if there is no certainty on the tomorrow prices (the charging controller will fine tune that anyway when the prices come out). For this I’m trying to create a sensor that would get the attributes conditionally depending on the existence of the real prices.

Here’s the nordpool sensor format:

And here’s the prediction sensor format:


Little extra challenge from the fact that the needed prediction values are attributes number 49-72 (the prediction includes yesterday (1-24), today (25-48), which are not interesting).

My code, that doesn’t work:

- platform: template
  sensors:
    nordpool_prices_real_and_estimate:
      unique_id: nordpool_prices_real_and_estimate
      friendly_name: 'Nordpool prices real and estimate'
      value_template: > #Not really relevant
        {{ states('sensor.nordpool_kwh_fi_eur_3_095_0255') }}
      attribute_templates:
        time: > #Just take the date/time from the prediction sensor attributes prediction-timestamp
          {% set prediction = state_attr('sensor.nordpool_prediction', 'prediction') %}
          {% set attributes = [] %}
          {% for i in range(25, 72) %}
            {% set attributes = attributes + [prediction[i][0]] %}
          {% endfor %}
          {{ attributes }}
        price: > #Conditional depending on tomorrow_valid
          {% set raw_today = state_attr('sensor.nordpool_kwh_fi_eur_3_095_0255', 'raw_today') %}
          {% set raw_tomorrow = state_attr('sensor.nordpool_kwh_fi_eur_3_095_0255', 'raw_tomorrow') %}
          {% set tomorrow_valid = state_attr('sensor.nordpool_kwh_fi_eur_3_095_0255', 'tomorrow_valid') %}
          {% set prediction = state_attr('sensor.nordpool_prediction', 'prediction') %}
          {% set attributes = [] %}
          {% for i in range(0, 24) %}
            {% set attributes = attributes + [raw_today[i][2]] %}
          {% endfor %}
          {% if tomorrow_valid %}
            {% for i in range(0, 24) %}
          {% set attributes = attributes + [raw_tomorrow[i][2]] %}
            {% endfor %}
          {% else %}
            {% for i in range(49, 72) %}
          {% set attributes = attributes + [prediction[i][1]] %}
            {% endfor %}
          {% endif %}
          {{ attributes }}

The sensor value is ok, but attributes are null. I really don’t know if the syntax raw_today[i][2] makes any sense, but have no idea how to point to attribute list items. Indeed, I’m no programmer, so in the mercy of google here, but appreciating even more help of humans.

@TheFes already has a solution to this with a macro specifically built to use nordpool results.

Looks like he wants to use the prediction sensor if no actual prices are published yet. I don’t use this prediction sensor in my macro.

Anyway, you need to use namespaces to use the data generated in your for loop :slight_smile:

So, without checking if your code works, that means:

{% set prediction = state_attr('sensor.nordpool_prediction', 'prediction') %}
{% set ns = namespace(attributes=[]) %}
{% for i in range(25, 72) %}
  {% set ns.attributes = ns.attributes + [prediction[i][0]] %}
{% endfor %}
{{ ns.attributes }}
1 Like

Where do you find the prediction integration?

From GitHub - vividfog/nordpool-predict-fi: A Python app and ML model that predicts spot prices for the Nordpool FI market.

Thanks mates! It looks like there is a ton of answers on this topic in the community already. However, without the right terminology and the example I would have never ever found them. Believe me, I tried. Using @Troon example as starting point I now believe I got the solution. I’ll post it tomorrow as I can validate it only after midnight. Took some few hours, but that is relatively short time when I’m coding. Last problem took two months to solve.

@Hellis81, the prediction is quite easy to illustrate on apexchart (vividfog has very detailed instructions in git), but using the prediction in automation is a bit more tricky. Of course someone more skilled could probably make it easier, but I’m in a position to do what I can, not what I want.

Ok, after validation I needed to fix quite a number of things. Including tuning the parameters to fit the format the EV charging controlling integration requires. Anyway, here we go:

- sensor:
    - name: nordpool_prices_real_and_estimate
      unique_id: nordpool_prices_real_and_estimate
      state: >
        {{ states('sensor.nordpool_kwh_fi_eur_3_095_0255') }}
      attributes:
        prices_today: >-
          {% set ns = namespace(items=[]) %}
          {% for i in states.sensor.nordpool_kwh_fi_eur_3_095_0255.attributes.raw_today %}
            {% set ns.items = ns.items + [ {'time': (as_timestamp(i.start))|timestamp_local , 'price': i.value} ] %}
          {% endfor %}
          {{ ns.items }}
        prices_tomorrow: >-
          {% set ns = namespace(items=[]) %}
          {% set tomorrow_valid = state_attr('sensor.nordpool_kwh_fi_eur_3_095_0255', 'tomorrow_valid') %}
          {% if tomorrow_valid %}
            {% for i in states.sensor.nordpool_kwh_fi_eur_3_095_0255.attributes.raw_tomorrow %}
              {% set ns.items = ns.items + [ {'time': (as_timestamp(i.start))|timestamp_local , 'price': i.value} ] %}
            {% endfor %}
          {% else %}
            {% for i in states.sensor.nordpool_prediction.attributes.prediction %}
              {% if as_timestamp(i.timestamp) < as_timestamp(today_at('23:59'))+86400 and as_timestamp(i.timestamp) >= as_timestamp(today_at('00:00'))+86400 %}
                {% set ns.items = ns.items + [ {'time': (as_timestamp(i.timestamp))|timestamp_local , 'price': i.value/100} ] %}
              {% endif %}
            {% endfor %}
          {% endif %}
          {{ ns.items }}

I’m guessing the “+86400” could be somehow more elegant (pointing directly to right values without if-statement), but hey, it works and I understand why.

Will need to follow the behaviour now for few days, but so far looks great!

1 Like

Could be

today_at('00:00') + timedelta(days = 1)

And it will work properly even on DST

1 Like