Zonneplan ONE custom component

Has anyone created a custom sensor that calculates the average price of that day? How could that be done?

In the current_tarrif attributes the details of upcoming (and past) prices are shown. However the ‘last’ time slot is that of 22:00 (see below) while the app shows also 23:00 to 24:00

Is there a reason for this? Is there some kind of offset as the price seems to be the one of 23:00 to 24:00

Last attribute:

- price: 2731696
  electricity_price: 2731696
  tariff_group: normal
  solar_percentage: 0
  solar_yield: 0
  datetime: '2023-01-13T22:00:00.000000Z'
  sustainability_score: 472
  carbon_footprint_in_grams: 1921

Answering my own question: Someone has been very helpful, solution to be found here

That’s GMT/UTC

Ouch. That makes making custom sensors based on the attribute date extremely complicated.

In the end Zonneplan is Dutch. @minifranske Is there anyway this can be made CET?

That should be fine… works with apex; date/time is stored as UTC an HA will automatically show the applied time zone; same should be for template sensors.

I would need to check manual. But take below sensor. It compares with now().date(); Are you sure it then automatically takes 1 hour from the previous day and not just the 23 hours it can find for today?

- platform: template
  sensors:
    avg_energy_price:
      friendly_name: Average current energy price
      value_template: >
        {% set ns = namespace(sum = 0, count = 0) %}
        {% for item in state_attr('sensor.zonneplan_current_electricity_tariff', 'forcast') -%}
          {% if as_datetime(item.datetime).date() == now().date()  %}
            {% set ns.sum = ns.sum + item.price %}
            {% set ns.count = ns.count + 1 %}
          {% endif %}
        {%- endfor %}
        {{ (ns.sum/ns.count/100000) }}

If you change the data generator to below you can also get extremas in the graph:

            return entity.attributes.forcast.map((entry) => {
              return [new Date(entry.datetime).getTime(), entry.price /100000] ;
            });

For the colors in the graph: Instead of a static value to set the color threshold you can also adjust based on (in my case) average.

Example below

  - type: custom:config-template-card
    variables:
      MOVINGAVERAGE: states['sensor.avg_energy_price_cnt']
    entities:
      - ${MOVINGAVERAGE.entity_id}
    card:
      type: custom:apexcharts-card
      apex_config:
        chart:
          height: 200px
          fontFamily: Raleway,sans-serif
        xaxis:
          labels:
            format: HH
        legend:
          show: false
        stroke:
          width: 2
        plotOptions:
          bar:
            columnWidth: 100%
        grid:
          show: true
          borderColor: '#00000030'
          strokeDashArray: 4
          position: back
        dataLabels:
          offsetY: -8
          background:
            opacity: 0.01
            enabled: true
            foreColor: '#CF7524'
            padding: 2
            borderRadius: 4
            borderWidth: 0
          style:
            fontSize: 9px
            color: rgb(200,200,200)
      experimental:
        color_threshold: true
      graph_span: 30h
      span:
        start: day
        offset: +4h
      update_interval: +1h
      header:
        title: Zonneplan Forecast
        show: false
      now:
        show: true
        label: NOW
      series:
        - entity: sensor.zonneplan_current_electricity_tariff
          color_threshold:
            - value: ${MOVINGAVERAGE.state * .75}
              color: '#228B22'
            - value: ${MOVINGAVERAGE.state * 1}
              color: '#d35400'
            - value: ${MOVINGAVERAGE.state * 1.25}
              color: '#c0392b'
          show:
            extremas: true
          type: column
          float_precision: 2
          data_generator: |
            return entity.attributes.forcast.map((entry) => {
              return [new Date(entry.datetime).getTime(), entry.price /100000] ;
            });
      yaxis:
        - id: '1'
          decimals: 1
          min: 0.1
          apex_config:
            tickAmount: 4

This one has an attribute with the last date_time of update:

- platform: template
  sensors:
    zonneplan_gas_prijs:
      friendly_name: "Zonneplan Gasprijs"
      unit_of_measurement: €/m³
      device_class: monetary
      value_template: >-
        {% for i in states.sensor.enever_gasprijs.attributes.data %}
        {{ i.prijsZP }}
        {% endfor %}
      attribute_templates:
        datum: >-
          {% for i in states.sensor.enever_gasprijs.attributes.data %}
          {{ i.datum }}
          {% endfor %}

@Tyfoon Cool graph. I have it working.
How did you make the circles with the pricing and the prediction of the cheapest?

The sensors on top are using ‘mushroom’ custom lovelace templates. Below is the full code.

The sensors are template sensors. Most of that code can be found in this post

type: custom:stack-in-card
cards:
  - type: horizontal-stack
    cards:
      - type: custom:mushroom-template-card
        entity: sensor.avg_energy_price
        secondary: >
          {{ states('sensor.lowest_price') | round(1) }}/{{
          states('sensor.highest_price') | round(1) }} 
        primary: |
          {{ states('sensor.avg_energy_price_CNT') | round(2) }} € 
        icon: mdi:power-plug
        icon_color: orange
        tap_action:
          action: more-info
      - type: custom:mushroom-template-card
        entity: sensor.hours_low_coming
        secondary: |
          {{ states('sensor.hours_low_coming_short') | round(0) }} urgent
        primary: >
          {{ states('sensor.hours_low_coming') | round(0) }}/{{
          states('sensor.hours_low_coming_far') | round(0) }} H
        icon: mdi:clock-check
        icon_color: orange
        tap_action:
          action: more-info
      - type: custom:mushroom-template-card
        entity: sensor.zonneplan_current_gas_tarriff_fixed
        secondary: |
          Gas
        primary: >
          {{ states('sensor.zonneplan_current_gas_tarriff_fixed') | round(2) }}
          € 
        icon: mdi:gas-burner
        icon_color: orange
        tap_action:
          action: more-info
  - type: custom:config-template-card
    variables:
      MOVINGAVERAGE: states['sensor.avg_energy_price_cnt']
    entities:
      - ${MOVINGAVERAGE.entity_id}
    card:
      type: custom:apexcharts-card
      apex_config:
        chart:
          height: 200px
          fontFamily: Raleway,sans-serif
        xaxis:
          labels:
            format: HH
        legend:
          show: false
        stroke:
          width: 2
        plotOptions:
          bar:
            columnWidth: 100%
        grid:
          show: true
          borderColor: '#00000030'
          strokeDashArray: 4
          position: back
        dataLabels:
          offsetY: -8
          background:
            opacity: 0.01
            enabled: true
            foreColor: '#CF7524'
            padding: 2
            borderRadius: 4
            borderWidth: 0
          style:
            fontSize: 9px
            color: rgb(200,200,200)
      experimental:
        color_threshold: true
      graph_span: 30h
      span:
        start: day
        offset: +4h
      update_interval: +1h
      header:
        title: Zonneplan Forecast
        show: false
      now:
        show: true
        label: NOW
      series:
        - entity: sensor.zonneplan_current_electricity_tariff
          color_threshold:
            - value: ${MOVINGAVERAGE.state * .75}
              color: '#228B22'
            - value: ${MOVINGAVERAGE.state * 1}
              color: '#d35400'
            - value: ${MOVINGAVERAGE.state * 1.25}
              color: '#c0392b'
          show:
            extremas: true
          type: column
          float_precision: 2
          data_generator: |
            return entity.attributes.forcast.map((entry) => {
              return [new Date(entry.datetime).getTime(), entry.price /100000] ;
            });
      yaxis:
        - id: '1'
          decimals: 1
          min: 10
          apex_config:
            tickAmount: 4

I cant seem to get this working.
The state of sensor.avg_energy_price = ‘Unavailable’ and i think due to this option i cant get the card to work!

Any clue what I need to fix / change?

Do you have sensor.lowest_price and sensor.highest_price created?

like @Hmmbob suggests; Did you create the sensors? Below is what I use. Also please note that the dev of this integration recently changed something. There was a spelling mistake in the sensor attributes and it was changed from “forcast” to “forecast”.

The yaml for the 2 sensors I use below:

- platform: template
  sensors:
    avg_energy_price_cnt:
      friendly_name: Average current energy price cent
      unique_id: avg_energy_price_cnt
      value_template: >
        {% set ns = namespace(sum = 0, count = 0) %}
        {% for item in state_attr('sensor.zonneplan_current_electricity_tariff', 'forecast') -%}
          {% if as_datetime(item.datetime).date() == now().date()  %}
            {% set ns.sum = ns.sum + item.price %}
            {% set ns.count = ns.count + 1 %}
          {% endif %}
        {%- endfor %}
        {{ (ns.sum/ns.count/100000) }}

- platform: template
  sensors:
    avg_energy_price:
      friendly_name: Average current energy price
      unique_id: avg_energy_price
      device_class: monetary
      value_template: >
        {% set ns = namespace(sum = 0, count = 0) %}
        {% for item in state_attr('sensor.zonneplan_current_electricity_tariff', 'forecast') -%}
          {% if as_datetime(item.datetime).date() == now().date()  %}
            {% set ns.sum = ns.sum + item.price %}
            {% set ns.count = ns.count + 1 %}
          {% endif %}
        {%- endfor %}
        {{ (ns.sum/ns.count/10000000) }}

Thank you! The issue was ‘Forcast’ instead of Forecast…
I didn’t know this was changed, thanks!

After the latest zonneplan.one update, this code is not working anymore.

template:

  - sensor:

    - name: zonneplan_cheapest_hour

      state: >

        {% set cheapest_hour_next_ten_hours = state_attr('sensor.zonneplan_current_electricity_tariff', 'forcast')

                    | selectattr('datetime', '>', utcnow().isoformat())

                    | selectattr('datetime', '<', (utcnow() + timedelta(hours = 13)).isoformat())

                    | sort(attribute='price')  

                    | first %}

        {{ (cheapest_hour_next_ten_hours.price /10000000)|round(2) }}

        {{ as_local(as_datetime(cheapest_hour_next_ten_hours.datetime)).strftime('%d-%m - %H:%M') }}

change forcast to forecast :+1:

Thanks man! This is great! Well done.

1 Like

Hi All,

Has somebody a solution for the montly costs, based on the zonneplan tariff as sensor data? I would like to show them on my dashboard.

Thanks :slight_smile:

Use the energy dashboard and set cost to variable/using sensor. If you use the zonneplan price sensor then the energy dashboard will calculate it for you and store the values in long term statistics.