ApexCharts card - A highly customizable graph card

I have the same issues and I’m also trying to display the long term statistics just like the energy dashboard but in the beautiful Apex way :slight_smile: A few weeks ago it sounded like RomRider har an idea on how to change this so hopefully there will be a fix for this. Please share if you find a work-around :slight_smile:

1 Like

Beautiful layout! Would you mind sharing some code showing how you got the small graph cards and the orange button?

Sorry for the delay @filikun, @Airyphyla, @alexreddy78 and @Lunkobelix .

I’m at the begining to create my own card with custom:button-card and I’m sure there are much cleaner ways of doing things than me. But here is the yaml of my card :

card_pool:
  styles:
    card:
      - padding: "0px"
    grid:
      - grid-template-areas: "'cam overlay' 'measures measures'"
      - grid-template-columns: "1fr 0"
      - grid-template-rows: "180px min-content"
    custom_fields:
      overlay:
        - height: 180px
        - background: linear-gradient(180deg, rgba(var(--rgb-card-background-color),0) 45%, rgba(var(--rgb-card-background-color),1) 100%)
        - opacity: 1
        - padding: 0
  custom_fields:
    cam:
      card:
        type: picture-glance
        camera_image: camera.poolcamera
        entities: []
        card_mod:
          style:
            hui-image:
              $: |
                div img {
                  height: 180px;
                  object-fit: cover;
                  object-position: center -25px;
                }
              .: |
                hui-image {
                  height: calc(100% - 0px);
                }
            .: |
              ha-card {
                border-bottom-left-radius: 0px;
                border-bottom-right-radius: 0px;
                box-shadow: none;
              }
              ha-card .box {
                display: none;
              }
    overlay: <div></div>
    measures: 
      card:
        type: custom:button-card
        name: Analyses de l'eau
        label: "[[[ return states['sensor.pool_analysed_at'].state; ]]]"
        show_name: true
        show_label: true
        styles:
          card:
            - padding: 4%
            - border-radius: 0px
            - box-shadow: "none"
          grid:
            - grid-template-areas: "'n tmp . ph . redox . sel' 'l tmp . ph . redox . sel' 'graph graph graph graph graph graph graph graph' 'actions actions actions actions actions actions actions actions' 'infos infos infos infos infos infos infos infos'"
            - grid-template-columns: "1fr 45px 5px 45px 5px 45px 5px 45px"
            - grid-template-rows: "min-content min-content min-content"
          name:
            - font-weight: "bold"
            - font-size: "14px"
            - place-self: end left
          label:
            - font-size: "10px"
            - place-self: start
            - filter: "opacity(40%)"
        custom_fields:
          tmp:
            card:
              type: custom:button-card
              template: button_pool_measure
              name: Temp
              label: "[[[ return states['sensor.pool_temperature'].state + '°C'; ]]]"
              variables:
                  color: "blue"
                  select_value: "Temperature"
          ph:
            card:
              type: custom:button-card
              template: button_pool_measure
              name: pH
              label: "[[[ return states['sensor.pool_ph'].state; ]]]"
              variables:
                  color: "green"
                  select_value: "PH"
                  alert: >
                    [[[
                      let ph = states['sensor.pool_ph'].state;
                      if (ph < 7.1 || ph > 7.5) return true;
                      return false;
                    ]]]
          redox:
            card:
              type: custom:button-card
              template: button_pool_measure
              name: RedOx
              label: "[[[ return states['sensor.pool_orp'].state + 'mV'; ]]]"
              variables:
                  color: "yellow"
                  select_value: "ORP"
                  alert: >
                    [[[
                      let orp = states['sensor.pool_orp'].state;
                      if (orp < 600 || orp > 800) return true;
                      return false;
                    ]]]
          sel:
            card:
              type: custom:button-card
              template: button_pool_measure
              name: Sel
              label: "[[[ return states['sensor.pool_salinity'].state + 'g/l'; ]]]"
              variables:
                  color: "red"
                  select_value: "Sel"
                  alert: >
                    [[[
                      let salinity = states['sensor.pool_salinity'].state;
                      if (salinity < 3 || salinity > 3.4) return true;
                      return false;
                    ]]]
          graph:
            card:
              type: custom:button-card
              entity: input_select.ui_pool_select_measure
              show_icon: false
              state:
                - name: Température de l'eau
                  value: Temperature
                - name: pH de l'eau
                  value: PH
                - name: Rédox de l'eau
                  value: ORP
                - name: Salinité de l'eau
                  value: Sel
              styles:
                card:
                  - border-radius: 0px
                  - box-shadow: "none"
                  - padding-bottom: 0
                name:
                  - font-weight: "normal"
                  - font-size: "12px"
                  - place-self: center left
                grid:
                  - grid-template-areas: "'n i1 . i2 . i3' 'graph graph graph graph graph graph'"
                  - grid-template-columns: "1fr 61px 6px 61px 6px 61px"
                  - grid-template-rows: "min-content min-content"
              custom_fields:
                i1: 
                  card:
                    type: custom:button-card
                    template: button_pool_period
                    name: Jour
                    variables:
                      period: Jour
                i2: 
                  card:
                    type: custom:button-card
                    template: button_pool_period
                    name: Semaine
                    variables:
                      period: Semaine
                i3:
                  card:
                    type: custom:button-card
                    template: button_pool_period
                    name: Mois
                    variables:
                      period: Mois
                graph:
                  card:
                    type: grid
                    square: false
                    columns: 1
                    cards:
                      - type: conditional
                        conditions:
                          - entity: input_select.ui_pool_select_measure
                            state: 'Temperature'
                        card:
                          type: custom:button-card
                          template: graph_pool_measure
                          variables:
                            entity: sensor.pool_temperature
                            color: "blue"
                            decimal: 0
                      - type: conditional
                        conditions:
                          - entity: input_select.ui_pool_select_measure
                            state: 'PH'
                        card:
                          type: custom:button-card
                          template: graph_pool_measure
                          variables:
                            entity: sensor.pool_ph
                            color: "green"
                            decimal: 1
                            yaxis:
                              min: 6.9
                              max: 7.7
                            annotations:
                              min:
                                value: 7.1
                                text: "7.1"
                              max:
                                value: 7.5
                                text: "7.5"
                      - type: conditional
                        conditions:
                          - entity: input_select.ui_pool_select_measure
                            state: 'ORP'
                        card:
                          type: custom:button-card
                          template: graph_pool_measure
                          variables:
                            entity: sensor.pool_orp
                            color: "yellow"
                            decimal: 0
                            yaxis:
                              min: 500
                              max: 800
                            annotations:
                              min:
                                value: 650
                                text: "650mv"
                              max:
                                value: 750
                                text: "750mv"
                      - type: conditional
                        conditions:
                          - entity: input_select.ui_pool_select_measure
                            state: 'Sel'
                        card:
                          type: custom:button-card
                          template: graph_pool_measure
                          variables:
                            entity: sensor.pool_salinity
                            color: "red"
                            decimal: 1
                            curve: "stepline"
                            yaxis:
                              min: 2.9
                              max: 3.4
          actions:
            card:
              type: custom:button-card
              styles:
                card:
                  - border-radius: 0px
                  - box-shadow: "none"
                  - padding-top: 0
                grid:
                  - grid-template-areas: " 'a1 . a2 . a3'"
                  - grid-template-columns: "1fr 10px 1fr 10px 1fr"
                  - grid-template-rows: "min-content"
              custom_fields:
                a1:
                  card:
                    type: custom:button-card
                    template: button_pool_action 
                    entity: switch.piscine_filtration
                    name: Filtration
                    icon: mdi:engine
                    label: "[[[ return states['sensor.pool_pump_duration'].state; ]]]"
                    variables:
                      schedules: "[[[ return states['sensor.pool_pump_hours'].state; ]]]"
                a2:
                  card:
                    type: custom:button-card
                    template: button_pool_action 
                    entity: switch.piscine_surpresseur
                    name: Robot
                    icon: mdi:robot-mower
                    label: "[[[ return states['sensor.robot_duration'].state; ]]]"
                    variables:
                      schedules: "[[[ return states['input_text.robot_hours'].state; ]]]"
                a3:
                  card:
                    type: custom:button-card
                    template: button_pool_action
                    entity: switch.piscine_electrolyseur_sel
                    name: Electrolyseur
                    icon: mdi:electron-framework
                    label: "[[[ return states['sensor.electrolyseur_sel_duration'].state; ]]]"
                    variables:
                      schedules: "-"
          infos:
            card:
              type: custom:button-card
              styles:
                card:
                  - border-radius: 0px
                  - box-shadow: "none"
                  - padding-top: 0
                grid:
                  - grid-template-areas: " 'i1 . i2 . i3 . i4'"
                  - grid-template-columns: "1fr 10px 1fr 10px 1fr 10px 1fr"
                  - grid-template-rows: "min-content"
              custom_fields:
                i1:
                  card:
                    type: custom:button-card
                    template: button_pool_info
                    name: Lumières
                    icon: mdi:lightbulb
                i2:
                  card:
                    type: custom:button-card
                    template: button_pool_info
                    name: Mode<br/>filtration
                    label: "[[[ return states['input_select.pool_pump'].state; ]]]"
                    tap_action:
                      action: 'fire-dom-event'
                      browser_mod:
                        command: "popup"
                        large: true
                        hide_header: true
                        card:
                          type: "custom:button-card"
                          template: "popup_pool_pump"
                        style:
                          $: |
                            .mdc-dialog .mdc-dialog__container .mdc-dialog__surface {
                              box-shadow: none;
                              border-radius: 0px;
                              background-color: var(--main-background-color);
                            }
                i3:
                  card:
                    type: custom:button-card
                    template: button_pool_info
                    name: Lavage<br/>filtre
                    label: Il y a 10 jours
                    variables:
                      alert: false
                i4:
                  card:
                    type: custom:button-card
                    template: button_pool_info
                    name: Lavage<br/>skimmers
                    label: Il y a 25 jours
                    variables:
                      alert: true

graph_pool_measure:
  variables:
    entity : ""
    color: ""
    decimal: 0
    curve: "smooth"
    annotations:
      min:
        value: -100
        text: ""
      max:
        value: -100
        text: ""
    yaxis:
      min: auto
      max: auto
  styles:
    card:
      - padding: 0px
      - border-radius: 0px
      - box-shadow: "none"
    grid:
      - grid-template-areas: "'graph'"
      - grid-template-columns: "1fr"
      - grid-template-rows: "min-content"
  custom_fields:
    graph:
      card:
        type: custom:apexcharts-card
        header:
          show: false
        graph_span: >
          [[[
            switch (states['input_select.ui_pool_select_measure_period'].state) {
              case "Mois":
                return "4w";
                break
              case "Semaine":
                return "1w";
                break;
              case "Jour":
                return "1d";
                break;
            }
          ]]]
        series:
          - entity: "[[[ return variables.entity; ]]]"
            stroke_width: 3
            color: "[[[ return `var(--google-${variables.color})`; ]]]"
            fill_raw: last
            type: area
        yaxis:
          - decimals: "[[[ return variables.decimal; ]]]"
            min: "[[[ return variables.yaxis.min; ]]]"
            max: "[[[ return variables.yaxis.max; ]]]"
            apex_config:
              tickAmount: 5
              forceNiceScale: true
              labels:
                offsetX: -15
        apex_config:
          chart:
            height: 200px
          grid:
            padding:
              left: 0
              right: 0
          fill:
            type: 'gradient'
            gradient:
              shade: "light"
              type: "vertical"
              opacityFrom: 0.7
              opacityTo: 0.1
              stops: [0, 100]
          stroke:
            curve: "[[[ return variables.curve; ]]]"
          annotations:
            position: 'front'
            yaxis:
              - y: "[[[ return variables.annotations.min.value; ]]]"
                y2: "[[[ return variables.annotations.max.value; ]]]"
                opacity: 0.2
              - y: "[[[ return variables.annotations.max.value; ]]]"
                strokeDashArray: 0
                label:
                  text: "[[[ return variables.annotations.max.text; ]]]"
                  offsetX: -5
                  offsetY: -1
                  style:
                    fontSize: 8px
              - y: "[[[ return variables.annotations.min.value; ]]]"
                strokeDashArray: 0
                label:
                  text: "[[[ return variables.annotations.min.text; ]]]"
                  offsetX: -5
                  offsetY: -1
                  style:
                    fontSize: 8px
        card_mod:
          style: |
            ha-card {
              border-radius: 0px;
              box-shadow: none;
              padding: 0;
              margin: 0;
            }
            #state__name, .apexcharts-xaxis-label, .apexcharts-yaxis-label {
              font-size: 10px !important;
            }

button_pool_measure:
  variables:
    color: "blue"
    select_value: "Temperature"
    alert: false
  show_name: true
  show_label: true
  aspect_ratio: 1/1
  styles:
    card:
      - padding: "0px"
      - box-shadow: none
      - background-color: var(--primary-background-color)
      - background-image: >
          [[[
              let theme = hass.themes.themes[hass.themes.theme].modes[(hass.themes.darkMode ? "dark" : "light")];
              let color_bckg = theme[`google-${variables.color}`].replace('#', '%23');
              let opacity = theme['opacity-bg'];
              return "url(\"data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' viewBox='0 0 1440 1440'><path fill='"+color_bckg+"' fill-opacity='"+opacity+"' d='m 0,566 48,26.7 C 96,619 192,673 288,699.3 384,726 480,726 576,710 c 96,-16 192,-48 288,-42.7 96,5.7 192,47.7 288,58.7 96,11 192,-11 240,-21.3 l 48,-10.7 v 754 H 1392 1152 864 576 288 48 0 Z'></path></svg>\")";
          ]]]
      - background-size: 100%
    grid:
      - grid-template-areas: "'n' 'l'"
      - grid-template-columns: "1fr"
      - grid-template-rows: "auto auto"
    name:
      - font-size: "10px"
      - place-self: center
    label:
      - font-size: "10px"
      - place-self: center
      - font-weight: "bold"
      - color: >
          [[[
            if (hass.themes.darkMode){
              return "#FFFFFF";
            } else {
              return `rgba(var(--color-${variables.color}), 1)`;
            }
          ]]]
    custom_fields:
      notification:
        - border-radius: "50%"
        - position: "absolute"
        - right: "2px"
        - top: "14px"
        - height: "12px"
        - width: "12px"
        - border: "1px solid var(--card-background-color)"
        - font-size: "6px"
        - line-height: "12px"
        - background-color: >
            [[[
              return "rgba(var(--color-red),1)";
            ]]]
  custom_fields:
    notification: >
      [[[
        if (variables.alert) {
          return `<ha-icon icon="mdi:exclamation" style="width: 9px; height: 9px; color: var(--primary-background-color);"></ha-icon>`
        }
      ]]]
  tap_action:
    action: call-service
    service: input_select.select_option
    service_data:
      entity_id: input_select.ui_pool_select_measure
      option: "[[[ return `${variables.select_value}`; ]]]"

button_pool_period:
  variables:
    period: "Semaine"
  show_name: true
  styles:
    card:
      - padding: "5px 0px"
      - box-shadow: none
      - background-color: >
          [[[
            if (states['input_select.ui_pool_select_measure_period'].state == variables.period) {
              switch (states['input_select.ui_pool_select_measure'].state) {
                case "Temperature":
                  return "var(--google-blue)";
                case "PH":
                  return "var(--google-green)";
                case "ORP":
                  return "var(--google-yellow)";
                case "Sel":
                  return "var(--google-red)";
                default:
                  return "var(--primary-background-color)";
              }
            } else {
              return "var(--primary-background-color)";
            }
          ]]]
    name:
      - font-size: "10px"
      - place-self: center
      - color: >
          [[[
            if (states['input_select.ui_pool_select_measure_period'].state == variables.period) {
              return "white";
            } else {
              return "var(--primary-text-color)";
            }
          ]]]
  tap_action:
    action: call-service
    service: input_select.select_option
    service_data:
      entity_id: input_select.ui_pool_select_measure_period
      option: "[[[ return `${variables.period}`; ]]]"

button_pool_action:
  variables:
    schedules: "-"
  show_name: true
  show_label: true
  show_icon: true
  styles:
    card:
      - padding: "5px 0px"
      - box-shadow: none
      - background-color: var(--primary-background-color)
    grid:
      - grid-template-areas: "'n' 'l' 'i' 'schedules'"
      - grid-template-columns: "1fr"
      - grid-template-rows: "min-content min-content min-content min-content"
    name:
      - font-size: "12px"
      - place-self: center
      - font-weight: "bold"
    label:
      - font-size: "10px"
      - place-self: center
      - filter: "opacity(40%)"
    custom_fields:
      schedules:
        - font-size: "10px"
        - place-self: center
        - filter: "opacity(40%)"
  custom_fields:
    schedules: "[[[ return `${variables.schedules}`; ]]]"

button_pool_info:
  variables:
    alert: false
  show_name: true
  show_label: true
  show_icon: true
  styles:
    card:
      - padding: "5px 10px"
      - box-shadow: none
      - background-color: var(--primary-background-color)
      - height: 55px
    grid:
      - grid-template-areas: "'n' 'l' 'i'"
      - grid-template-columns: "1fr"
      - grid-template-rows: "min-content min-content"
    name:
      - font-size: "10px"
      - place-self: center
      - font-weight: "bold"
    label:
      - font-size: "10px"
      - place-self: center
      - filter: "opacity(40%)"
      - padding-top: 5px
    icon:
      - padding-top: 3px
    custom_fields:
      notification:
        - border-radius: "50%"
        - position: "absolute"
        - right: "2px"
        - top: "2px"
        - height: "16px"
        - width: "16px"
        - border: "2px solid var(--card-background-color)"
        - font-size: "12px"
        - line-height: "14px"
        - background-color: >
            [[[
              return "rgba(var(--color-red),1)";
            ]]]
  custom_fields:
    notification: >
      [[[
        if (variables.alert) {
          return `<ha-icon icon="mdi:exclamation" style="width: 12px; height: 12px; color: var(--primary-background-color);"></ha-icon>`
        }
      ]]]

For the question :

It’s both at the same time :slight_smile:
For the choice of temperature, redox,… it’s an input_select with a conditional card and a unique chart template.
For the choice of the period it is also an input_select that I process in my chart template on the attribute graph_span

8 Likes

Wow! Thanks :+1:

this made me want to rebuild my own card (see above) that uses the config-template-card to do just that, adapt the graph_span based on an input_select.apex_span. Why use an extra card, if we can template directly (I wasnt aware)?

but, using

graph_span: >
  [[[ return states['input_select.apex_span'].state; ]]]

throws the error

making me think templates aren’t supported on that field…

and the docs dont mention templates being supported either:

obviously my input_selects holds only valid options

now why would that be? How did you make the templates a valid graph_span input…

for now, back to:

type: custom:config-template-card
entities:
  - input_select.apex_span
variables:
  span: states['input_select.apex_span'].state
card:

  type: custom:apexcharts-card
  graph_span: ${span}

if I enter the template you use, and adapt with my options, the card is displayed alright, but changing a selection does not update the graph at all. So a bit of a mystery here…:wink:
just in case: FR: allow template on graph_span · Issue #344 · RomRider/apexcharts-card · GitHub

Hi,

I am seeking some help as I have spent hours fiddling can not see the forest from the trees now.

My Card is loading blank… annoying. I have other apex cards, working with no issue. This particular entity (actually group of entities) just will not work.

You can see its consuming some level of data, as it nows the timeline and scales on the axis’s. Legend also shows max values for the period.

Card:

type: custom:apexcharts-card
span:
  start: minute
header:
  show: true
  title: EMHASS Forecasts
  show_states: true
  colorize_states: true
now:
  show: true
  label: now
series:
  - entity: sensor.p_pv_forecast
    curve: stepline
    show:
      in_header: before_now
    stroke_width: 1
    data_generator: |
      return entity.attributes.forecasts.map((entry) => {
        return [new Date(entry.date), entry.p_pv_forecast];
      });
  - entity: sensor.p_batt_forecast
    curve: stepline
    show:
      in_header: before_now
    stroke_width: 1
    data_generator: |
      return entity.attributes.forecasts.map((entry) => {
        return [new Date(entry.date), entry.p_batt_forecast];
      });
  - entity: sensor.p_load_forecast
    curve: stepline
    show:
      in_header: before_now
    stroke_width: 1
    data_generator: |
      return entity.attributes.forecasts.map((entry) => {
        return [new Date(entry.date), entry.p_load_forecast];
      });

Entity Attributes:

unit_of_measurement: W
friendly_name: Battery Power Forecast
forecasts:
  - date: '2022-06-03 20:30:00+10:00'
    p_batt_forecast: -7899
  - date: '2022-06-03 21:00:00+10:00'
    p_batt_forecast: -4320
  - date: '2022-06-03 21:30:00+10:00'
    p_batt_forecast: -7015
  - date: '2022-06-03 22:00:00+10:00'
    p_batt_forecast: 0
  - date: '2022-06-03 22:30:00+10:00'
    p_batt_forecast: 0
  - date: '2022-06-03 23:00:00+10:00'
    p_batt_forecast: 0
  - date: '2022-06-03 23:30:00+10:00'
    p_batt_forecast: 0
  - date: '2022-06-04 00:00:00+10:00'
    p_batt_forecast: 0
  - date: '2022-06-04 00:30:00+10:00'
    p_batt_forecast: 0
  - date: '2022-06-04 01:00:00+10:00'
    p_batt_forecast: 0
  - date: '2022-06-04 01:30:00+10:00'
    p_batt_forecast: 0
  - date: '2022-06-04 02:00:00+10:00'
    p_batt_forecast: 0
  - date: '2022-06-04 02:30:00+10:00'
    p_batt_forecast: 0
  - date: '2022-06-04 03:00:00+10:00'
    p_batt_forecast: 0
  - date: '2022-06-04 03:30:00+10:00'
    p_batt_forecast: 669
  - date: '2022-06-04 04:00:00+10:00'
    p_batt_forecast: -669
  - date: '2022-06-04 04:30:00+10:00'
    p_batt_forecast: 0
  - date: '2022-06-04 05:00:00+10:00'
    p_batt_forecast: 699
  - date: '2022-06-04 05:30:00+10:00'
    p_batt_forecast: 2643
  - date: '2022-06-04 06:00:00+10:00'
    p_batt_forecast: -4988
  - date: '2022-06-04 06:30:00+10:00'
    p_batt_forecast: 3653
  - date: '2022-06-04 07:00:00+10:00'
    p_batt_forecast: 2346
  - date: '2022-06-04 07:30:00+10:00'
    p_batt_forecast: 2268
  - date: '2022-06-04 08:00:00+10:00'
    p_batt_forecast: 1289
  - date: '2022-06-04 08:30:00+10:00'
    p_batt_forecast: 882
  - date: '2022-06-04 09:00:00+10:00'
    p_batt_forecast: -944
  - date: '2022-06-04 09:30:00+10:00'
    p_batt_forecast: -1528
  - date: '2022-06-04 10:00:00+10:00'
    p_batt_forecast: -2063
  - date: '2022-06-04 10:30:00+10:00'
    p_batt_forecast: -2357
  - date: '2022-06-04 11:00:00+10:00'
    p_batt_forecast: -2568
  - date: '2022-06-04 11:30:00+10:00'
    p_batt_forecast: -2674
  - date: '2022-06-04 12:00:00+10:00'
    p_batt_forecast: -2649
  - date: '2022-06-04 12:30:00+10:00'
    p_batt_forecast: -5000
  - date: '2022-06-04 13:00:00+10:00'
    p_batt_forecast: -5000
  - date: '2022-06-04 13:30:00+10:00'
    p_batt_forecast: -5000
  - date: '2022-06-04 14:00:00+10:00'
    p_batt_forecast: -5000
  - date: '2022-06-04 14:30:00+10:00'
    p_batt_forecast: -1661
  - date: '2022-06-04 15:00:00+10:00'
    p_batt_forecast: 2157
  - date: '2022-06-04 15:30:00+10:00'
    p_batt_forecast: 4782
  - date: '2022-06-04 16:00:00+10:00'
    p_batt_forecast: 2131
  - date: '2022-06-04 16:30:00+10:00'
    p_batt_forecast: 5000
  - date: '2022-06-04 17:00:00+10:00'
    p_batt_forecast: -1152
  - date: '2022-06-04 17:30:00+10:00'
    p_batt_forecast: 5000
  - date: '2022-06-04 18:00:00+10:00'
    p_batt_forecast: 5000
  - date: '2022-06-04 18:30:00+10:00'
    p_batt_forecast: 5000
  - date: '2022-06-04 19:00:00+10:00'
    p_batt_forecast: 5000
  - date: '2022-06-04 19:30:00+10:00'
    p_batt_forecast: 5000
  - date: '2022-06-04 20:00:00+10:00'
    p_batt_forecast: 5000

Any help would be appreciated as I am starting to lose my marbles.

Maybe you are missing the graph_span.
Try adding:

graph_span: 24h
span:
  start: minute

I’m trying to learn how to setup these charts - is it possible (think I’ve seen it) to take a sensor and plot a graph over several days, lets say yesterday and today and have those in different colors or in some way divided so I can see clearly the different days?

Hi all,
Just found this ApexCharts card in HA, now looking if I can do an XY chart.
I want to make a chart where the X axis is not a datetime but a value from sensor history.
Idea is to make a hysteresis diagram for some temp/rh sensors.
Basically something like this:
https://apexcharts.com/javascript-chart-demos/scatter-charts/basic/

How would I do that in HA ?

Thanks @davidusb

I had it removed it, added it etc.

It’s back in now. Same result.

Super weird

There are still some other problems, but I solved this one.
You can not use span:start or span:end, then weeks work:

type: custom:apexcharts-card
graph_span: 7day
span:
  offset: +1d
series:
  - entity: sensor.home_meter_grid_energy
    type: column
    statistics:
      type: sum
      period: day
      align: middle
    group_by:
      func: diff
      duration: 1d
      fill: last
      start_with_last: true
    float_precision: 2
    show:
      legend_value: false

I’m creating an Status page to show all tech related numbers.

I also want to replicate the Adguard DNS Queries and blocked queries stats, and stack them in 1 graph.
With the energy meter i spliced them to give me daily numbers (and tested first omn 15 min numbers.)

How it looks in adguard.
adguart sensor span

  • i would keep the tekst style of 3.103.658 DNS Queries (Blocked total - sensor.adguard_dns_queries)
  • i want to show the current total average percentage on the top right in the combined stats. (sensor.adguard_dns_queries_blocked_ratio)
  • want want the hover to show the same as adguard do’s. number and date. but with the numbers blocked added between the date and total dns queries.
    image

Look i want (photo-shopped):
wanted

How i made it so far. Almost, except some details.

Code:

type: custom:apexcharts-card
graph_span: 6h #< will go to 60d
brush:
  selection_span: 1h #< will go to 24h
header:
  show: true
  show_states: true
  colorize_states: true
series:
  - entity: sensor.dns_queries
    stroke_width: 1.5
    type: area
    opacity: 0.1
  - entity: sensor.dns_queries_blocked
    stroke_width: 1.5
    type: area
    opacity: 0.1
cache: true
layout: minimal
color_list:
  - blue
  - red

Any help/direction is appreciated.

Hello. I’m trying to duplicate the mystical history chart that shows one sensor and then shades the area under the graph based on another sensor. (picture example attached) The example shows the thermostat current temperature and shades under the graph when the thermostat is in the ‘cooling’ state (actively running the AC).

It seems that this should be doable using this apex charts card by transforming the cooling state data and plotting it as an area curve.

  1. I need to get all of the data for the thermostat temperature and the thermostat cooling state (I have a template sensor for the cooling state)
  2. I need to transform the values of the cooling state sensor data into numbers: either the value of the thermostat temperature at the given time or 0. Thus, an area graph of the thermostat state will shade under the corresponding temperature value.

I’m trying to use the transform option but I’m having trouble with hass.states['sensor.thermostat_temperature']. It is only returning the same value for every thermostat cooling data point (I think it’s the current value), instead of returning the value of the thermostat temperature at each thermostat cooling state data point.

Not working code:

transform: "
                return x === 'idle' ? 0 : hass.states['sensor.thermostat_temperature'].state;
                "

Maybe a feature could be added for shading an area graph based on a binary value from a different sensor?

Maybe this isn’t the correct way to approach the problem. Has anyone else tried to do this? Any advice?

Thanks.

Okay, at the end of writing this I realized that I could just make the thermostat cooling template sensor equal to the thermostat temperature when cooling or 0 when not, instead of trying to get apex charts to do a transform. I still would like to know how to use the hass.states['sensor.other'] in a transformation though.

2 Likes

In an area chart, is there a way to stack the area of positive curves together and negative curves together? I have electricity producers (solar+grid) and consumers (house, EV, grid, they all have the “invert: true” setting). If I just enable “stacked: true” it looks terrible wrong. I would like the producers to stack on the positive Y axis and the consumers to stack on the negative Y axis.
Any hint is appreciated (and thanks for the marvelous tool!)

1 Like

I would love to patch that functionality - especially the select time period, but…
…where to put the code? If I simply put that as a card, I get a no card type defined.
So I assumed to put that code into the ui-locelace.yaml, but what to do then?

Might someone please give some hints?

Hi Guys,

When I move my finger or mouse over the Apex Graph there is a pop up showing data. Is there anyway to stop that action so not to block the chart with additional data that I dont want to see? Ideally at most I would only like to see the time line and values below the chart as I mouse or move across the chart.

I’m getting a blank graph unfortuunately. Long term statistics just isn’t stable for me and not working fully yet…

type: custom:apexcharts-card
header:
  title: ''
  show: false
  show_states: true
graph_span: 7day
span:
  offset: +1d
...
series:
  - entity: sensor.last_meter_consumption
    name: Förbrukning per dag
    type: column
    color: fc7703
    statistics:
      type: sum
      period: day
      align: middle
    group_by:
      func: diff
      duration: 1d
      fill: last

Changing duration to “2d” gives me a graph but only data for every second day :slight_smile:

Anyone able to help ?

I’ve fixed this issue for anyone looking for a solution on this. The reason is that the data_generator for the series in question had an issue, with one of the datapoints being invalid. Apparently the column type handles this just fine but a line or area won’t show if that is the case.

You can do that with the data_generator option for a series, and altering the x-axis in apex_config. You’ll need to write some javascript code. I did my prototype function in CodeSandBox with MomentJS .

1 Like