ApexCharts card - A highly customizable graph card

Thank you @Kertz1954 .
But it was just a mistake when writing the post. Sorry for that.
I doublechecked it:

data_generator: |
      return entity.attributes.period_start.map((start, index) => {
        return [new Date(start).getTime(), entity.attributes.price[index]];
      });

still does not work.

To answer my own question, you can use the hass object in data_generator to access other sensors, for example to get a state: hass.states['sensor.my_sensor'].state

Ok, having done a quick test with your fixed data, I got nothing showing as the time is now in the past, which is correct.
Changing the time to start from 16:00 ,1700 etc, produced the desired results.
It looks like your attribute data is now out of date.
You can check this by changing your span: code and add an negative offset.

Thanks @Kertz1954 ,

although it does not work for me, it is good to know, that it should work.

Writing the entity with:

self.set_state('price_forecast.price_low_power', state=0.2,
                    attribute={'period_start': '2023-02-20 16:00',
                    'price': 0.2 })

leads to:

when I do this:

type: custom:apexcharts-card
header:
  show: true
  show_states: true
graph_span: 1w
span:
  start: week
series:
  - entity: price_forecast.price_low_power
    data_generator: |
      return [[new Date().getTime(), entity.state], [new Date().getTime() + 1000*60*60, 2*entity.state]]

I get the expected result:

Doing the same with the attribute instead of state, the value is ‘NaN’

type: custom:apexcharts-card
header:
  show: true
  show_states: true
graph_span: 1w
span:
  start: week
series:
  - entity: price_forecast.price_low_power
    data_generator: |
      return [[new Date().getTime(), entity.attributes.price], [new Date().getTime() + 1000*60*60, 2*entity.attributes.pricee]]

I fear that I am making a very stupid mistake :scream:

And possibly without knowing it…part of your solution resolves my question from a few days ago !!
Thx

In my world we spell PRICE with just 1 e !!

Dear @Kertz1954,
I want to thank you for your patience and also apologize for my stupid mistakes.
When copy & paste, I must probably better watch what I’m doing! Maybe I should try again in one or two days. :unamused:

But the extra “e” is not the problem, have tried it with the right spelling before:

type: custom:apexcharts-card
header:
  show: true
  show_states: true
graph_span: 1d
span:
  start: day
series:
  - entity: price_forecast.price_low_power
    data_generator: |
      return [[new Date().getTime(), entity.state], [new Date().getTime() + 1000*60*60, entity.attributes.price]]

The first element is ok, the second one is null (before with pricee, it was NaN)

I also tried to set the attributes value as a string and use Number(entitiy.attributes.price) and …
It seems, that accessing the attributes data via entity.attributes.* does not work for me.

In german I would say: “I have a plank in front of my head”

@unknown_user Your entity is wrong. Should be something like sensor.price_forecast

Now with image:

How can I have the top left show the current usage (0.05) instead of rounding it to 0?

YAML:

type: custom:apexcharts-card
apex_config:
  legend:
    show: false
header:
  show: true
  title: Gasverbruik
  show_states: true
  colorize_states: true
yaxis:
  - id: current
    decimals: 2
    apex_config:
      tickAmount: 6
      forceNiceScale: true
      labels:
        show: true
  - id: total
    decimals: 1
    opposite: true
    apex_config:
      tickAmount: 6
      forceNiceScale: true
      labels:
        show: true
series:
  - entity: sensor.dsmr_consumption_gas_currently_delivered
    name: Huidig
    yaxis_id: current
    stroke_width: 3
    color: orange
  - entity: sensor.dsmr_day_consumption_gas
    name: Vandaag
    yaxis_id: total
    stroke_width: 1
show:
  last_updated: true
graph_span: 8h

Hi, I paged through a lot of the above but cannot find an answer to this
I have a set of 5 values as part of an attribute but no dates to match. How can I map this, i.e. x-axis could show 1,2,3,4,5 each with the value. Alternatively create fake dates for each one of them based on today -1, today -2 etc. and then hide the x-axis values.

EDIT: found a solution after more browsing, the values are in the daily_week_MP attributes

data_generator: |
      const now = new Date();
      const data = [];
      for(let i = 0; i <= 5; i++) {
        data.push([now.getTime() - i*1000*60*60*24, entity.attributes.dailyweek_MP[i]])
      }
      return data

@Tyfoon Thank you for your answer. I create the entity price_forecast.price_low_power by myself in a python script, therefore I can access it that way. An with the state it already worked

But I know, where the fault was.
I create the entity in python via:

self.set_state('price_forecast.price_low_power', state=0.2,
                    attribute={'period_start': '2023-02-20 16:00',
                    'price': 0.2 })

To access the attribute in ApexCharts, I have to use:

entity.attributes.attribute.price

instead of

entity.attributes.price

That’s a bit suprising for me. I will try to find out, how to use the set_state() function to access the attributes without the extra attribute … later. For the moment it works so I can start to tune my chart.

Here is what I do now:

type: custom:apexcharts-card
apex_config:
  legend:
    show: true
  tooltip:
    shared: false
  plotOptions:
    bar:
      columnWidth: 100%
graph_span: 2d
span:
  start: day
all_series_config:
  type: column
  float_precision: 3
  show:
    legend_value: false
yaxis:
  - min: 0
    max: 0.5
    decimals: 2
    apex_config:
      tickAmount: 5
series:
  - entity: price_forecast.price_grid
    name: Netz
    type: line
    data_generator: |
      return entity.attributes.attribute.period_start.map((start, index) => {
        return [new Date(start).getTime(), entity.attributes.attribute.price[index]];
      });
  - entity: price_forecast.price_low_power
    name: Low power
    type: column
    color: green
    group_by:
      func: avg
      duration: 1h
    data_generator: |
      return entity.attributes.attribute.period_start.map((start, index) => {
        return [new Date(start).getTime(), entity.attributes.attribute.price[index]];
      });

and the result as expected:
apex_34

@Kertz1954 Tank you for your assistance, too!

I use float_precision to do that:

type: custom:apexcharts-card
apex_config:
  legend:
    show: false
header:
  show: true
  title: Gasverbruik
  show_states: true
  colorize_states: true
yaxis:
  - id: current
    decimals: 2
    apex_config:
      tickAmount: 6
      forceNiceScale: true
      labels:
        show: true
  - id: total
    decimals: 1
    opposite: true
    apex_config:
      tickAmount: 6
      forceNiceScale: true
      labels:
        show: true
series:
  - entity: sensor.dsmr_consumption_gas_currently_delivered
    name: Huidig
    yaxis_id: current
    stroke_width: 3
    color: orange
    float_precision: 2
  - entity: sensor.dsmr_day_consumption_gas
    name: Vandaag
    yaxis_id: total
    stroke_width: 1
show:
  last_updated: true
graph_span: 8h
1 Like

Hi, working through creating a temperature graph for a Thermostat type device (Hive - connected via Zigbee).

I’ve almost posted a few times but was able to figure it out. I’m possibly being lazy with this last problem.

Code:

type: custom:apexcharts-card
experimental:
  color_threshold: true
graph_span: 24h
yaxis:
  - min: 0
    max: 30
    decimals: 0
    apex_config:
      tickAmount: 6
show:
  last_updated: true
header:
  standard_format: false
  show: true
  show_states: true
  colorize_states: true
  title: Downstairs Temperature
now:
  show: true
  color: black
  label: Now
span:
  start: day
  offset: '-4h'
apex_config:
  legend:
    show: false
series:
  - entity: climate.downstairs_receiver
    attribute: occupied_heating_setpoint
    name: Set Temperature
    stroke_width: 2
    unit: °C
  - entity: climate.downstairs_receiver   
    attribute: running_state
    extend_to_end: false
    name: Heating
    transform: 'return x === "heat" ? entity.attributes.local_temperature : null;'
    type: area
    curve: stepline
    color: red
    opacity: 0.5
    stroke_width: 1
    show:
      in_header: false
  - entity: climate.downstairs_receiver  
    attribute: running_state
    name: Heating
    transform: 'return x === "idle" ? entity.attributes.local_temperature : null;'
    type: area
    curve: stepline
    color: lightblue
    opacity: 0.5
    stroke_width: 1
    show:
      in_header: false
  - entity: climate.downstairs_receiver
    attribute: local_temperature
    name: Actual Temperature
    unit: °C
    type: line
    fill_raw: last
    curve: smooth
    group_by:
      func: avg
      duration: 15m
      start_with_last: true      
    extend_to_end: false
    stroke_width: 3
    show:
      extremas: true
      header_color_threshold: true
    color_threshold:
      - value: 0
        color: steelblue
      - value: 10
        color: midnightblue
      - value: 16
        color: orange
      - value: 23
        color: orangered
      - value: 25
        color: red

Graph:

I am trying to use extend_to_end: false for some of the series in the above, but it keeps failing. Any ideas on what I have done wrong?

This is the error I get:

/// apexcharts-card version 2.0.2 /// value.series[2] is not a ChartCardSeriesExternalConfig value.series[2].extend_to_end is extraneous value.series[2].extend_to_end is extraneous

1 Like

You are being lazy !! :slightly_smiling_face:

Read the documentation for the series Options.

1 Like

Oh jeez.

I’m an idiot.

Thank you for the gentle nudge! Bloody deprecated.

extend_to: now should do what I want!

I don’t know how I missed that, could have sworn it was in the documentation I first saw it (then old examples here). Anyway, live and learn.

I’ve now pretty much created the graph the Hive app used to make - need to work on setting a schedule for the stat now and then adding that into the graph. :slight_smile:

Hello everyone!

I’m currently been tired of an issue I have with apex charts on one of mine dashboards. It’s started already in November, after one of HA upgrades, I don’t remember which one. Maybe some of you guys had similar problem and solved it.

Here is the case.

I’m using two ApexCharts-cards to visualize future grid prices from Nordpool. There is identical setup on two different dashboards. One of them, is mostly standard HA cards, no issues there, charts showing correct.
The other dashboard I use on the built-in screen in Samsung Family Hub refrigerator. This screen and built in web browser is quite strange. It’s zooming everything on it to 200%. So, when I use regular dashboard on it, it’s showing enormous big cards and only one card in width.

Therefore I’m using frontend module lovelace-card-mod, to apply some visual changes (CSS Style) to cards and zoom it down by 50%. Cards are hold in place by vertical-stack and horizontal-stack card configuration.

Everything was fine, until some upgrades in November or start December 2022, I don’t really remember.

Now, when I open this resized dashboard, it looks like charts are resized 50% inside the already resized card. When I switch to other view on the dashboard and come back again to view witch charts, they looks right, like it suppose to be. When I refresh website or change dashboard, charts are smaller again. They also looks right when I resize browser window.

Here is a code of charts:

      - type: horizontal-stack
        cards:
          - type: vertical-stack
            cards:
              - type: custom:apexcharts-card
                card_mod: !include lovelace/cardmod1-50.yaml
                graph_span: 26h
                experimental:
                  color_threshold: true
                header:
                  title: Prices next 24h (kr/kWh)
                  show: true
                apex_config:
                  chart:
                   redrawOnWindowResize: true
                  yaxis:
                    min: 0
                    max: 10
                hours_12: false
                span:
                  start: hour
                  offset: "-2h"
                now:
                  show: true
                  label: Nu
                series:
                  - entity: sensor.import_power_price_incl_transport
                    type: column
                    float_precision: 2
                    data_generator: >
                      return (entity.attributes.raw_today.map((start, index) =>
                      {
                        return [new Date(start["start"]).getTime(), entity.attributes.raw_today[index]["value"]];
                      })).concat(entity.attributes.raw_tomorrow.map((start,
                      index) => {
                        return [new Date(start["start"]).getTime(), entity.attributes.raw_tomorrow[index]["value"]];
                      }));
                    color_threshold:
                      - value: 0
                        color: lightgreen
                      - value: 1
                        color: green
                      - value: 3
                        color: yellow
                      - value: 5
                        color: orange
                      - value: 7
                        color: red
                      - value: 9
                        color: darkred
              - type: custom:apexcharts-card
                card_mod: !include lovelace/cardmod1-50.yaml
                graph_span: 26h
                experimental:
                  color_threshold: true
                header:
                  show: true
                  title: Grid Export next 24h (kr/kWh)
                apex_config:
                  yaxis:
                    min: 0
                    max: 10
                hours_12: false
                span:
                  start: hour
                  offset: "-2h"
                now:
                  show: true
                  label: Nu
                series:
                  - entity: sensor.export_price_power
                    type: column
                    float_precision: 2
                    data_generator: |
                      return (entity.attributes.raw_today.map((start, index) => {
                        return [new Date(start["start"]).getTime(), entity.attributes.raw_today[index]["value"]];
                      })).concat(entity.attributes.raw_tomorrow.map((start, index) => {
                        return [new Date(start["start"]).getTime(), entity.attributes.raw_tomorrow[index]["value"]];
                      }));
                    color_threshold:
                      - value: 0
                        color: lightgreen
                      - value: 1
                        color: green
                      - value: 3
                        color: yellow
                      - value: 5
                        color: orange
                      - value: 7
                        color: red
                      - value: 9
                        color: darkred

Here is a code of cardmod1-50.yaml, which resizing cards by 50%

style:
  .: |
    #states > * {
        margin: -1px 0px !important;
    }
    ha-card {
      background: rgba(120, 200, 255, .1);
      background-image: linear-gradient(to bottom, rgba(120,200,255,.1), rgba(120,200,255,0));
      border: 1px solid rgba(120,200,255,.3);
      font-variant: small-caps;
      zoom: 0.5;
    }
    .card-header {
      padding-top: 5px;
      padding-bottom: 5px;
      border-bottom: 1px solid rgba(120,200,255,.3);
      color: rgba(120,200,255,.8);
    }
    .card-content {
        padding-top: 8px;
        padding-bottom: 8px;
    }

When I just open dashboard (same issue on pc in Chrome, on refrigerator or HA app), it’s look like this:

wrong

When I switch between views in dashboard, it’s looks like it should be (and like it was before upgrade):

I looked in the console on web browser, there is no errors on loading, or nothing else indicating what is wrong. Somehow charts changed behavior to CSS styles and applies double on page loading but goes single again on change view…

Anyone has an idea how to fix this?

hey guys, im in to apex card and i like it.
can you point me how to merge two cards together
and few more customizations:

  1. as i have it now. for example my offpeak tariff is 23:00 - 7:00. Apex card shows offpeak info on 0:00-7:00 (146kWh) and i want it to show my full offpeak info (172 kWh)


  2. apex card loads information when the day has passed, can it load for just right now?
    on a chart it is zero, but in the entity it is raising and has a value already

my code looks this way now

- type: vertical-stack
            cards:
              - type: custom:apexcharts-card
                header:
                  show: true
                  title: Day tariff
                graph_span: 14d
                yaxis:
                  - min: 0
                series:
                  - entity: sensor.main_counter_data_daily_peak
                    group_by:
                      func: diff
                      duration: 1d
                    statistics:
                      period: hour
                      type: sum
                      align: start
                    type: column
                    color: '#7b99b5'
                span:
                  start: day
                  offset: '-13d'

I use the Apex chart among others for displaying grid prices.
This dataset has prices for today, and after 1 PM / 13:00 also for tomorrow.
Therefore I use the Now option to quickly see what hour in the chart is the current one. This is good and works nicely.

My question is, can I somehow get the legend value (shown above the graph) to display the price where the Now marker is placed, rather than the last data point?

image

I can just hide it, it is not a big deal.
But it would be nice if it could show the current price.

1 Like

I to, wondered why/what price it showed in top, as i have 2 -sensors and none showing the actual “state” , current price, which to me also seems more relevant … could you share your code for your column view ?

So far it looks like this:

    data_generator: |
      var ret = entity.attributes.raw_today.map((element, index) => {
        return [new Date(element["hour"]), element["price"]];
      })
      if (entity.attributes.raw_tomorrow != null) {
        ret = ret.concat(entity.attributes.raw_tomorrow.map((element, index) => {
          return [new Date(element["hour"]), element["price"]];
        }));
      }      
      return(ret);

But not tested with data for tomorrow yet.