Plotly interactive Graph Card

For some reason this is not solving my problem. I am just new, and want to stack humidity and temperature.

type: custom:plotly-graph
entities:
  - entity: sensor.atc1_temperature
  - entity: sensor.atc2_temperature
  - entity: sensor.atc1_humidity
  - entity: sensor.atc2_humidity
refresh_interval: 10
hours_to_show: 6
layout:
  height: 400

makes this:
2023-02-23 21.42.26 homeassistant.local 4a144c3d34b3

If I add your lines, and try it like this:

type: custom:plotly-graph
entities:
  - entity: sensor.atc1_temperature
  - entity: sensor.atc2_temperature
  - entity: sensor.atc1_humidity
  - entity: sensor.atc2_humidity
refresh_interval: 10
hours_to_show: 6
layout:
  height: 400
defaults:
  yaxes:
    side: left
    overlaying: 'y'
    visible: true

Gives:
2023-02-23 21.44.29 homeassistant.local fc64d14ee276

It looks pretty ugly.

Is there another good way to do two separate graphs on top of each other? I don’t want to use HA grids, because if I scroll to the left or right, I want both graphs to change there x-axis simultanously.

Thank you in advance.

There is, but it is a bit more involved:

type: custom:plotly-graph
entities:
  - entity: sensor.atc1_temperature
    yaxis: y1
  - entity: sensor.atc2_temperature
    yaxis: y1
  - entity: sensor.atc1_humidity
    yaxis: y2
  - entity: sensor.atc2_humidity
    yaxis: y2
layout:
  dragmode: pan
  margin:
    t: 30
    l: 45
    r: 40
    b: 50
  showlegend: false
  height: 650
  grid:
    rows: 2
    columns: 1
    roworder: top to bottom
  annotations: null
  yaxis:
    title:
      text: Temperature.
  yaxis2:
    title:
      text: Humidity.
defaults:
  entity:
    show_value: true
  yaxes:
    fixedrange: false
    autorange: true
    side: left
    overlaying: 'y'
    visible: true
    showgrid: true
title: Grid
hours_to_show: 1d
color_scheme: 2
1 Like

Thank you very much for the quick answer!!!

Adding the following to my last code above does already the job:

  grid:
    rows: 2
    columns: 1
    roworder: top to bottom

Resulting in:
2023-02-25 15.38.27 homeassistant.local 6766a21b8ab3

Thank you, for the other suggestions for improvement. It looks great!
For me the graph for your code looks like this:

1 Like

Looks good! This card is not the easiest one, but it is really flexible by design.
I’m considering adding presets, including an option to share them via gist url

1 Like

More questions:

  1. Why is it neccesary to use yaxis: y1 or yaxis: y2 for each entity? For me it works also, if I don’t use it.
  2. And if I use yaxis: y1 and yaxis: y2, without a title for yaxis: and yaxis2:, the default °C for the upper graph is missing. Why is that?
  3. Can I disable the legend only of the humidity in a way, that if I disable a the temperature graph by clicking it, it will also hide the coresponding humidity-graph? The problem I have right now is, that I have two times the label of ATC1 and ATC2, because one is the temperature, and one the humidity. And it is not necessary. See screenshot below.
  4. How can I make the color of ATC1_temperature the same as ATC1_humidity? This would be necessary for the way i mentioned it under “3.”.

This example is exactly what you want Grouping graces & split temperature and humidity plots · Discussion #31 · dbuezas/lovelace-plotly-graph-card · GitHub
Important are legendgroup and color_scheme

You’ll have to massage it a bit because of the deprecation of no_default_layout, but that part you already covered.

The yaxis: y1 is not necessary if you don’t put raw_plotly_config, because the card will assign one yaxis to each unit_of_measurement

1 Like

Oh wow! I Love it. Thank you very very much :slight_smile:

How can I get a lineplot with marks? I am trying this now for a long time, and can’t get a nice solution. The only solution I’ve got is, to plot the graph twice. One time with line: and one time with mode: markers.

Like this:

  - entity: sensor.atc1_temperature
    yaxis: y1
    legendgroup: 1
    line:
      shape: hv
  - entity: sensor.atc1_temperature
    yaxis: y1
    legendgroup: 1
    mode: markers
    showlegend: false

It leads to my wanted result, but I have the feeling, that the performance now is lacking in my graph with 8 entities (so 16 graphs, if I add the marks every time as extra graph).

Is there a smarter solution than mine?

mode: lines+markers should do the trick.
Remember that you can find answers for a lot of plotly questions by googling “how do I xyz in plotly?”

1 Like

I just wanted to add an example of a solution I have for a problem: when you show a graph which takes data from the long term statistics, the last value is not always up-to-date (sometimes it takes a while before it is updated). To work around this, I used this:
map_y_numbers: '(i<ys.length-1) ? y : hass.states["sensor.daily_gas"].state'

Full code:

type: custom:plotly-graph
title: Gas daily
entities:
  - entity: sensor.daily_gas
    statistic: state
    period: day
    type: bar
    texttemplate: '%{y}'
    filters:
      - filter: i>0
      - map_y_numbers: '(i<ys.length-1) ? y : hass.states["sensor.daily_gas"].state'
    marker:
      color: '148E99'
time_offset: 12h
hours_to_show: 240
defaults:
  yaxes:
    fixedrange: true
layout:
  height: 250

image

4 Likes

Great card, i use it mainly for temperature sensors and such, however i added the Garmin integration together with a couple of sensors that i’m trying to make graphs for.
For example, how would i make a graph for the steps counter? What i’m looking to get out is total steps each day in a nice bar graph.

This is what i got so far but it´s acting kind of funny with panning and zooming.

type: custom:plotly-graph
entities:
  - entity: sensor.total_steps
    statistic: state
    period: auto
    type: bar
    texttemplate: '%{y}'
hours_to_show: 168
defaults:
  entity:
    line:
      width: 2
  yaxes:
    fixedrange: true
refresh_interval: 60
fn: |
  $fn({getFromConfig, vars})=> {
    const range = getFromConfig("visible_range");
    const width = range[1] - range[0];
    vars.scroll = (label, p) => ({
      args: [
        {
          layout: {
            "xaxis.range": [range[0] + width*p, range[1] + width*p],
          }
        }, {
          transition: {
            duration: 150,
          }
        }
      ],
      label,
      method: "animate",
    })
    vars.zoom = (label, h) => ({
      args: [
        {
          layout: {
            "xaxis.range": [Date.now()-1000*60*60*h, Date.now()],
          }
        }
      ],
      label,
      method: "animate",
    })
  }
layout:
  updatemenus:
    - buttons:
        - $fn({vars}) => vars.scroll( '<', -.5)
        - $fn({vars}) => vars.scroll( '>', .5)
      direction: right
      active: -1
      pad:
        r: 10
        t: 10
      type: buttons
      x: 1
      xanchor: right
      'y': 1.3
      yanchor: top
    - buttons:
        - $fn({vars}) => vars.zoom( '1d', 24)
        - $fn({vars}) => vars.zoom( '1w', 24*7)
        - $fn({vars}) => vars.zoom( '1m', 24*30)
      direction: right
      active: -1
      pad:
        r: 10
        t: 10
      type: buttons
      x: 0
      xanchor: left
      'y': 1.3
      yanchor: top

I would like to use

period: day

but it gives me wrong values when i pan/zoom and i don´t think that “auto” is really made for this type application?

IMO this is too complex for the forum and I’ll forget. I suggest you make a Q&A post in the Discussions section of the github repository instead, somebody else may also join the analysis :slight_smile:

1 Like

Short question, how to have a fix start time and a fix end time in plotly? So I mean, I want to show data current day from 5:00 - 21:00.

hours_to_show: 16h
time_offset: 5h

Will not work since it shows me last 16h with time offset 5h.

hours_to_show: current_day
time_offset: 5h

Will not work since it shows me 5:00 until end of day.

Thanx for a hint !

You’ll have to implement that yourself.
Something like this:

type: custom:plotly-graph
hours_to_show: |
  $ex {
    vars.hours = [5, 21];
    return vars.hours[1] - vars.hours[0];
  }
time_offset: |
  $ex  new Date().setHours(vars.hours[1],0,0) - Date.now() + 'ms'
entities:
  - entity: sensor.wintergarten_thermometer_temperature

more here: Show the current day from midnight to midnight · dbuezas/lovelace-plotly-graph-card · Discussion #220 · GitHub

Another option is to set the layout:xaxis:range with an expression, but then it will snap back if you scroll. I think the code above should have all you need :slight_smile:

Ahh yes, cool, your first reply is great! but I decided for second option layout:xaxis:range which works great and is much easier when I have ‘fixedrange: true’ for yaxes and xaxis.

range: $ex [new Date().setHours(5,0,0,0), new Date().setHours(21,0,0,0)]

Thanx a lot for the idea!

1 Like

I might be little lost here.
A few days ago I decided to migrate from apex chart, because they caused extreme front- (and) backend lags.

I am happy so far, but there is one or two things I am really struggling with.
1, How do you make the current entity value to show inside of the legend and not on the end of the line as on some dual data graphs this is not viable.
2, Is there a way so that the yaxis does move if the data escape its limits and adapts to the data.

You can see both problems in the picture.

type: custom:plotly-graph
entities:
  - entity: sensor.pokoj_teplota
    yaxis: y1
    line:
      color: '#fff200'
  - entity: sensor.pokoj_vlhkost
    yaxis: y2
    line:
      color: '#00ffb7'
  - entity: sensor.loznice_teplota
    yaxis: y1
    line:
      color: '#ff9d00'
  - entity: sensor.loznice_vlhkost
    yaxis: y2
    line:
      color: '#00c8ff'
defaults:
  entity:
    show_value: true
    line:
      width: 1,5
layout:
  showlegend: true
  dragmode: false
  uirevision: 'true'
  yaxis:
    fixedrange: true
    range:
      - 17
      - 25
  yaxis2:
    fixedrange: true
    range:
      - 0
      - 100
  xaxis:
    fixedrange: true
config:
  tickformat: '%Y%H:%M:%S'
  displayModeBar: false
hours_to_show: 24
refresh_interval: 10

obrazek

Happy to hear you are enjoying it :slight_smile:

To have the values inside the plot you can use the global time_offset: 6h. This will leave space to the right inside the plot.

To have the plot refresh the y axes, remove their ranges and uirevision: ‘true’

What I was trying to achieve is that I want to have the range from 15 °C to 25 °C, but if the temperature goes below 15 °C or above 25 °C it will autoadjust the range to the maximal value.

For example the temperature will be 15.03 °C, then I want the range to auto adjust to: from 15.03 °C to 25 °C.
If it the temperature is for example 26.54 °C, then I want the range to auto adjust to: from 17 °C to 26.54 °C.

Is there an easy way to achieve this?

So you want it to be 10 degrees from min to max, where min is the smallest between observed and 15 and the max is the biggest between observed and 25, right?
I think you need this: