Dynamic color_threshold for ApexCharts

I want to highlight the hours with the lowest prices for the next days to plan EV charging. I have calculated the lowest price based of remaining battery (%), battery capacity (74kwh) and my charger efficency (11kw), but in custom:apexcharts-card I can only set the values as hard coded integers.

type: custom:apexcharts-card
apex_config:
  chart:
    height: 400px
experimental:
  color_threshold: true
graph_span: 24h
header:
  title: Elpriser pr. time (kr/kWh)
  show: true
span:
  start: hour
  offset: '-2h'
now:
  show: true
  label: Nu
yaxis:
  - min: 0.75
    apex_config:
      tickAmount: 2
series:
  - entity: sensor.elspotpris
    type: column
    data_generator: |
      var tt = 1;
      var today = entity.attributes.raw_today.map((start, index) => {
        return [new Date(start["hour"]).getTime(), 
        entity.attributes.raw_today[index]["price"] * 1];
      });
      if (entity.attributes.tomorrow_valid) {
        var tomorrow = entity.attributes.raw_tomorrow.map((start, index) => {
          return [new Date(start["hour"]).getTime(), entity.attributes.raw_tomorrow[index]["price"]];
        });

        var data = today.concat(tomorrow);
      } else {
        var data = today
      }
      return data;
    float_precision: 2
    color_threshold:
      - value: 0
        color: green
      - value: 2.04
        color: red

Best regards
/Tonkin

1 Like

To achieve what you want, I think you have to use the custom “Config Template Card” card and create a card something like this:

type: custom:config-template-card
variables:
  - '"sensor.elspotpris"'
  - <calculate the lowest price>
entities: ${vars[0]}
card:
  type: custom:apexcharts-card
  [...]
  series:
    - entity: ${vars[0]}
      type: column
      [...]
      float_precision: 2
      color_threshold:
        - value: 0
          color: green
        - value: ${vars[1]}
          color: red

Did u manage to get this to work

No! I had no luck with the suggested code.

@Tonkin @dezito Had a similar problem, here’s my solution:

I managed this by creating four variables with a calculated threshold value for each color to show in the graph:

type: custom:config-template-card
variables:
  - >-
    (((states['sensor.tibber_highest_energy_price_today'].state -
    states['sensor.tibber_lowest_energy_price_today'].state) / 4) * 0) +
    Number(states['sensor.tibber_lowest_energy_price_today'].state)
  - >-
    (((states['sensor.tibber_highest_energy_price_today'].state -
    states['sensor.tibber_lowest_energy_price_today'].state) / 4) * 1) +
    Number(states['sensor.tibber_lowest_energy_price_today'].state)
  - >-
    (((states['sensor.tibber_highest_energy_price_today'].state -
    states['sensor.tibber_lowest_energy_price_today'].state) / 4) * 2) +
    Number(states['sensor.tibber_lowest_energy_price_today'].state)
  - >-
    (((states['sensor.tibber_highest_energy_price_today'].state -
    states['sensor.tibber_lowest_energy_price_today'].state) / 4) * 3) +
    Number(states['sensor.tibber_lowest_energy_price_today'].state)

Then I was able to use them inside the custom:apexcharts-card :

series:
    - entity: sensor.tibber_average_electricity_price_today
      show:
        in_header: false
      stroke_width: 2
      float_precision: 3
      type: column
      color_threshold:
        - value: ${vars[0]}
          color: '#42a047'
        - value: ${vars[1]}
          color: '#ffa600'
        - value: ${vars[2]}
          color: '#ff7100'
        - value: ${vars[3]}
          color: '#db4437'

result:

2 Likes

Placing apexcharts inside CTC:

  • either the graph is not updated real-time since a sensor is not declared as monitored;
  • or the whole card is redrawn every time the sensor is changed - otherwise.

I got it working with the following code! Thanks!!

type: custom:config-template-card
variables:
  - '"sensor.elspotpris"'
  - Number(states['sensor.smart_charge_target_price'].state)
  - >-
    String('Charging at ' + states['sensor.smart_charge_target_price'].state + '
    kr/kWh')
entities: ${vars[0]}
card:
  type: custom:apexcharts-card
  apex_config:
    chart:
      height: 400px
  experimental:
    color_threshold: true
  graph_span: 24h
  header:
    title: ${vars[2]}
    show: true
  span:
    start: hour
    offset: '-2h'
  now:
    show: true
    label: Nu
  yaxis:
    - min: 0.75
      apex_config:
        tickAmount: 2
  series:
    - entity: ${vars[0]}
      type: column
      data_generator: |
        var tt = 1;
        var today = entity.attributes.raw_today.map((start, index) => {
          return [new Date(start["hour"]).getTime(), 
          entity.attributes.raw_today[index]["price"] * 1];
        });
        if (entity.attributes.tomorrow_valid) {
          var tomorrow = entity.attributes.raw_tomorrow.map((start, index) => {
            return [new Date(start["hour"]).getTime(), entity.attributes.raw_tomorrow[index]["price"]];
          });

          var data = today.concat(tomorrow);
        } else {
          var data = today
        }
        return data;
      float_precision: 2
      color_threshold:
        - value: 0
          color: green
        - value: ${vars[1]}
          color: red

Hi,

can you please share the full code.

I dont understand:? you posted 2 codes for 2 diffrent cards?

Do you mind making a full instruction :slight_smile: I am new in Home assistant. ( I have tibber and nordpol both installed)

1 Like

Hi guys
This is what I’m trying to do, but I did it with a different approach.
I created this in the configuration:

template:
  - sensor:
      - name: "Tibber Average Price"
        state: >-
          {% set price = state_attr('sensor.tibber_price_highs_and_lows', 'categorized_prices')['average_price'] %}
          {{ price | float }}
        unit_of_measurement: "Öre/kWh"
        device_class: monetary
        state_class: measurement

Then I did this in the apex chart card:

    color_threshold:
      - value: 0
        color: green
      - value: sensor.tibber_average_price
        color: red

But I got this error:
/// apexcharts-card version 2.1.2 /// value.series[0] is not a ChartCardSeriesExternalConfig; value.series[0].color_threshold[1] is not a ChartCardColorThreshold; value.series[0].color_threshold[1].value is not a number

------ State is:
[sensor.tibber_average_price]
Tibber Average Price 0.235504166666667
state_class: measurement
unit_of_measurement: Öre/kWh
device_class: monetary
friendly_name: Tibber Average Price

I really don’t get it? Any suggestions

I believe it’s not possible to directly use entity value as dynamic threshold.
That why you need to use the config-template-card.

Here is my complete code, based on the examples in this thread.
I slightly adjusted it to a 5-point scale and removed the background using card-mod.

type: custom:config-template-card
variables:
  - >-
    ((((states['sensor.energy_current_highest_price_entsoe'].state -
    states['sensor.energy_current_lowest_price_entsoe'].state) / 5) * 0) +
    Number(states['sensor.energy_current_lowest_price_entsoe'].state))*100
  - >-
    ((((states['sensor.energy_current_highest_price_entsoe'].state -
    states['sensor.energy_current_lowest_price_entsoe'].state) / 5) * 1) +
    Number(states['sensor.energy_current_lowest_price_entsoe'].state))*100
  - >-
    ((((states['sensor.energy_current_highest_price_entsoe'].state -
    states['sensor.energy_current_lowest_price_entsoe'].state) / 5) * 2) +
    Number(states['sensor.energy_current_lowest_price_entsoe'].state))*100
  - >-
    ((((states['sensor.energy_current_highest_price_entsoe'].state -
    states['sensor.energy_current_lowest_price_entsoe'].state) / 5) * 3) +
    Number(states['sensor.energy_current_lowest_price_entsoe'].state))*100
  - >-
    ((((states['sensor.energy_current_highest_price_entsoe'].state -
    states['sensor.energy_current_lowest_price_entsoe'].state) / 5) * 4) +
    Number(states['sensor.energy_current_lowest_price_entsoe'].state))*100    
entities:
  - sensor.energy_current_lowest_price_entsoe
  - sensor.energy_current_highest_price_entsoe
card:
  type: custom:apexcharts-card
  graph_span: 36h
  experimental:
    color_threshold: true
  span:
    start: day
  header:
    show: true
    title: ENTSOE
    show_states: true
    colorize_states: false
  yaxis:
    - id: price
      min: "|-2|"
      max: "|+2|"
  now:
    show: true
    label: Now
  apex_config:
    chart:
      height: 250
  series:
    - entity: sensor.energy_price_trend_netsoe
      type: column
      float_precision: 3
      data_generator: |
        return entity.attributes.times.map((time, index) => {
          return [new Date(time).getTime(), entity.attributes.prices[index]];
        });
      show:
        in_header: false
        legend_value: false
      color_threshold:
        - value: ${vars[0]}
          color: "#2cba00"
        - value: ${vars[1]}
          color: "#a3ff00"
        - value: ${vars[2]}
          color: "#fff400"
        - value: ${vars[3]}
          color: "#ffa700"
        - value: ${vars[4]}
          color: "#ff0000"
  card_mod:
    style: |
      ha-card {
        --ha-card-background: rgba(0,0,0,0);
          box-shadow: none !important;
          border-style: none;
      }

Results in:

Some other example:

type: custom:config-template-card
variables:
  - >-
    ((((states['sensor.energy_current_highest_price_entsoe'].state -
    states['sensor.energy_current_lowest_price_entsoe'].state) / 5) * 0) +
    Number(states['sensor.energy_current_lowest_price_entsoe'].state))*100
  - >-
    ((((states['sensor.energy_current_highest_price_entsoe'].state -
    states['sensor.energy_current_lowest_price_entsoe'].state) / 5) * 1) +
    Number(states['sensor.energy_current_lowest_price_entsoe'].state))*100
  - >-
    ((((states['sensor.energy_current_highest_price_entsoe'].state -
    states['sensor.energy_current_lowest_price_entsoe'].state) / 5) * 2) +
    Number(states['sensor.energy_current_lowest_price_entsoe'].state))*100
  - >-
    ((((states['sensor.energy_current_highest_price_entsoe'].state -
    states['sensor.energy_current_lowest_price_entsoe'].state) / 5) * 3) +
    Number(states['sensor.energy_current_lowest_price_entsoe'].state))*100
  - >-
    ((((states['sensor.energy_current_highest_price_entsoe'].state -
    states['sensor.energy_current_lowest_price_entsoe'].state) / 5) * 4) +
    Number(states['sensor.energy_current_lowest_price_entsoe'].state))*100    
entities:
  - sensor.energy_current_lowest_price_entsoe
  - sensor.energy_current_highest_price_entsoe
card:
  type: custom:apexcharts-card
  graph_span: 36h
  experimental:
    color_threshold: true
  span:
    start: day
  header:
    show: true
    title: ENTSOE
    show_states: true
    colorize_states: false
  yaxis:
    - id: price
      decimals: 2
      align_to: 1
      min: "|-2|"
      max: "|+2|"
  now:
    show: true
    label: Now
  apex_config:
    chart:
      height: 250
    annotations:
      strokeDashArray: 1
      yaxis:
        - "y": -100
          y2: ${vars[1]}
          fillColor: "#2cba00"
          opacity: 0.2
        - "y": ${vars[1]}
          y2: ${vars[2]}
          fillColor: "#a3ff00"
          opacity: 0.2
        - "y": ${vars[2]}
          y2: ${vars[3]}
          fillColor: "#fff400"
          opacity: 0.2
        - "y": ${vars[3]}
          y2: ${vars[4]}
          fillColor: "#ffa700"
          opacity: 0.2
        - "y": ${vars[4]}
          y2: 100
          fillColor: "#ff0000"
          opacity: 0.2
  series:
    - entity: sensor.energy_price_trend_netsoe
      type: area
      curve: stepline
      stroke_width: 2
      extend_to: false
      float_precision: 3
      data_generator: |
        return entity.attributes.times.map((time, index) => {
          return [new Date(time).getTime(), entity.attributes.prices[index]];
        });
      show:
        in_header: false
        legend_value: false
      color_threshold:
        - value: ${vars[0]}
          color: "#2cba00"
        - value: ${vars[1]}
          color: "#a3ff00"
        - value: ${vars[2]}
          color: "#fff400"
        - value: ${vars[3]}
          color: "#ffa700"
        - value: ${vars[4]}
          color: "#ff0000"
  card_mod:
    style: |
      ha-card {
        --ha-card-background: rgba(0,0,0,0);
          box-shadow: none !important;
          border-style: none;
      }

You card does not update the graph in real-time - when the monitored entity is changed while you are looking at the graph. To fix it - add the entity into “entities” option of config-template-card (but note that the whole card will be redrawn when this entity changes).