Plotly interactive Graph Card

yes, see here: GitHub - dbuezas/lovelace-plotly-graph-card: Highly customisable Lovelace card to plot interactive graphs. Brings scrolling, zooming, and much more!

Iā€™m missing somethingā€¦

I have

title: host statistics
entities:
  - entity: sensor.processor_temperature
    name: Processor temperature
    yaxis: y1
  - entity: sensor.memory_use
    name: Memory use
    yaxis: y2
  - entity: sensor.memory_free
    name: Memory free
    yaxis: y3
hours_to_show: 24
refresh_interval: 10
defaults:
  yaxes:
    side: left
    overlaying: 'y'
    visible: true

and the result is:

But I want my old graph back :smiley:

that was with the code:

type: custom:plotly-graph
entities:
  - entity: sensor.processor_use
    yaxis: y1
  - entity: sensor.memory_use
    yaxis: y2
  - entity: sensor.processor_temperature
    yaxis: y3
no_default_layout: true
default_trace:
  line:
    width: 2
layout:
  dragmode: pan
  annotations:
    - xref: paper
      yref: paper
      'y': 1
      text: Processor Util %
      showarrow: false
    - xref: paper
      yref: paper
      'y': 0.6
      text: Memory Use Mb
      showarrow: false
    - xref: paper
      yref: paper
      'y': 0.2
      text: Processor Temp C
      showarrow: false
  margin:
    t: 30
    l: 45
    r: 30
    b: 50
  showlegend: false
  height: 300
  yaxis:
    fixedrange: true
  yaxis2:
    fixedrange: true
  yaxis3:
    fixedrange: true
  grid:
    rows: 3
    columns: 1
    pattern: coupled
    roworder: top to bottom
hours_to_show: 72
refresh_interval: 10
title: HA Server Stats

Can you tell me where Iā€™m going the wrong way?

Keep your old yaml, just add the default yaxis and remove no_default_layout: true

The only strange thing isā€¦ the first graph has lines, the other two donā€™tā€¦

If you think itā€™s a bug, please post the actual yaml and screenshot as a bug report in GitHub and Iā€™ll take a look in the coming days :slight_smile:

Oh, now I noticed this in mine too. This is missing in the default yaxes:


showgrid: true

Iā€™ll add it to the readme too.

1 Like

EDIT: My bad, i had a wrong entity selected.
Works like a charm! Thanks!

Glad to hear.
Iā€™m still looking for some usage (an excuse basically) for the surface3d plot. Maybe the one could store the extended hourly forecast via a template entity and then have:

  • time when forecast was stored in the X axis
  • forecast length in the Y axis
  • forecasted temperature in the Z axis.

It would be interesting to finally get a visual sense of how (in) accurate forecasts are.

image
Anybody missing a filter or some simple feature? Weā€™re 1 out of 3 digit closed issues :slight_smile:

2 Likes

Maybe you can help me with this: I have a graph showing the actual usage of my airconditioning

The only thing which is missing is the value of the current hour (since this is not in the statistics yet). How can I add this value?

Current code:

type: custom:plotly-graph
entities:
  - entity: sensor.airco_beneden_hourly
    statistic: state
    period: hour
    type: bar
    name: Hourly
    texttemplate: '%{y}'
    filters:
      - filter: i>0
    yaxis: y1
  - entity: sensor.airco_beneden_hourly
    name: $ex "Current hour:" + hass.states["sensor.airco_beneden_hourly"].state
    x: $ex [Date.now(), Date.now()]
    filters:
      - map_y_numbers: 0
hours_to_show: 12
defaults:
  yaxes:
    fixedrange: true

I currently show the current value with a workaround, but it would be nice to see it as an extra bar in the graph.

Can someone tell me whatā€™s wrong in this old code for it to work on V3.0.0 ?
Every axes are stacked on the first graph, and there are no line displayed anymore.

type: custom:plotly-graph
entities:
  - entity: climate.modulating_thermostat::current_temperature
    name: Temperature
    legendgroup: climate.modulating_thermostat::current_temperature
    yaxis: "y"
    line:
      color: '#1f77b4'
    texttemplate: <b> %{y}</b> Ā°C
    show_value: true
    fill: tozeroy
    fillcolor: rgba(131, 238, 255 , 0.05)
  - entity: climate.modulating_thermostat::temperature
    legendgroup: climate.modulating_thermostat::temperature
    name: Setpoint
    yaxis: "y"
    line:
      color: '#9467bd'
    fill: tozeroy
    fillcolor: rgba(177, 156, 217 , 0.05)
  - entity: weather.buienradar::temperature
    legendgroup: weather.buienradar::temperature
    name: outside
    yaxis: "y"
    line:
      color: '#DD4444'
    show_value: true
    texttemplate: <b> %{y}</b> Ā°C
    fill: tozeroy
    fillcolor: rgba(255, 156, 217 , 0.05)
  - entity: climate.modulating_thermostat::hvac_action
    legendgroup: climate.modulating_thermostat::hvac_action
    name: Modulation
    yaxis: y4
    fill: tozeroy
    fillcolor: rgba(255, 127, 14, 0.15)
    line:
      color: '#ff7f0e'
      width: 0
    filters:
      '-fn': |-
        (ys) => ys.map(y => {
               if (y == 'heating') return 'heating';
               else return 'idle'
            })
  - entity: climate.netatmo_valve_1::current_temperature
    legendgroup: climate.modulating_thermostat::current_temperature
    name: Temperature
    showlegend: false
    yaxis: y2
    line:
      color: '#1f77b4'
    texttemplate: <b> %{y}</b> Ā°C
    show_value: true
    fill: tozeroy
    fillcolor: rgba(131, 238, 255 , 0.05)
  - entity: climate.netatmo_valve_1::temperature
    legendgroup: climate.modulating_thermostat::temperature
    name: Setpoint
    showlegend: false
    yaxis: y2
    line:
      color: '#9467bd'
    fill: tozeroy
    fillcolor: rgba(177, 156, 217 , 0.05)
  - entity: climate.netatmo_valve_1::hvac_action
    legendgroup: climate.modulating_thermostat::hvac_action
    name: Modulation
    showlegend: false
    yaxis: y5
    fill: tozeroy
    fillcolor: rgba(255, 127, 14, 0.15)
    line:
      color: '#ff7f0e'
      width: 0

  - entity: climate.netatmo_valve_2::current_temperature
    legendgroup: climate.modulating_thermostat::current_temperature
    name: Temperature
    showlegend: false
    yaxis: y3
    line:
      color: '#1f77b4'
    texttemplate: <b> %{y}</b> Ā°C
    show_value: true
    fill: tozeroy
    fillcolor: rgba(131, 238, 255 , 0.05)
  - entity: climate.netatmo_valve_2::temperature
    legendgroup: climate.modulating_thermostat::temperature
    name: Setpoint
    showlegend: false
    yaxis: y3
    line:
      color: '#9467bd'
    fill: tozeroy
    fillcolor: rgba(177, 156, 217 , 0.05)
  - entity: climate.netatmo_valve_2::hvac_action
    legendgroup: climate.modulating_thermostat::hvac_action
    name: Modulation
    showlegend: false
    yaxis: y6
    fill: tozeroy
    fillcolor: rgba(255, 127, 14, 0.15)
    line:
      color: '#ff7f0e'
      width: 0
defaults:
  type: line
  entity:
    line:
      width: 3
hours_to_show: 36
layout:
  title:
    text: Temperatures
    x: 0.12
    'y': 0.9
  dragmode: pan
  xaxis:
    domaine:
      - 0
      - 1
    rangeselector:
      'y': 1.05
      x: 0
      buttons:
        - count: 6
          step: hour
        - count: 1
          step: day
        - count: 7
          step: day
  yaxis:
    side: left
    title:
      text: Ā°C
    visible: true
    min_value: 10
  yaxis2:
    side: left
    title:
      text: Ā°C
    visible: true
  yaxis3:
    side: left
    title:
      text: Ā°C
    visible: true
  yaxis4:
    overlaying: 'y'
    side: right
    fixedrange: true
    categoryorder: category descending
    visible: false
  yaxis5:
    overlaying: y2
    side: right
    fixedrange: true
    categoryorder: category descending
    visible: false
  yaxis6:
    overlaying: y3
    side: right
    fixedrange: true
    categoryorder: category descending
    visible: false
  annotations:
    - xref: paper
      yref: paper
      'y': 1.04
      text: Living
      showarrow: false
    - xref: paper
      yref: paper
      'y': 0.69
      text: Salle de bain
      showarrow: false
    - xref: paper
      yref: paper
      'y': 0.31
      text: Chambre
      showarrow: false
  margin:
    t: 20
    l: 60
    r: 80
    b: 60
  showlegend: true
  legend:
    'y': 1.25
  height: 700
  grid:
    rows: 3
    columns: 1
    pattern: coupled
    roworder: top to bottom

you can add the current state to the data with a fn filter, like this:

filters:
  - xxx
  - fn: ({xs, ys, hass}) => ({xs: [...xs, new Date()], ys: [...ys, hass.states["sensor.airco_beneden_hourly"].state]})

you could use a $fn or $ex too, but this is cleaner IMO.

It could be that the added bar forces all the others to be thinner (because plotly determines the width of bars as the minimum x axis distance between two consecutive datapoints). To fix that, you can use new Date(+xs[xs.length-1] + 1000*60*60) instead of new Date(). Then you can use a global time_offset: 1h to show a bit into the future, or hours_to_show: current_day.
There are almost too many options in the latest versions of the card :laughing:

See the readme section on deprecations, and make sure to update to the latest version, it also has a couple of fixes, not only new features.

I managed to fix the code, for those interested :

type: custom:plotly-graph
entities:
  - entity: climate.modulating_thermostat::current_temperature
    name: Temperature
    legendgroup: climate.modulating_thermostat::current_temperature
    yaxis: 'y'
    line:
      color: '#1f77b4'
    texttemplate: <b> %{y}</b> Ā°C
    show_value: true
    fill: tozeroy
    fillcolor: rgba(131, 238, 255 , 0.05)
  - entity: climate.modulating_thermostat::temperature
    legendgroup: climate.modulating_thermostat::temperature
    name: Setpoint
    yaxis: 'y'
    line:
      color: '#9467bd'
    fill: tozeroy
    fillcolor: rgba(177, 156, 217 , 0.05)
  - entity: weather.buienradar::temperature
    legendgroup: weather.buienradar::temperature
    name: outside
    yaxis: 'y'
    line:
      color: '#DD4444'
    show_value: true
    texttemplate: <b> %{y}</b> Ā°C
    fill: tozeroy
    fillcolor: rgba(255, 156, 217 , 0.05)
  - entity: climate.modulating_thermostat::hvac_action
    legendgroup: climate.modulating_thermostat::hvac_action
    name: Modulation
    yaxis: y4
    fill: tozeroy
    fillcolor: rgba(255, 127, 14, 0.15)
    line:
      color: '#ff7f0e'
      width: 0
    filters:
      - map_y: >-
          ys.map(y => { if (y == 'heating') return 'heating'; else return 'idle'
          })
  - entity: climate.netatmo_valve_1::current_temperature
    legendgroup: climate.modulating_thermostat::current_temperature
    name: Temperature
    showlegend: false
    yaxis: y2
    line:
      color: '#1f77b4'
    texttemplate: <b> %{y}</b> Ā°C
    show_value: true
    fill: tozeroy
    fillcolor: rgba(131, 238, 255 , 0.05)
  - entity: climate.netatmo_valve_1::temperature
    legendgroup: climate.modulating_thermostat::temperature
    name: Setpoint
    showlegend: false
    yaxis: y2
    line:
      color: '#9467bd'
    fill: tozeroy
    fillcolor: rgba(177, 156, 217 , 0.05)
  - entity: climate.netatmo_valve_1::hvac_action
    legendgroup: climate.modulating_thermostat::hvac_action
    name: Modulation
    showlegend: false
    yaxis: y5
    fill: tozeroy
    fillcolor: rgba(255, 127, 14, 0.15)
    line:
      color: '#ff7f0e'
      width: 0
    filters:
      - map_y: >-
          ys.map(y => { if (y == 'heating') return 'heating'; else return 'idle'
          })
  - entity: climate.netatmo_valve_2::current_temperature
    legendgroup: climate.modulating_thermostat::current_temperature
    name: Temperature
    showlegend: false
    yaxis: y3
    line:
      color: '#1f77b4'
    texttemplate: <b> %{y}</b> Ā°C
    show_value: true
    fill: tozeroy
    fillcolor: rgba(131, 238, 255 , 0.05)
  - entity: climate.netatmo_valve_2::temperature
    legendgroup: climate.modulating_thermostat::temperature
    name: Setpoint
    showlegend: false
    yaxis: y3
    line:
      color: '#9467bd'
    fill: tozeroy
    fillcolor: rgba(177, 156, 217 , 0.05)
  - entity: climate.netatmo_valve_2::hvac_action
    legendgroup: climate.modulating_thermostat::hvac_action
    name: Modulation
    showlegend: false
    yaxis: y6
    fill: tozeroy
    fillcolor: rgba(255, 127, 14, 0.15)
    line:
      color: '#ff7f0e'
      width: 0
    filters:
      - map_y: >-
          ys.map(y => { if (y == 'heating') return 'heating'; else return 'idle'
          })
defaults:
  type: line
  entity:
    line:
      width: 3
  yaxes:
    side: left
    overlaying: 'y'
    visible: true
hours_to_show: 36
layout:
  title:
    text: Temperatures
    x: 0.12
    'y': 0.9
  dragmode: pan
  xaxis:
    domaine:
      - 0
      - 1
    rangeselector:
      'y': 1.05
      x: 0
      buttons:
        - count: 6
          step: hour
        - count: 1
          step: day
        - count: 7
          step: day
  yaxis:
    overlaying: false
    side: left
    title:
      text: Ā°C
    visible: true
    min_value: 10
  yaxis2:
    overlaying: false
    side: left
    title:
      text: Ā°C
    visible: true
  yaxis3:
    overlaying: false
    side: left
    title:
      text: Ā°C
    visible: true
  yaxis4:
    overlaying: 'y'
    side: right
    fixedrange: true
    categoryorder: category descending
    visible: false
  yaxis5:
    overlaying: y2
    side: right
    fixedrange: true
    categoryorder: category descending
    visible: false
  yaxis6:
    overlaying: y3
    side: right
    fixedrange: true
    categoryorder: category descending
    visible: false
  annotations:
    - xref: paper
      yref: paper
      'y': 1.04
      text: Living
      showarrow: false
    - xref: paper
      yref: paper
      'y': 0.69
      text: Salle de bain
      showarrow: false
    - xref: paper
      yref: paper
      'y': 0.31
      text: Chambre
      showarrow: false
  margin:
    t: 20
    l: 60
    r: 80
    b: 60
  showlegend: true
  legend:
    'y': 1.25
  height: 700
  grid:
    rows: 3
    columns: 1
    pattern: coupled
    roworder: top to bottom

Glad to hear! :tada:
Watchout, map_y is called for each datapoint, I think you confused it with fn. You can fix it like this:

 - map_y: (y == 'heating') ? 'heating' : 'idle'

Hi Plotly central. Small issue. Did the HA Plotly updates recently and now got this. Any ideas how to overcome the error please?

on github it says:

Breaking Changes

  • no_default_layout: replaced with more general raw_plotly_config

besides some others, so Iā€™d say work youā€™re lucky since you were only affected by 1 of the complete number or changes. So simply replace that line as mentioned by the error.

Hereā€™s what to fo:

Iā€™d say youā€™re lucky since you were only affected by 1 of the complete number or changes.

I feel you, I didnā€™t take the breaking changes lightly myself, but I needed to do some cleanup to manage the
code complexity. I did my best making the error messages intuitive and documenting how to change the yaml, but breaking changes always suck. On the plus side, we now have universal functions, which unlock a lot of cool tricks :slight_smile:. And a lot of bug fixes as result of the code rewrite

breaking changes ā€¦ mostly do make sense from the authors perspective.
The drawback is:
Poeple stumble across dead clever code snippets from the past flagged ā€œsolutionā€ while if adopting them they fail straight due to the breaking changes.

And no I canā€™t think of something clever yet. Itā€™s likely the community software which needs another burst, something such as the chatbotalike popups allowing authors to define some rules such as
IF CONTAINS plotly AND CODESNIPPET INCLUDES no_default_layout FIRE A NOTIFICATION POPUP telling the user that they do watch outdated code which needs some adjustments. :slight_smile: