ApexCharts card - A highly customizable graph card

Good morning.
My problem seems very simple, but I can’t find the solution…
I have 3 series (electrical phases) that share the axes, scales and marked limits.
The problem I have is that if I click on the series name (below) to stop viewing one and concentrate on another, when I bring up Phase A, it removes the axes and limits from my view. When I bring up Phases B and C, it doesn’t. It’s like everything is associated with Phase A, but I can’t find this in the configuration.
Does anyone know what’s wrong or what I need to configure so that the information is visible in all the series? Thanks.

type: custom:apexcharts-card
header:
  standard_format: false
  show: true
  show_states: true
  colorize_states: true
  title: Tensión
experimental:
  color_threshold: true
graph_span: 3h
yaxis:
  - min: ~195
    max: ~245
apex_config:
  annotations:
    yaxis:
      - "y": 198
        borderColor: red
        borderWidth: 1
      - "y": 242
        borderColor: red
        borderWidth: 1
show:
  last_updated: true
  loading: true
all_series_config:
  curve: smooth
  stroke_width: 1
  show:
    extremas: true
    header_color_threshold: true
series:
  - entity: sensor.mapuche_channel_a_voltage
    name: Fase A
    color: CornflowerBlue
    group_by:
      duration: 1sec
  - entity: sensor.mapuche_channel_b_voltage
    name: Fase B
    color: DarkCyan
    group_by:
      duration: 1sec
  - entity: sensor.mapuche_channel_c_voltage
    name: Fase C
    color: DarkMagenta
    group_by:
      duration: 1sec




Put it under apex_config

Thanks for the reply.
If I put it like this (see code) it doesn’t take the limits. Putting it or not has the same effect… It’s true that I see the axes with any selection, but I lose the maximum and minimum limits.
Or did I do it wrong?

apex_config:
  annotations:
    yaxis:
      - min: ~195
        max: ~245      
      - "y": 198
        borderColor: red
        borderWidth: 1
      - "y": 242
        borderColor: red
        borderWidth: 1

It is not in annotations… now you are one step too deep
EDIT: it is a bit fiddly so it seems

apex_config:
  yaxis:
    - min: ~2
      max: 25
  annotations:
    yaxis:
      - "y": "10"
        borderColor: red
        borderWidth: 1
      - y: '20'
        borderColor: green
        borderWidth: 1

Hi,

I have the following chart

What I would like to have is

  • that the tooltip show from all 3 graphs the value when I move the position

Here is the card-config:

type: custom:apexcharts-card
apex_config:
  stroke:
    width: 3
    curve: smooth
  chart:
    zoom:
      type: x
      enabled: true
      autoScaleYaxis: false
    toolbar:
      show: true
      autoSelected: zoom
  dataLabels:
    enabled: true
    dropShadow:
      enabled: true
  xaxis:
    labels:
      show: true
      rotate: -15
      rotateAlways: true
    type: datetime
  yaxis:
    - title:
        text: Wasser
      axisTicks:
        show: true
        color: yellow
      axisBorder:
        show: false
        color: "#008FFB"
      decimalsInFloat: 0
      opposite: false
      labels:
        show: true
        style:
          colors: Yellow
      tooltip:
        enabled: true
    - title:
        text: Gas
      axisTicks:
        show: true
        color: "#008FFB"
      axisBorder:
        show: true
        color: "#008FFB"
      decimalsInFloat: 0
      opposite: true
      labels:
        show: true
        style:
          colors: "#008FFB"
      tooltip:
        enabled: true
    - title:
        text: Strom
      axisTicks:
        show: true
        color: "#008FFB"
      axisBorder:
        show: true
        color: "#008FFB"
      decimalsInFloat: 0
      opposite: true
      labels:
        show: true
        style:
          colors: "#008FFB"
      tooltip:
        enabled: true
header:
  show: true
  floating: false
  show_states: true
  colorize_states: true
now:
  show: true
  color: red
  label: jetzt
all_series_config:
  stroke_width: 2
graph_span: 24h
span:
  start: day
  offset: +0h
series:
  - entity: sensor.hw_watermeter_1997fa_wasser_verbrauch_in_l_taglich
  - entity: sensor.gaszahler_verbrauch_volumen_heute
  - entity: sensor.stromzahler_energy_energy_daily

Thanks! :slight_smile:

Hi All,

I still can’t figure out how to use the server time. Most of my attempts result in an error, but when I try the code below, there is no error, but the chart just says “Loading…” and never returns any data.

type: custom:apexcharts-card
graph_span: 2h
all_series_config:
  stroke_width: 1.5
yaxis:
  - id: temp
    decimals: 0
    min: ~90
    max: ~101
series:
  - entity: sensor.water_temperature
    yaxis_id: temp
    name: Temp
    data_generator: |
      return entity.attributes.serverDatetime.map((serverTime, index) => {
        return [new Date(serverTime).getTime(), parseFloat(entity.state)];
      });

This doesn’t seem right since I don’t see a serverDatetime attribute on the temperature sensor (a Ds182b20). How should I reference the server time?

Edit - I don’t know javascript other than googling and trying to reverse engineer what others have used. :slight_smile:

Edit 2: The browser console log shows this:

Error: TypeError: entity.attributes.serverDatetime is undefined in 'return entity.attributes.serverDatetime.map((serverTime, index) => {
  return [new Date(serverTime...'

How can I reference the server time?

I wish I would be able to present a better solution (not mine, copied) but…

apex_config:
      tooltip:
        enabled: true
        shared: true
        custom: >
          EVAL:function customTooltip({ series, seriesIndex,
          dataPointIndex, w }) {
              const hoverXaxis = w.globals.seriesX[seriesIndex][dataPointIndex];
              const hoverIndexes = w.globals.seriesX.map((seriesX) => {
                let min = Math.abs(seriesX[0] - hoverXaxis);
                let minIndex = 0;
                for (let i = 1; i < seriesX.length; i++) {
                  const v = Math.abs(seriesX[i] - hoverXaxis);
                  if (v < min) { 
                    min = v;
                    minIndex = i;
                  }
                 }
                return minIndex
              });

              let hoverList = "";
              hoverIndexes.forEach((hoverIndex, seriesEachIndex) => {
                  if (hoverIndex >= 0) {
                      hoverList += `
                          <div class="apexcharts-tooltip-series-group apexcharts-active" style="order: 1; display: flex;">
                              <span class="apexcharts-tooltip-marker" style="background-color: ${
                                  w.globals.markers.colors[seriesEachIndex]
                              };"></span>
                              <div class="apexcharts-tooltip-text" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px;">
                                  <div class="apexcharts-tooltip-y-group">
                                      <span class="apexcharts-tooltip-text-y-label">${
                                          w.globals.seriesNames[seriesEachIndex]
                                      }: </span>
                                      <span class="apexcharts-tooltip-text-y-value">${w.globals.yLabelFormatters[0](
                                          series[seriesEachIndex][hoverIndex]
                                      )}</span>
                                  </div>
                              </div>
                          </div>`;
                  }
              });
              const parsed = new Date(hoverXaxis)
                  .toDateString()
                  .split(" ")
                  .slice(1);
              return `<div class="apexcharts-tooltip-title" style="font-family: Helvetica, Arial, sans-serif; font-size: 12px;">${
                  parsed[1] + " " + parsed[0] + " " + parsed[2]
              }</div>${hoverList}`;
          }
2 Likes

This indicates that you are using the attribute with that name for that entity, is that correct? Show the data maybe?

Any Idee how I get the decimal digest in the tooltip?

Your original picture does not show dec’s …so do they exist?

Yes they do exist

Thanks for the reply. That is where I’m getting stuck. The temp sensor does not have an attribute for the server time, so I know that’s not right. From the Developer Tools, this is all that is available with the sensor:

state_class: measurement
unit_of_measurement: °F
device_class: temperature
friendly_name: Water Temperature

This is the Github page that indicates that it is possible to use the server time, but I can’t find a reference for how to do it with an entity that doesn’t have that attribute

The only code reference (after the feature was introduced) was asking for help and I don’t understand the response or how to apply it to my situation. All I am trying to do is force the chart to use the time from the server. Not looking to shift it or anything else.

I’m not sure what you mean by show the data. Here is what the chart looks like if I remove the data_generator:
image

I’m sure it’s something small that I am missing, I just don’t know what.

Seeking some advice here, followed this thread: Apexchart med fargekoding for strømpriser og strømforbruk, Nordpool og Tibber - Lovelace - Hjemmeautomasjon and with my code, it does not load/ generate any graph.

I will forward a virtual beer to anyone that can support me, as I have discussed with chatgpt down a rabbit hole for the last 2 hours without solving it :frowning:

type: custom:config-template-card
variables:
  sensor_price: sensor.huset_electricity_price
  sensor_usage: sensor.tibber_pulse_huset_accumulated_consumption_current_hour
  low_price: states['sensor.nord_pool_no1_lowest_price'].attributes.min
  high_price: states['sensor.nord_pool_no1_highest_price'].attributes.max
  mean_price: states['sensor.nord_pool_no1_next_price'].attributes.mean
  current_price: states['sensor.price_with_subsidy_tomtabakken_4b'].state
  state_color: |
    (low, high, current) => {
      const range = high - low;
      const third_low = low + range / 3;
      const third_high = high - range / 3;

      if (current <= third_low) {
        return '#42a047';  // Green
      } else if (current <= third_high) {
        return '#ffa600';  // Orange
      } else {
        return '#db4437';  // Red
      }
    }
entities:
  - ${sensor_price}
  - ${sensor_usage}
card:
  type: custom:apexcharts-card
  experimental:
    color_threshold: true
  header:
    show: true
    title: Strømpris og Forbruk
    show_states: true
    standard_format: true
    colorize_states: true
  now:
    show: true
    label: Nå
  graph_span: 2d
  span:
    start: day
  apex_config:
    dataLabels:
      enabled: true
    legend:
      show: true
    chart:
      height: 210px
    yaxis:
      - id: price
        show: true
        decimalsInFloat: 0
        floating: false
        forceNiceScale: true
      - id: usage
        show: true
        opposite: true
        decimalsInFloat: 0
        floating: false
        forceNiceScale: true
  series:
    - entity: ${sensor_price}
      yaxis_id: price
      extend_to: now
      name: Pris
      unit: " øre/kWh"
      stroke_width: 1
      type: area
      curve: stepline
      float_precision: 0
      color: ${state_color(low_price, high_price, current_price)}
      color_threshold:
        - value: ${low_price}
          color: "#42a047"
        - value: ${mean_price}
          color: "#ffa600"
        - value: ${high_price}
          color: "#db4437"
      show:
        legend_value: false
        in_header: before_now
      data_generator: |
        return (entity.attributes.raw_today.map((entry) => { 
          return [new Date(entry.start).getTime(), entry.value];
        })).concat(entity.attributes.raw_tomorrow.map((entry) => { 
          return [new Date(entry.start).getTime(), entry.value];
        }));
    - entity: ${sensor_usage}
      yaxis_id: usage
      type: column
      name: Forbruk
      stroke_width: 2
      invert: false
      group_by:
        func: max
      show:
        legend_value: false


It speaks of server time ZONE and not sure what you want to accomplish / need

Maybe someone with the same setup can help. My approach would be to decompose it and start without the use of variables and add gradually add them

Thanks.
But the variable scale functionality if it exceeds the limits that the “~” symbol gives me would not be working within apex_config.
Moreover, I think that in your example it does not work either, because you should see the axis between 2 and 25 (because your lower part of the graph is not lower than 2) and you see it from 0 to 25.
I tried putting it with fixed limits (that is, without “~”) and my problem is partially solved, because I see the scales and limits in all the series, but in this way if the limits are exceeded, they are left out of the graph.

Apparently one cannot have all :neutral_face: so fix the max/min or… accept hidden axis
Along apexcharts.js you could create a function too, to set the values min/max but I have no example/experience
EDIT: not sure if this is a direction but…

  yaxis:
    - min:   EVAL:min => min -2
      max:   EVAL:max => max +3

All I want is to use the time from the server, not the client. You make a good point on ‘time’ vs ‘timezone’ and it may not be possible. Still, I’d like to test it. RomRider’s last comment in the Github thread makes me think it might be possible using start.getTime()

Without veering too far off, my use case is an Amazon Fire tablet with Fully Kiosk that is blocked from the Internet. Amazon removed the ability to manually set the time and it doesn’t use normal NTP that I can redirect. There are countless threads on how Amazon will not help with this but the time on the tablet doesn’t matter to me if I can get the card to use the server time.

Assuming the tablet is in a fixed TZ and the time is stable ‘off’ then why not apply an offset to the series ? maybe with a to-UTC reformat first?

I thought about that but it’s not stable. I can connect it briefly to the Internet and it resets the time correctly, then I can move it back, but the time will slowly drift. And if the tablet resets, it goes back to the last time it was connected to the Amazon server. It currently thinks the time is 2 days and 3 hours ago :roll_eyes: