Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

header.show_states does not display current value when using data_generator #840

Open
4 tasks done
RichardPoes opened this issue Jan 3, 2025 · 6 comments
Open
4 tasks done
Labels
bug Something isn't working

Comments

@RichardPoes
Copy link

Checklist

  • I updated the card to the latest version available
  • I cleared the cache of my browser
  • I verified that I'm really running the lastest version in my browser console
  • I checked if there is another issue opened with the same problem

Describe the bug
The value show_states does not show the current state of a sensor when using the data_generator.
Instead. it uses the last value in the list provided.

Version of the card
Version: v2.1.2

To Reproduce
This is the configuration I used:

type: custom:apexcharts-card
graph_span: 24h
span:
  start: day
update_interval: 5min
show:
  last_updated: true
now:
  show: true
  label: Nu
header:
  show: true
  title: Stroomprijzen vandaag
  colorize_states: true
  show_states: true
  standard_format: false
series:
  - entity: sensor.electricity_price_0_days_ahead
    type: column
    offset: "-30m"
    float_precision: 4
    data_generator: >
      const now = new Date(); 

      const startOfDay = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 0, 0, 0, 0); 
      const pricePerHour = [];

      for(let i = 0; i < 24; i++) {
        pricePerHour.push([startOfDay.getTime() + i * 1000 * 60 * 60, entity.attributes[`Hour ${i}`]])
      }

      return pricePerHour;

Screenshots
image
This screenshot was taken around 12:30, but we can see that the price in the header does not reflect the current price.
image
In this image we can see that the price does equal the last value in the list.

Expected behavior
I expect the header value to be the current value of the sensor or the value closest to now.

Desktop (please complete the following information):
Irrelevant but

  • Browser Firefox
  • Version 133.0.3

Additional context
For now, the issue can be fixed by making sure the last entry in the list to be the value you want to be displayed in the state header.
I can add this to the README as a quick and dirty fix.
For instance, I fixed it by adding:

const priceNow = pricePerHour[now.getHours()];
pricePerHour[now.getHours()] = pricePerHour[23]; 
pricePerHour[23] = priceNow;
@RichardPoes RichardPoes added the bug Something isn't working label Jan 3, 2025
@yutani42
Copy link

yutani42 commented Jan 8, 2025

I encountered the same bug but sadly above workaround doesn't fix it for me.. (tested it below with the hour of my testing).

{B3C243AF-0ED9-4AAA-BDEC-11EDB0594CCD}
type: custom:apexcharts-card
header:
  title: Strompreise
  show: true
  show_states: true
graph_span: 25h
span:
  start: day
  offset: +.0h
now:
  show: true
  label: Now
color_list:
  - var(--primary-color)
series:
  - entity: number.fixed_energy_prices
    yaxis_id: prices
    float_precision: 2
    type: column
    curve: smooth
    extend_to: false
    data_generator: |      
      const prices = [];

      for(let i = 0; i < 6; i++) {
        prices.push([moment().startOf('day').add(i + 0.5, 'hours'), 19.04]);
      }

      for(let i = 6; i < 24; i++) {
        prices.push([moment().startOf('day').add(i + 0.5, 'hours'), 32.07]);
      }

      prices.push([moment().startOf('day').add(24 + 0.5, 'hours'), 19.04]);      

      const priceNow = prices[13];
      prices[13] = prices[23];   
      prices[23] = priceNow;

      return prices;
    color_threshold:
      - value: 15.2
        color: green
      - value: 20.25
        color: "#79B92C"
      - value: 25.3
        color: "#C4D81D"
      - value: 30.35
        color: "#F3DC0C"
      - value: 33.4
        color: red
      - value: 40.5
        color: purple
experimental:
  color_threshold: true
yaxis:
  - id: prices
    decimals: 0
    min: 18
    max: 34
    apex_config:
      title:
        text: cent/kWh
      tickAmount: 4
apex_config:
  legend:
    show: false
  tooltip:
    x:
      show: true
      format: HH:00 - HH:59
all_series_config:
  stroke_width: -4

fixed_energy_prices is a number-template sensor with a simple schema:

{% if now().hour < 6 %}
  {{ 19.04 }}
{% else %}
  {{ 32.07 }}
{% endif %}

EDIT: I'm dumb, it didn't work b/c my last value is not at 23h. Workaround is fine!

@RichardPoes
Copy link
Author

So the workaround worked for you too? :)

@INPoppoRTUNE
Copy link

Same issue:

Image

For instance, I fixed it by adding:


const priceNow = pricePerHour[now.getHours()];
pricePerHour[now.getHours()] = pricePerHour[23]; 
pricePerHour[23] = priceNow;

The workaround seems to work (the "Oggi" value in the second chart's header value return the correct value), but it messes up the line chart.

type: custom:apexcharts-card
graph_span: 1d
span:
  start: day
update_interval: 10min
now:
  show: true
  label: Adesso
  color: "#ffbc15"
header:
  show: true
  title: Costo elettricità
  show_states: true
  colorize_states: true
  title_actions:
    tap_action:
      action: navigate
      navigation_path: energy
cache: true
apex_config:
  legend:
    show: true
  grid:
    show: false
  chart:
    foreColor: "#999999"
  dataLabels:
    enabled: true
    style:
      fontSize: 10px
    background:
      opacity: 0.7
  stroke:
    curve: stepline
show:
  last_updated: true
experimental:
  color_threshold: true
all_series_config:
  unit: €/kWh
  header_actions:
    tap_action:
      action: navigate
      navigation_path: energy
  show:
    legend_value: false
    extremas: true
yaxis:
  - decimals: 3
series:
  - entity: sensor.pun_prezzo_zonale
    data_generator: >
      const hourlyValues = [];
      const currentDate = new Date();
      currentDate.setHours(0, 0, 0, 0);

      for (let hour = 0; hour < 24; hour++) {
        const hourStr = String(hour).padStart(2, '0');
        const value = entity.attributes[`oggi_h_${hourStr}`];

        if (value !== undefined) {
          const time = new Date(currentDate); 
          time.setHours(hour, 0, 0, 0);
          
          hourlyValues.push([time.getTime(), value]); 
        }
      }
      const priceNow = hourlyValues[currentDate.getHours()];
      hourlyValues[currentDate.getHours()] = hourlyValues[23]; 
      hourlyValues[23] = priceNow;

      return hourlyValues;
    name: Oggi
    type: line
    color: "#f44336"
    unit: €/kWh
    stroke_width: 3
    float_precision: 5
  - entity: sensor.pun_prezzo_zonale
    data_generator: >
      const hourlyValues = [];
      const currentDate = new Date();
      current date and time currentDate.setHours(0, 0, 0, 0);

      for (let hour = 0; hour < 24; hour++) {
        const hourStr = String(hour).padStart(2, '0');
        const value = entity.attributes[`domani_h_${hourStr}`];

        if (value !== undefined) {
          const time = new Date(currentDate); 
          time.setHours(hour, 0, 0, 0);
          
          hourlyValues.push([time.getTime(), value]);
        }
      }

      return hourlyValues;
    name: Domani
    type: line
    color: "#999999"
    unit: €/kWh
    stroke_width: 1
    stroke_dash: 5
    float_precision: 5

@INPoppoRTUNE
Copy link

I ended up stylizing it with card-mod just to overwrite those values:

Image

Here's my final snippet if anyone is interested:

type: custom:apexcharts-card
graph_span: 1d
span:
  start: day
update_interval: 10min
now:
  show: true
  label: Adesso
  color: "#ffbc15"
header:
  show: true
  title: Costo elettricità
  show_states: true
  colorize_states: true
  title_actions:
    tap_action:
      action: navigate
      navigation_path: energy
cache: true
apex_config:
  legend:
    show: true
  grid:
    show: false
  chart:
    foreColor: "#999999"
  dataLabels:
    enabled: true
    style:
      fontSize: 10px
    background:
      opacity: 0.7
  stroke:
    curve: stepline
show:
  last_updated: true
experimental:
  color_threshold: true
all_series_config:
  unit: €/kWh
  header_actions:
    tap_action:
      action: navigate
      navigation_path: energy
  show:
    legend_value: false
    extremas: true
yaxis:
  - decimals: 3
series:
  - entity: sensor.pun_prezzo_zonale
    data_generator: >
      const hourlyValues = []; const currentDate = new Date();  // Get the
      current date and time currentDate.setHours(0, 0, 0, 0);  // Set the time
      to midnight (start of the day)

      for (let hour = 0; hour < 24; hour++) {
        const hourStr = String(hour).padStart(2, '0');
        const value = entity.attributes[`oggi_h_${hourStr}`];

        if (value !== undefined) {
          const time = new Date(currentDate);  // Copy of the midnight date
          time.setHours(hour, 0, 0, 0); // Set hours, minutes, seconds, and milliseconds
          
          hourlyValues.push([time.getTime(), value]);  // Push timestamp and value
        }
      }

      return hourlyValues;
    name: Oggi
    type: line
    color: "#f44336"
    unit: €/kWh
    stroke_width: 3
    float_precision: 5
  - entity: sensor.pun_prezzo_zonale
    data_generator: >
      const hourlyValues = []; const currentDate = new Date();  // Get the
      current date and time currentDate.setHours(0, 0, 0, 0);  // Set the time
      to midnight (start of the day)

      for (let hour = 0; hour < 24; hour++) {
        const hourStr = String(hour).padStart(2, '0');
        const value = entity.attributes[`domani_h_${hourStr}`];

        if (value !== undefined) {
          const time = new Date(currentDate);  // Copy of the midnight date
          time.setHours(hour, 0, 0, 0); // Set hours, minutes, seconds, and milliseconds
          
          hourlyValues.push([time.getTime(), value]);  // Push timestamp and value
        }
      }

      return hourlyValues;
    name: Domani
    type: line
    color: "#999999"
    unit: €/kWh
    stroke_width: 1
    stroke_dash: 5
    float_precision: 5
card_mod:
  style: >
    #header__states > div:nth-child(1) > div:nth-child(1) >
    span:nth-child(1)::after { content: "{{ '%.5f' |
    format(states('sensor.pun_prezzo_zonale') | float) }}";
      visibility: visible;
      display: block;
      text-align: left;
      position: absolute;
      left: 0;
      top: 0px;
    }

    #header__states > div:nth-child(1) > div:nth-child(1) > span:nth-child(1) {
      visibility: hidden;
      display: block;
    }

    #header__states > div:nth-child(2) > div:nth-child(1) >
    span:nth-child(1)::after { content: "{{ '%.5f' |
    format(state_attr('sensor.pun_prezzo_zonale', 'domani_h_' ~
    now().strftime('%H')) | float) }}";
      visibility: visible;
      display: block;
      text-align: left;
      position: absolute;
      left: -45px;
      top: 0px;
    }

    #header__states > div:nth-child(2) > div:nth-child(1) > span:nth-child(1) {
      visibility: hidden;
      display: block;
    }

    #header__states > div:nth-child(1) > div:nth-child(1) > span:nth-child(2) {
      position: absolute;
      right: -45px;
      top: 3px;  // Align to the same height as the first styled element
    }

    #header__states > div:nth-child(2) > div:nth-child(1) > span:nth-child(2) {
      position: absolute;
      right: 0px;
      top: 3px;  // Align to the same height as the first styled element
    }

    #header__states > div.actions:nth-child(2) > div:nth-child(2) {
      position: absolute;
      right: 98px !important;
      top: px;  // Align to the same height as the first styled element
    }

@GradientMarker
Copy link

GradientMarker commented Feb 9, 2025

Researching the same issue, I came across this comment. Using 'in_header: raw' solved the problem for me without the need of any workaround.

@INPoppoRTUNE
Copy link

INPoppoRTUNE commented Feb 9, 2025

Researching the same issue, I came across this comment. Using 'in_header: raw' solved the problem for me without the need of any workaround.

Doesn't seems to work for me unfortunately:
Image

I'm using data_generator, top one is stylized with card-mod, bottom one uses in_header: raw.

EDIT:
I re-checked the documentation:

  show:
    in_header: before_now

before_now seems to work flawlessly with data_generator, thanks for the tip!

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

4 participants