ApexCharts card - A highly customizable graph card

Thanks!
I was not attentive.

Haven’t started using the card, just testing it sometimes.
Now I wonder how it processes unavailable data.

Here are two simple sensors:

  1. Equal to some input_number, is available if some input_boolean = on.
  2. Equal to the 1st sensor * 2, is available if that 1st sensor is available.
sensor:
  - platform: template
    sensors:

      test_availability:
        unit_of_measurement: "unit"
        icon_template: mdi:account
        value_template: >-
          {{ states("input_number.test_number") }}
        availability_template: >-
          {{ is_state("input_boolean.test_boolean","on") }} 

      test_availability_2:
        unit_of_measurement: "unit"
        icon_template: mdi:car
        value_template: >-
          {% set VALUE = states("sensor.test_availability") -%}
          {%- if is_number(VALUE) -%}
          {{ VALUE | float * 2 }}
          {%- else -%}
          {{ 0 }}
          {%- endif %}
        availability_template: >-
          {{ not states("sensor.test_availability") in ["unavailable","unknown"] }} 

Now let’s see graphs for these sensors:

  - type: entities
    entities:
      - entity: input_boolean.test_boolean
        name: Available
      - entity: input_number.test_number
        name: Value
      - type: divider
      - entity: sensor.test_availability
      - entity: sensor.test_availability_2

  - type: vertical-stack
    cards:
      - type: custom:mini-graph-card
        entities:
          - entity: sensor.test_availability
            show_points: true
          - entity: sensor.test_availability_2
            show_points: true
        lower_bound: 0
        points_per_hour: 60
        hours_to_show: 1
        average_func: last
        update_interval: 0
        line_width: 1
        smoothing: false
        cache: false

      - type: history-graph
        entities:
          - entity: sensor.test_availability
          - entity: sensor.test_availability_2
        hours_to_show: 1
        refresh_interval: 0

      - type: custom:apexcharts-card
        series:
          - entity: sensor.test_availability
            curve: stepline
            stroke_width: 1
            fill_raw: 'null'
          - entity: sensor.test_availability_2
            curve: stepline
            stroke_width: 1
            fill_raw: 'null'
        graph_span: 1h
        cache: false
        now:
          show: true

There are 3 graphs:

  • based on mini-graph-card;
  • based on stock history-graph;
  • based on apexcharts-card.

Play with the input_number value & the input_boolean value.
Note that:

  1. The mini-graph-card shows no gap for unavailable data (sad but true - and this will not be rectified unfortunately).
  2. The stock history-graph shows gaps when sensors are unavailable (great!!!).
  3. The apexcharts-card shows gaps - but in a strange manner:

it shows a gap when the data are unavailable, then shows a curve otherwise:


then again shows a gap - even for the time when the data were available:

Is it a bug? Or am I missing smth?

Hi @ all,

how i can change the font Size of the "Status Display?

5 Sensors are for this size to much, i want a display without a Linebreak.

best reguards
Faruk

Screenshot 2021-11-02 091446

:wave:

Just discovered this card

LINES NETWORK

Convert kB/s and MB/s with custom legend

yaml
type: custom:apexcharts-card
layout: minimal
graph_span: 1h
apex_config:
  tooltip:
    style:
      fontSize: 14px
    x:
      show: true
      formatter: |
        EVAL:(timestamp) => {
          let date = new Date(timestamp).toLocaleString('sv-SE',{weekday: 'long', hour: '2-digit', minute:'2-digit'}).toString();
          return date.charAt(0).toUpperCase() + date.slice(1);
        }
  chart:
    fontFamily: SF Text
    height: 250px
  legend:
    fontSize: 15px
    fontWeight: 600
    itemMargin:
      horizontal: 25
    formatter: |
      EVAL:(seriesName, opts) => {
        var arr = opts.w.globals.series[opts.seriesIndex],
          value = arr[arr.length - 1],
          convert = (value / 1024).toFixed(2);
        if (value == null) {
          return seriesName;
        } else {
          return value < 1024 ? `${Math.round(value)} kB/s` : `${convert} MB/s`;
        }
      }
    markers:
      width: 26
      height: 23
      customHTML:
        - |-
          EVAL:() => {
            return `<ha-icon icon="mdi:arrow-down-bold" style="--mdc-icon-size: 23px;"></ha-icon>`
          }
        - |-
          EVAL:() => {
            return `<ha-icon icon="mdi:arrow-up-bold" style="--mdc-icon-size: 23px;"></ha-icon>`
          }
      fillColors:
        - none
        - none
  fill:
    type: gradient
    gradient:
      type: vertical
      shadeIntensity: 0.2
      opacityFrom: 0.7
      opacityTo: 0.1
      stops:
        - 0
        - 90
        - 100
  stroke:
    curve: smooth
    width: 3
all_series_config:
  type: area
  fill_raw: last
series:
  - entity: sensor.nas_network_down
    name: Ned
    color: green
  - entity: sensor.nas_network_up
    name: Upp
    color: '#385581'

AREA WEIGHT

Fetch data directly from InfluxDB Using HA or HACS graphs w/ InfluxDB data in HA? - #6 by koying

yaml
type: custom:apexcharts-card
graph_span: 0.3month
apex_config:
  yaxis:
    show: true
    decimalsInFloat: 1
    labels:
      style:
        colors:
          - rgba(255, 255, 255, 0.5)
        fontSize: 13px
        fontWeight: 200
      offsetX: -2
  grid:
    show: true
    borderColor: rgba(112, 135, 164, 0.1)
  title:
    text: kg
    style:
      color: white
      fontSize: 30px
      fontWeight: 100
  tooltip:
    style:
      fontSize: 14px
    x:
      show: true
      formatter: |
        EVAL:(timestamp) => {
          let date = new Date(timestamp).toLocaleString('sv-SE',{day: 'numeric', year: 'numeric', month:'long'}).toString().split(' ');
          return `${date[0]} ${date[1].charAt(0).toUpperCase() + date[1].slice(1)} ${date[2]}`;
        }
  xaxis:
    tooltip:
      enabled: false
    crosshairs:
      show: false
    axisTicks:
      show: false
    axisBorder:
      show: true
      color: rgba(112, 135, 164, 0.5)
      height: 1
    labels:
      style:
        fontSize: 15px
        fontWeight: 500
      offsetX: -1
      formatter: |
        EVAL:(timestamp) => {
          return new Date(timestamp).toLocaleString('sv-SE',{day: 'numeric', month:'short'});
        }
  chart:
    fontFamily: SF Text
    height: 350px
  fill:
    type: gradient
    gradient:
      type: vertical
      shadeIntensity: 0.2
      opacityFrom: 0.7
      opacityTo: 0.1
      stops:
        - 0
        - 90
        - 100
  stroke:
    curve: smooth
    width: 3
all_series_config:
  type: area
  fill_raw: last
series:
  - entity: sensor.date
    curve: smooth
    name: Mattias
    color: '#9a0ca3'
    data_generator: |
      let params = new URLSearchParams({
        db: "home_assistant",
        q: "SELECT value FROM kg WHERE entity_id = 'weight'"
      }),
      request = async () => {
        let a = [],
          r = await fetch("http://192.168.1.241:8086/query?" + params),
          j = await r.json();
        for (let r of j.results[0].series[0].values) a.push([new Date(r[0]), r[1]]);
        return a
      };
      return request()

COLUMN ENERGY

Fetch data from Tibber API

yaml
type: custom:apexcharts-card
graph_span: 5months
apex_config:
  tooltip:
    style:
      fontSize: 14px
    x:
      show: true
      formatter: |
        EVAL:(timestamp) => {
          let date = new Date(timestamp).toLocaleString('sv-SE',{year: 'numeric', month:'long'}).toString()
          return date.charAt(0).toUpperCase() + date.slice(1);
        }
  chart:
    height: 400px
    fontFamily: SF Text
  fill:
    type: gradient
    gradient:
      type: vertical
      shadeIntensity: 0.2
      opacityFrom: 1
      opacityTo: 0.7
      stops:
        - 0
        - 70
        - 100
  grid:
    show: true
    borderColor: rgba(112, 135, 164, 0.1)
  yaxis:
    show: true
    decimalsInFloat: 0
    labels:
      style:
        colors:
          - rgba(255, 255, 255, 0.5)
        fontSize: 13px
        fontWeight: 200
      offsetX: -2
  title:
    text: ⚡ kWh
    style:
      color: white
      fontSize: 38px
      fontWeight: 700
  xaxis:
    tooltip:
      enabled: false
    crosshairs:
      show: false
    axisTicks:
      show: false
    axisBorder:
      show: true
      color: rgba(112, 135, 164, 0.5)
      height: 1
    labels:
      style:
        fontSize: 15px
        fontWeight: 500
      offsetX: -1
      formatter: |
        EVAL:(timestamp) => {
          let date = new Date(timestamp).toLocaleString('en-US',{month:'short'}).toString();
          return date.replace('c','k').replace('y','j');
        }
series:
  - entity: sensor.date
    name: Förbrukning
    unit: kWh
    type: column
    color: rgba(228,224,17,1)
    data_generator: |
      let array = [], request = async () => {
        let request = await fetch("https://api.tibber.com/v1-beta/gql", {method:"POST",headers:{Authorization:"Bearer xxx","Content-Type":"application/json"},body:JSON.stringify({query:"{viewer{homes{consumption(resolution: MONTHLY, last: 12){nodes{from consumption}}}}}"})}),
          json = await request.json();
          console.log(request);
        for (let request of json.data.viewer.homes[0].consumption.nodes) array.push([new Date(request.from), request.consumption]);
        return array
      }; return request()

RADIAL SENSOR

UniFi OS style sensor

yaml
type: grid
cards:
  - type: custom:apexcharts-card
    chart_type: radialBar
    apex_config:
      legend:
        onItemHover:
          highlightDataSeries: false
        show: false
      chart:
        height: 280px
        fontFamily: SF Display
      plotOptions:
        radialBar:
          startAngle: -180
          endAngle: 180
          dataLabels:
            name:
              show: true
              offsetY: 55
            value:
              show: true
              offsetY: 5
              fontSize: 50px
              fontWeight: 600
              color: '#379c55'
            total:
              show: true
              fontSize: 21px
              fontWeight: 300
              label: CPU Load
              color: '#a8a8a8'
              formatter: |
                EVAL:(w) => {
                  return w.globals.seriesTotals + '٪';
                }
          hollow:
            size: 75%
            image: >-
              data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'
              viewBox='0 0 283.5 283.5'%3E%3Cpath d='M117.3
              109.2h48.8v4.1h12.2v8.1h-12.2v8.1h12.2v8.1h-12.2v8.1h12.2v8.1h-12.2v8.1h12.2v8.1h-12.2v4.1h-48.8V170h-12.2v-8.1h12.2V154h-12.2v-8.1h12.2v-8.1h-12.2v-8.1h12.2v-8.1h-12.2v-8.1h12.2v-4.3m20.4
              44.8v12.2h4.1V154h-4.1m8.1 0v12.2h4.1V154h-4.1m8.2
              0v12.2h4.1V154H154z' fill='%23a8a7a7'/%3E%3C/svg%3E
            imageWidth: 118
            imageHeight: 118
            imageOffsetY: -50
            imageClipped: false
          track:
            show: true
            background: '#222222'
            strokeWidth: 155%
      stroke:
        dashArray: 3.2
        lineCap: butt
    series:
      - entity: sensor.template_udm_cpu
        color: '#379c55'
  - type: custom:apexcharts-card
    chart_type: radialBar
    apex_config:
      legend:
        onItemHover:
          highlightDataSeries: false
        show: false
      chart:
        height: 280px
        fontFamily: SF Display
      plotOptions:
        radialBar:
          startAngle: -180
          endAngle: 180
          dataLabels:
            name:
              show: true
              offsetY: 55
            value:
              show: true
              offsetY: 5
              fontSize: 50px
              fontWeight: 600
              color: '#379c55'
            total:
              show: true
              fontSize: 21px
              fontWeight: 300
              label: CPU Temp
              color: '#a8a8a8'
              formatter: |
                EVAL:(w) => {
                  return w.globals.seriesTotals + '°';
                }
          hollow:
            size: 75%
            image: >-
              data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg'
              viewBox='0 0 283.5 283.5'%3E%3Cpath d='M152.1 145.4v-26.9a10.07
              10.07 0 1 0-20.2 0v26.9c-7.4 5.6-8.9 16.1-3.4 23.5 5.6 7.4 16.1
              8.9 23.5 3.4s8.9-16.1 3.4-23.5c-.9-1.4-2.1-2.5-3.3-3.4M142
              115.1a3.37 3.37 0 0 1 3.4 3.4v10.1h-6.7v-10.1c-.1-1.9 1.4-3.4
              3.3-3.4z' fill='%23a8a7a7'/%3E%3C/svg%3E
            imageWidth: 150
            imageHeight: 150
            imageOffsetY: -50
            imageClipped: false
          track:
            show: true
            background: '#222222'
            strokeWidth: 155%
      stroke:
        dashArray: 3.2
        lineCap: butt
    series:
      - entity: sensor.template_udm_cpu_temp
        color: '#379c55'
columns: 2
square: true

DONUT COUNTER

Count total entities {{ states.automation | count }} etc.

yaml
type: custom:apexcharts-card
chart_type: donut
apex_config:
  fill:
    type: gradient
    gradient:
      shade: dark
      shadeIntensity: 0.1
      opacityFrom: 0.9
      opacityTo: 0.85
      stops:
        - 0
        - 90
        - 100
  chart:
    fontFamily: SF Text
  legend:
    position: right
    fontSize: 13px
    fontWeight: 300
    markers:
      width: 16
      height: 25
      customHTML:
        - |-
          EVAL:() => {
            return `<ha-icon icon="hass:robot" style="--mdc-icon-size: 14px;"></ha-icon>`
          }
        - |-
          EVAL:() => {
            return `<ha-icon icon="hass:radiobox-blank" style="--mdc-icon-size: 14px;"></ha-icon>`
          }
        - |-
          EVAL:() => {
            return `<ha-icon icon="hass:account" style="--mdc-icon-size: 14px;"></ha-icon>`
          }
        - |-
          EVAL:() => {
            return `<ha-icon icon="hass:lightbulb" style="--mdc-icon-size: 14px;"></ha-icon>`
          }
        - |-
          EVAL:() => {
            return `<ha-icon icon="hass:cast" style="--mdc-icon-size: 14px;"></ha-icon>`
          }
        - |-
          EVAL:() => {
            return `<ha-icon icon="hass:eye" style="--mdc-icon-size: 14px;"></ha-icon>`
          }
        - |-
          EVAL:() => {
            return `<ha-icon icon="hass:flash" style="--mdc-icon-size: 14px;"></ha-icon>`
          }
        - |-
          EVAL:() => {
            return `<ha-icon icon="hass:home-assistant" style="--mdc-icon-size: 14px;"></ha-icon>`
          }
      fillColors:
        - none
        - none
        - none
        - none
        - none
        - none
        - none
        - none
  stroke:
    show: true
    width: 0.4
  dataLabels:
    enabled: false
    style:
      fontSize: 14px
      fontWeight: 700
    dropShadow:
      enabled: true
      top: 0
      left: 0
      blur: 3
      color: black
      opacity: 0.1
  plotOptions:
    pie:
      startAngle: 0
      endAngle: 360
      expandOnClick: true
      offsetX: 0
      offsetY: 0
      customScale: 1
      dataLabels:
        offset: 0
        minAngleToShowLabel: 10
      donut:
        size: 65%
        background: transparent
        labels:
          show: true
          value:
            fontSize: 42px
            fontWeight: 700
            offsetY: 16
          total:
            show: true
            label: Entities
            fontSize: 15px
            fontWeight: 800
            color: '#ffffff50'
series:
  - entity: sensor.template_domain_counter
    attribute: automation
    name: Automations
  - entity: sensor.template_domain_counter
    attribute: binary_sensor
    name: Binary sensors
  - entity: sensor.template_domain_counter
    attribute: device_tracker
    name: Device trackers
  - entity: sensor.template_domain_counter
    attribute: light
    name: Lights
  - entity: sensor.template_domain_counter
    attribute: media_player
    name: Media players
  - entity: sensor.template_domain_counter
    attribute: sensor
    name: Sensors
  - entity: sensor.template_domain_counter
    attribute: switch
    name: Switches
  - entity: sensor.template_domain_counter
    attribute: other
    name: Other

Excuse the yaml, not used to using ui editor

EDIT: fixed “lines network” graph reversal

32 Likes

Does anyone know if it is possible to hide only the bottom time axis?

I would like a result like this. Like a minimal chart but keep the left value axis:

Edit, solved it:

  xaxis:
    labels:
      show: false
    axisTicks: 
      show: false
2 Likes

How can I add an extra value on the datapoint?

I use the Tautulli sensor to monitor Plex, I’d like to show the number of user watching (works out of the box), but show additional info on datapoint hover, i.e. user, title, these are currently nested attributes of the sensor (see screenshot). Is this possible?

Good morning,
some time ago I’ve made an ApexCharts dashboard for my weather station where, in some charts, I’ve put in header the value of a string sensor as “raw” (like the pressure trend or UV exposition warning) and it was correctly displayed.

From the last update or two of the integration I see, for that sensors, only “NaN” instead of the string.
Is possible to fix this?
How?

Amazing use of the card :slight_smile: Love it, thanks for sharing your work!

That won’t be possible

Please open a bug on github :slight_smile:

Hi @RomRider,

Thanks for the quick reply. That’s not a big deal.

The only other issue I’m having is that because my sensor only updates upon a change, the column chart isn’t reflective of the status, i.e. a user started playing 30 mins ago, I have a single column at that time, but following, the graph is blank (unless the sensor updates, such as when they pause, play). How can I work around this? I tried to ‘fill’, ‘last’ but had no luck?

You can use update_interval instead of relying on the update of the sensor.

That’s what I’ve done, but you can see it’s not working (things have been playing for over 30m)

type: custom:apexcharts-card
graph_span: 1h
update_interval: 5sec
stacked: true
all_series_config:
  show:
    extremas: false
  opacity: 0.1
  fill_raw: zero
now:
  show: false
  label: Now
  color: FF0000
header:
  show: true
  title: 24H Watching Statistics
  show_states: true
  colorize_states: true
series:
  - entity: sensor.tautulli
    attribute: stream_count_direct_play
    name: Direct Play
    curve: stepline
    type: column
    show:
      datalabels: false
      in_chart: true
    float_precision: 0
  - entity: sensor.tautulli
    attribute: stream_count_direct_stream
    name: Direct Stream
    curve: stepline
    type: column
    show:
      datalabels: false
      in_chart: true
    float_precision: 0
  - entity: sensor.tautulli
    attribute: stream_count_transcode
    name: Transcode
    curve: stepline
    type: column
    show:
      datalabels: false
      in_chart: true
    float_precision: 0
apex_config:
  legend:
    show: true
    position: bottom
  plotoptions:
    bar:
      borderRadius: 10
  xaxis:
    tooltip:
      enabled: false

Hello,

I would like to know if there is something to display the time serie by cumulate the value with the previous. Ex: "transform: return Y + (Y-1) "

Would you mind trying without curve: stepline please?

I’m trying to add to my chart when the AC turns on, and I’ve done it, but in a really janky way. What I’ve done is:

transform: 'return x > 100 ? 60 : null;'

but what I want is:

  • When the AC is on, say ‘On’ vs 60
  • A vertical line that fills from top to bottom vs being 60.

Help and thank you so much!

Full YAML Code
type: custom:apexcharts-card
graph_span: 2d
all_series_config:
  stroke_width: 1
  group_by:
    func: max
    fill: last
header:
  show: true
  show_states: false
  colorize_states: false
  title: Temp Overlay
apex_config:
  grid:
    show: false
  legend:
    show: true
  tooltip:
    shared: true
series:
  - entity: sensor.temp_sensor_001_temperature
    type: line
    name: '1'
  - entity: sensor.temp_sensor_002_temperature
    name: '2'
    type: line
  - entity: sensor.temp_sensor_003_temperature
    name: '3'
    type: line
  - entity: sensor.temp_sensor_004_temperature
    name: '4'
    type: line
  - entity: sensor.temp_sensor_005_temperature
    name: '5'
    type: line
  - entity: sensor.6_channel_energy_meter_ct3_watts
    name: AC
    type: area
    transform: 'return x > 100 ? 60 : null;'
    unit: ' '
  - entity: sensor.openweathermap_temperature
    name: Weather
    type: area

I tried the straight option.
Same strange behaviour:


I think that gaps on the apexcharts graphs should be same as on the stock graph.

Correct, I’ve just checked and update_interval is broken, I’ll need to look into it.

Could it be a reason of my issue too?

No, that’s different, I’ll need to investigate.
Please open a github issue as it’s easier for me to track it and update you.

Done.

Hi customizing professionals, is it possible to format the series name, in the example below? I would like to change both the positioning and font/color.

image

series:
  - entity: sensor.aqaratemp1_temperature
    type: area
    name: '>>>>How do i format this text?<<<'
    curve: smooth
    stroke_width: 3
    color: '#1188db'
    opacity: 0.15
    group_by:
      func: last
      duration: 4h
      fill: last