Making an Accurate Rain Graph, Day, Month, Year (Netamo, SmartMixn and Others.)

I have had Home Assistant for a bit over two years now and there does not seem to be a way to make an accurate (Monthly) rain graph, from the data given from my Netamo Rain Sensor.

I have also found very few posts directly relating, to what you would think being a simple task to create a rain graph in Home Assistant. I may also be a Luddite.

I have put this post together to capture the code I have used for any other Newbies that need a template to start with but would also like any advice you can give to make my graphs more accurate. I have tried utility meters to no avail. The Monthly Data is what I really need help with.

The Netamo Rain Sensor reports the following sensors.

  • Rain Rate (mm/h)
  • Rain Per Hour (mm)
  • Rain Accumulated Per Day (mm) - Resets and Midnight
    9am prefered to align with the weatherman in Australia.

This is a snip of how those sensors look in history stats, during a rainfall event.

SmartMixn Phone and Web App
SmartMixin is an application that provides access to your weather station and 40K+ other stations worldwide. It helps you see and understand weather data.

I have all My Weather Station Data recorded there for over two years now, you can click on the link and see the data.

I have added the Web App as a Web Page Dashboard and gives me access to all my graphs and accurate data.

The Mobile App give you more access to historical comparisons, charts and exporting csv files of your data. I wish they had an open API so I could import that data straight into Home Assistant, or an Integration.

The below image shows 87.7mm for January.

APEX CHARTS Monthly Rain Fall Graph
I am using the Rain Per Hour Sensor. It is close but not quite right because of the uneven shift of data over the month. Using the long term statistics option in this card is key.
The below graph shows 82.3 for January, because of the shift in data, and being on the 12 June Currently (Last 30 days is not in line with the months)

          - type: custom:apexcharts-card
            graph_span: 365d
            header:
              show: true
              title: Monthly Rainfall
              show_states: false
            apex_config:
              fill:
                type: gradient
                gradient:
                  type: vertical
                  shadeIntensity: 0.0
                  opacityFrom: 1
                  opacityTo: 0.5
                  stops: 10
              chart:
                height: 150px
              grid:
                show: false
                borderColor: darkslateblue
                strokeDashArray: 2
              dataLabels:
                background:
                  borderWidth: 0
                  opacity: 0
                  foreColor: white
                offsetY: -10
              plotOptions:
                bar:
                  borderRadius: 0
                  dataLabels:
                    position: top
            span:
              start: month
              offset: '-334.5833333333333d'
            series:
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_last_hour
                color: deepskyblue
                type: column
                group_by:
                  func: sum
                  duration: 30.41666666666667d
                  fill: zero
                statistics:
                  type: state
                  period: hour
                  align: end
                show:
                  name_in_header: false
                  datalabels: true

APEX CHARTS Daily Rain Fall Graph 30 Days
I am using the Rain Accumulated Per Day sensor. Using the MAX function and duration of 1d. when trying to use the same sensor in the above card it does not work properly. Using the long term statistics option in this card is key.
This one seems close to accurate

          - type: custom:apexcharts-card
            graph_span: 30d
            header:
              show: true
              title: Daily Rainfall
              show_states: false
            span:
              end: day
            apex_config:
              fill:
                type: gradient
                gradient:
                  type: vertical
                  shadeIntensity: 0.0
                  opacityFrom: 1
                  opacityTo: 0.5
                  stops: 10
              chart:
                height: 150px
              grid:
                show: false
                borderColor: darkslateblue
                strokeDashArray: 2
              dataLabels:
                background:
                  borderWidth: 0
                  opacity: 0
                  foreColor: white
                offsetY: -10
              plotOptions:
                bar:
                  borderRadius: 0
                  dataLabels:
                    position: top
            series:
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_today
                color: deepskyblue
                type: column
                group_by:
                  func: max
                  duration: 1d
                statistics:
                  type: state
                show:
                  name_in_header: false
                  datalabels: true

MINI GRAPH CARD Last 7 Days Rain
I am using a template, statistics sensor to Accumulate the last 7 Days (10080mins) of Data.
This one seems close to accurate and drives my sprinkler system
image

Sensor:

# Rain Last 7 Days
-platform: template
 sensors:
  - platform: statistics
    name: "Rain last 7 days"
    unique_id: afe4b9f2-d0a6-4c42-86eb-786737f2ea14
    entity_id: sensor.netatmo_devonport_tas_indoor_rain_rain_today
    state_characteristic: sum_differences_nonnegative
    max_age:
      minutes: 10080
    precision: 1
    keep_last_sample: true

Card:

  - type: custom:mini-graph-card
    entities:
      - entity: sensor.rain_last_7_days
        color: lightblue
    name: Rain Last 7 Days
    group_by: date
    show:
      graph: bar
      extrema: false
    hours_to_show: 168
    points_per_hour: 1
    cache: true
    animate: true
    aggregate_func: last

MINI GRAPH CARD Rain Last 24Hrs
Directly reads the Rain Per Hour sensor and gives a good appreciation of the rain fallen in the last 24hrs.
This one seems accurate
image

type: custom:mini-graph-card
entities:
  - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_last_hour
    color: lightblue
name: Rain Last 24hrs
group_by: hour
show:
  graph: bar
  extrema: false
hours_to_show: 24
points_per_hour: 1
cache: true
animate: true
agregate_func: last

RAIN GAUGE CARD Rain Last 24Hrs
Directly reads the Rain Accumulated Per Day sensor and gives a good appreciation of the rain fallen in the last 24hrs.
This one seems accurate

- type: custom:rain-gauge-card
  entity: sensor.netatmo_devonport_tas_indoor_rain_rain_today
  hourly_rate_entity: sensor.netatmo_devonport_tas_indoor_rain_rain_last_hour
  name: Daily Rain
  show_warning: false
  show_error: false

Any advice you can give to make my graphs more accurate would be much appreciated.

2 Likes

UPDATE
I managed to fix the accuracy issues in the APEX CHARTS Rainfall Graphs. They now mirror my data stored on SmartMixn, from the same weather sensors.

APEX CHARTS Monthly Rain Fall Graph (12 Months)

Some Important settings

# For the "Rain This Month" (VISIBLE IN CHART)(Using the Rain Accumulated Per Day sensor)
graph_span: 12month # 12 month graph span
span:
  end: month # Span ends at the end of the month
group_by:
  func: sum # Sum
  duration: 1month # 1 Month Data
  fill: zero
statistics: # Grabs Long Term Statistics
  type: state
  period: day # Grabs 1 day at a time
  align: start
  show:
    name_in_header: true # shows name in header
    datalabels: true # makes data labels visible above bars
    in_chart: true # makes bars visible in chart
    legend_value: false # hides from legend
    extremas: false # hides extremas

# For the "Rain Last 12 Months" (ONLY VISIBLE IN HEADER)(Using the Rain Accumulated Per Day sensor)
  group_by:
    func: sum # Sum
    duration: 12month # 12 month duration
    fill: zero
  statistics: # Long Term Statistics
    type: state
    period: day
    align: end
  show:
    name_in_header: true # Show only Total in Header
    datalabels: false # Do not show data labels above graph
    in_chart: false # Do not show bars in graph
    legend_value: false # Do not show in legend

COMPLETE CODE FOR MONTHLY RAINFALL (12 MONTHS) GRAPH

          - type: custom:apexcharts-card
            graph_span: 12month
            span:
              end: month
              offset: '-0d'
            header:
              show: true
              show_states: true
            apex_config:
              fill:
                type: gradient
                gradient:
                  type: vertical
                  shadeIntensity: 0
                  opacityFrom: 1
                  opacityTo: 0.5
                  stops: 10
              chart:
                height: 150px
              grid:
                show: false
                borderColor: darkslateblue
                strokeDashArray: 2
              dataLabels:
                background:
                  borderWidth: 0
                  opacity: 0
                  foreColor: white
                offsetY: -10
              plotOptions:
                bar:
                  borderRadius: 0
                  dataLabels:
                    position: top
            series:
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_today
                name: Rain This Month
                color: deepskyblue
                type: column
                group_by:
                  func: sum
                  duration: 1month
                  fill: zero
                statistics:
                  type: state
                  period: day
                  align: start
                show:
                  name_in_header: true
                  datalabels: true
                  in_chart: true
                  legend_value: false
                  extremas: false
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_today
                name: Rain Last 12 Months
                color: deepskyblue
                type: column
                group_by:
                  func: sum
                  duration: 12month
                  fill: zero
                statistics:
                  type: state
                  period: day
                  align: end
                show:
                  name_in_header: true
                  datalabels: false
                  in_chart: false
                  legend_value: false

APEX CHARTS Daily Rain Fall Graph (30 Days)

Some Important Settings:

# For the "Rain Today" (VISIBLE IN CHART)(Using the Rain Accumulated Per Day sensor)
graph_span: 30d # 30 days graph span
span:
  end: day # Span ends at the end of the day
group_by:
  func: max # Max
  duration: 1d # 1 Day Data
  fill: zero
statistics: # Grabs Long Term Statistics
  type: state
  period: day # Grabs 1 day at a time
  align: end
  show:
    name_in_header: true # shows name in header
    datalabels: true # makes data labels visible above bars
    in_chart: true # makes bars visible in chart
    legend_value: false # hides from legend
    extremas: false # hides extremas

# For the "Rain Last 30 Days" (ONLY VISIBLE IN HEADER)(Using the Rain Accumulated Per Day sensor)
  group_by:
    func: sum # Sum
    duration: 30d # 30 days duration
    fill: zero
  statistics: # Long Term Statistics
    type: state
    period: day
    align: end # align at end
  show:
    name_in_header: true # Show only Total in Header
    datalabels: false # Do not show data labels above graph
    in_chart: false # Do not show bars in graph
    legend_value: false # Do not show in legend

COMPLETE CODE FOR DAILY RAINFALL (30 DAYS) GRAPH

          - type: custom:apexcharts-card
            graph_span: 30d
            span:
              end: day
            header:
              show: true
              show_states: true
            apex_config:
              fill:
                type: gradient
                gradient:
                  type: vertical
                  shadeIntensity: 0
                  opacityFrom: 1
                  opacityTo: 0.5
                  stops: 10
              chart:
                height: 150px
              grid:
                show: false
                borderColor: darkslateblue
                strokeDashArray: 2
              dataLabels:
                background:
                  borderWidth: 0
                  opacity: 0
                  foreColor: white
                offsetY: -10
              plotOptions:
                bar:
                  borderRadius: 0
                  dataLabels:
                    position: top
            series:
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_today
                name: Rain Today
                color: deepskyblue
                type: column
                group_by:
                  func: max
                  duration: 1d
                  fill: zero
                statistics:
                  type: state
                  period: day
                  align: end
                show:
                  name_in_header: true
                  datalabels: true
                  in_chart: true
                  legend_value: false
                  extremas: false
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_today
                name: Rain Last 30 Days
                color: deepskyblue
                type: column
                group_by:
                  func: sum
                  duration: 30d
                  fill: zero
                statistics:
                  type: state
                  period: day
                  align: end
                show:
                  name_in_header: true
                  datalabels: false
                  in_chart: false
                  legend_value: false
6 Likes

APEX CHARTS Hourly Rain Fall Graph (24 Hours)


Some Important Settings:

# For the "Rain Now" (VISIBLE IN CHART)(Using the Rain Per Hour sensor)
graph_span: 24h # 24 hour graph span
span:
  end: hour # Span ends at the end of the hour
group_by:
  func: raw # Raw data
  duration: 1d # 1 Day Data
  fill: zero
statistics: # Grabs Long Term Statistics
  type: state
  period: hour # Grabs 1 hour at a time
  align: end
  show:
    name_in_header: true # shows name in header
    datalabels: true # makes data labels visible above bars
    in_chart: true # makes bars visible in chart
    legend_value: false # hides from legend
    extremas: false # hides extremas

# For the "Rain Today" (ONLY VISIBLE IN HEADER)(Using the Rain per Hour Sensor sensor)
  group_by:
    func: sum # Sum
    duration: 24h # 24 Hours duration
    fill: zero
  statistics: # Long Term Statistics
    type: state
    period: hour # Grabs 1 hour at a time
    align: end # align at end
  show:
    name_in_header: true # Show only Total in Header
    datalabels: false # Do not show data labels above graph
    in_chart: false # Do not show bars in graph
    legend_value: false # Do not show in legend

COMPLETE HOURLY RAINFALL (24 HOURS) GRAPH

      - type: vertical-stack
        cards:
          - type: custom:apexcharts-card
            graph_span: 24h
            span:
              end: hour
            header:
              show: true
              show_states: true
            apex_config:
              fill:
                type: gradient
                gradient:
                  type: vertical
                  shadeIntensity: 0
                  opacityFrom: 1
                  opacityTo: 0.5
                  stops: 10
              chart:
                height: 150px
              grid:
                show: false
                borderColor: darkslateblue
                strokeDashArray: 2
              dataLabels:
                background:
                  borderWidth: 0
                  opacity: 0
                  foreColor: white
                offsetY: -10
              plotOptions:
                bar:
                  borderRadius: 0
                  dataLabels:
                    position: top
            series:
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_last_hour
                name: Rain Last Hour
                color: deepskyblue
                type: column
                group_by:
                  func: raw
                  duration: 1d
                  fill: zero
                statistics:
                  type: state
                  period: hour
                  align: end
                show:
                  name_in_header: true
                  datalabels: true
                  in_chart: true
                  legend_value: false
                  extremas: false
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_last_hour
                name: Rain Last 24 Hours
                color: deepskyblue
                type: column
                group_by:
                  func: sum
                  duration: 24h
                  fill: zero
                statistics:
                  type: state
                  period: hour
                  align: end
                show:
                  name_in_header: true
                  datalabels: false
                  in_chart: false
                  legend_value: false
6 Likes

Great, thanks for this helpful Apex charts. Do you have others? maybe for Temps and/or Wind?

2 Likes

For wind I use Lovelace Windrose card

Temperature forecast I use Weather Chart Card

Temperatures at different levels of my house Mini Graph Card (Could easily be adapted in Apex.)

I also have my Netatmo Weather station feeding into SmartMixn. I add it as a webpage dashboard to my Home Assistant. There is also a really good Android App which gives you in detail reports and comparisons. I have about 4 years of data stored there.


1 Like

I tried to use your code (thanks!) to track my pv production for the last year, but I am getting an error message, so nothing is display :frowning:

1 Like

The Rainfall queries are done from a Daily Sensor and uses statistics data and group_by . This will give the correct values. The Netamo does not collect by default in month.

So if you have Daily Counter for your PV Production the below yaml code should do i
( it is the monthly rainfall query )

The very most important to know

Take the “state” from the Statistics per day (1 record ) and sum them up for a month.

So 1st is the statistics and 2nd is the group by u want to have , together with *span you get a correct chart.

type: custom:apexcharts-card
graph_span: 12month
span:
  end: month
  offset: "-0d"
header:
  show: true
  show_states: true
apex_config:
  fill:
    type: gradient
    gradient:
      type: vertical
      shadeIntensity: 0
      opacityFrom: 1
      opacityTo: 0.5
      stops: 10
  chart:
    height: 150px
  grid:
    show: false
    borderColor: darkslateblue
    strokeDashArray: 2
  dataLabels:
    background:
      borderWidth: 0
      opacity: 0
      foreColor: white
    offsetY: -10
  plotOptions:
    bar:
      borderRadius: 0
      dataLabels:
        position: top
  xaxis:
    tooltip:
      enabled: false
series:
  - entity: sensor.unknown_70_ee_50_7a_9c_c4_regen_niederschlagsmenge_heute
    name: Regen pro Monat
    color: deepskyblue
    type: column
    group_by:
      func: sum
      duration: 1month
      fill: zero
    statistics:
      type: state
      period: day
      align: start
    show:
      name_in_header: true
      datalabels: true
      in_chart: true
      legend_value: false
      extremas: false
  - entity: sensor.unknown_70_ee_50_7a_9c_c4_regen_niederschlagsmenge_heute
    name: Regen letzte 12 Monate
    color: deepskyblue
    type: column
    group_by:
      func: sum
      duration: 12month
      fill: zero
    statistics:
      type: state
      period: day
      align: end
    show:
      name_in_header: true
      datalabels: false
      in_chart: false
      legend_value: false

1 Like

Very big thanks for the fast help, looks like it works! I remade the PV daily sensor in November. The daily sensor for the Mini PV has Data since May.

pv rdy

3 Likes

Thank you so much! Just what I needed!

1 Like

You are welcome. I am pleased my many hours pulling my hair out is helping.

Great stuff, thank you so much for sharing this!

1 Like

No problems

Hi, what theme did you use? It’s beautiful.

Couple of minor tweaks to the cards

Rain 24hrs

  • Rain Last Hour Sensor

- type: custom:apexcharts-card
            graph_span: 24h
            span:
              end: hour
            header:
              show: true
              show_states: true
            apex_config:
              fill:
                type: gradient
                gradient:
                  type: vertical
                  shadeIntensity: 0
                  opacityFrom: 1
                  opacityTo: 0.5
                  stops: 10
              chart:
                height: 150px
              grid:
                show: false
                borderColor: darkslateblue
                strokeDashArray: 2
              dataLabels:
                background:
                  borderWidth: 0
                  opacity: 0
                  foreColor: white
                offsetY: -10
              plotOptions:
                bar:
                  borderRadius: 0
                  dataLabels:
                    position: top
            series:
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_last_hour
                name: Rain Last Hour
                color: deepskyblue
                type: column
                group_by:
                  func: raw
                  duration: 1d
                  fill: zero
                statistics:
                  type: state
                  period: hour
                  align: end
                show:
                  name_in_header: true
                  datalabels: true
                  in_chart: true
                  legend_value: false
                  extremas: false
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_last_hour
                name: Rain Last 24 Hours
                color: deepskyblue
                type: column
                group_by:
                  func: sum
                  duration: 24h
                  fill: zero
                statistics:
                  type: state
                  period: hour
                  align: end
                show:
                  name_in_header: true
                  datalabels: false
                  in_chart: false
                  legend_value: false

Rain 30days

  • Rain Accumulated Per Day Sensor

- type: custom:apexcharts-card
            graph_span: 30d
            span:
              end: day
            header:
              show: true
              show_states: true
            apex_config:
              fill:
                type: gradient
                gradient:
                  type: vertical
                  shadeIntensity: 0
                  opacityFrom: 1
                  opacityTo: 0.5
                  stops: 10
              chart:
                height: 150px
              grid:
                show: false
                borderColor: darkslateblue
                strokeDashArray: 2
              dataLabels:
                background:
                  borderWidth: 0
                  opacity: 0
                  foreColor: white
                offsetY: -10
              plotOptions:
                bar:
                  borderRadius: 0
                  dataLabels:
                    position: top
            series:
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_today
                name: Rain Today
                color: deepskyblue
                type: column
                group_by:
                  func: raw
                  duration: 1d
                  fill: zero
                statistics:
                  type: state
                  period: day
                  align: end
                show:
                  name_in_header: true
                  datalabels: true
                  in_chart: true
                  legend_value: false
                  extremas: false
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_today
                name: Rain Last 30 Days
                color: deepskyblue
                type: line
                group_by:
                  func: sum
                  duration: 30d
                  fill: zero
                statistics:
                  type: state
                  period: day
                  align: start
                show:
                  name_in_header: true
                  datalabels: false
                  in_chart: false
                  legend_value: false

Rain 12 Months

  • Rain Accumulated Per Day Sensor

- type: custom:apexcharts-card
            graph_span: 12month
            span:
              end: month
              offset: '-0d'
            header:
              show: true
              show_states: true
            apex_config:
              fill:
                type: gradient
                gradient:
                  type: vertical
                  shadeIntensity: 0
                  opacityFrom: 1
                  opacityTo: 0.5
                  stops: 10
              chart:
                height: 150px
              grid:
                show: false
                borderColor: darkslateblue
                strokeDashArray: 2
              dataLabels:
                background:
                  borderWidth: 0
                  opacity: 0
                  foreColor: white
                offsetY: -10
              plotOptions:
                bar:
                  borderRadius: 0
                  dataLabels:
                    position: top
            series:
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_today
                name: Rain This Month
                color: deepskyblue
                type: column
                group_by:
                  func: sum
                  duration: 1month
                  fill: zero
                statistics:
                  type: state
                  period: day
                  align: end
                show:
                  name_in_header: true
                  datalabels: true
                  in_chart: true
                  legend_value: false
                  extremas: false
              - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_today
                name: Rain Last 12 Months
                color: deepskyblue
                type: column
                group_by:
                  func: sum
                  duration: 12month
                  fill: zero
                statistics:
                  type: state
                  period: day
                  align: end
                show:
                  name_in_header: true
                  datalabels: false
                  in_chart: false
                  legend_value: false
1 Like

I notice an error for last hour sensor with you code as it is.
here the stat graph of the netatmo last hour


and here the Apex graph with last_hour sensor show errror in the hours rain as well in the sum for the last 24h

As you can see the 5.1mm didnt show well.

I manage to do it right with the today sensor as it show here, the Rain last 24hours sum is correct too.

Any suggestion for the problem ? am I the only one who find a value error.

Here my modify code :

type: custom:apexcharts-card
style: |
  ha-card {
    background: none;
    border: none;
  }
graph_span: 24h
span:
  end: hour
header:
  show: true
  show_states: true
apex_config:
  fill:
    type: gradient
    gradient:
      type: vertical
      shadeIntensity: 0
      opacityFrom: 1
      opacityTo: 0.5
      stops: 10
  chart:
    height: 150px
  grid:
    show: false
    borderColor: darkslateblue
    strokeDashArray: 2
  dataLabels:
    background:
      borderWidth: 0
      opacity: 0
      foreColor: white
    offsetY: -10
  plotOptions:
    bar:
      borderRadius: 0
      dataLabels:
        position: top
series:
  - entity: sensor.pluviometre_netatmo_precipitation_aujourd_hui
    name: Rain Last Hour
    color: deepskyblue
    type: column
    group_by:
      func: raw
      duration: 1d
      fill: zero
    statistics:
      type: change
      period: hour
      align: end
    show:
      name_in_header: true
      datalabels: true
      in_chart: true
      legend_value: false
      extremas: false
  - entity: sensor.pluviometre_netatmo_precipitation_aujourd_hui
    name: Rain Last 24 Hours
    color: deepskyblue
    type: column
    group_by:
      func: sum
      duration: 24h
      fill: zero
    statistics:
      type: change
      period: hour
      align: end
    show:
      name_in_header: true
      datalabels: false
      in_chart: false
      legend_value: false


I am pretty sure the difference is down to daily being taken from midnight to midnight. While the hourly sensor is reading the last 24 hrs, it will differ.

I use the hourly graph as trend only, how much rain fell and when. The two bottom graphs do the totals.

I don’t agree with your original premise that this isn’t possible to do in stock HA.

A statistics graph card, of the “rain accumulated per day” entity, bar chart, set to monthly resolution, and the change statistic, should show a nice bar chart of rainfall per month.

@karwosts and @gris74 I have revisited this now I have finally had a day with rain, that coincided with some available time to look at it properly.

Comments throughout the YAML.
These graphs use the Netatmo Rainfall sensors directly

  • Hourly Rolling Cumulative Rainfall
state_class: total
unit_of_measurement: mm
attribution: Data provided by Netatmo
device_class: precipitation
friendly_name: Netatmo Rain Precipitation last hour
  • Daily Cumulative Rainfall (Resets Midnight)
state_class: total_increasing
unit_of_measurement: mm
attribution: Data provided by Netatmo
device_class: precipitation
friendly_name: Netatmo Rain Precipitation today 

### What’s happening under the hood

* Daily cumulative (…rain_today)
Increases when it’s raining and resets at midnight. Good for today and as a base for derived totals.
* statistics: acts as a first bucketing stage
type: state, period: day, align: end collapses raw history to one sample per calendar day (the end-of-day cumulative). This prevents over-counting when you later sum across longer windows.
* group_by: is the second bucketing stage
* duration: 1h, func: diff → turn cumulative into hourly bars.
* duration: 1d, func: maxdaily totals (end-of-day cumulative).
* duration: 30d, func: sum (on day-level stats) → rolling 30-day total.
* duration: 1month, func: sum (on day-level stats) → monthly totals.
* duration: 12month, func: sum (on day-level stats) → rolling 12-month total.
* span: offset: '+1h' HOURLY RAINFALL
Shifts the window start forward one hour so the first hour bucket does not pick up yesterdays total, prior midnight. Without the offset, ApexCharts will pick up the bucket start, previous to midnight and produce a negative figure.
* span.offset: '+1d' DAILY RAINFALL
Shifts the window end forward one day so the latest day/month bucket appears even before it completely closes. Without the offset, ApexCharts often hides the last (still-forming) bar until the bucket end.

What’s happening under the hood

  • Daily cumulative (…rain_today)
    Increases while it’s raining and resets at midnight. Great base for derived totals.

  • Bucketing stages

    1. statistics: first buckettype: state, period: day, align: end collapses raw history to one end-of-day sample per calendar day. This prevents over-counting when you sum over longer windows.
    2. group_by: second bucket — performs the final aggregation you want to plot/show.
  • Hourly bars (correct + live)
    Use 5-minute deltas of the daily cumulative (statistics: type: change, period: 5minute) → clamp negativessum to 1h. This updates mid-hour and survives sensor dips/resets.

  • Daily/rolling/monthly
    Keep using the day EOD approach for accuracy and speed:

    • duration: 1d, func: max → daily totals (end-of-day cumulative)
    • duration: 30d, func: sum (on day EOD) → rolling 30-day total
    • duration: 1month, func: sum (on day EOD) → monthly totals
    • duration: 12month, func: sum (on day EOD) → rolling 12-month total
      NOTE: 5/10/30min deltas can be used here to increase update interval but will increase processing overhead
  • Offsets

    • Hourly: not needed with the 5-minute method (offsets only move the viewport).
    • Daily/Monthly: span.offset: '+1d' is useful to show the still-forming today/this month bar.

It would be great if someone using monthly or annual, statistic sensor or utility meter can confirm if the below graphs are correct.

DAILY RAINFALL

  • - Hourly Bars (from daily cumulative)
  • Hourly Bars (from 5-minute deltas of daily cumulative)
  • Rain Last Hour (from rolling hourly cumulative)(raw sensor)
  • - span: offset: '+1h' to prevent a negative number at midnight
  • Rain Today (from daily cumulative) (5-minute deltas → 1d sum)

Header chips show:

  • Rain Last Hour (Netatmo rolling 60-min sum)
  • Rain Today (daily cumulative)
  • - The bars are computed from the DAILY cumulative using diff per hour.
  • The bars are computed from 5-minute deltas (gives live updates).

type: custom:apexcharts-card
header:
  title: >
    Rain — Hourly Bars (from daily cumulative) - Rain Last Hour
    (rolling 60-min) - Rain Today (sum of 5-min deltas)
  show: true
  show_states: true
graph_span: 24h
span:
  end: day
yaxis:
  - min: 0
    decimals: 1
    apex_config:
      labels:
        formatter: |
          EVAL: (v) => `${(v ?? 0).toFixed(2)} mm`
apex_config:
  fill:
    type: gradient
    gradient:
      type: vertical
      shadeIntensity: 0
      opacityFrom: 1
      opacityTo: 0.5
      stops: [0, 100]
  chart:
    height: 150px
  grid:
    show: false
    borderColor: darkslateblue
    strokeDashArray: 2
  dataLabels:
    background:
      borderWidth: 0
      opacity: 0
      foreColor: white
    offsetY: -10
  plotOptions:
    bar:
      borderRadius: 0
      dataLabels:
        position: top
series:
  - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_last_hour
    name: Rain Last Hour
    type: line
    show:
      in_chart: false
      in_header: true

  - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_today
    name: Hourly Rain Bars
    color: deepskyblue
    type: column
    statistics:
      type: change
      period: 5minute
      align: end
    transform: "return x < 0 ? 0 : x;"
    group_by:
      duration: 1h
      func: sum
      start_with_last: true
    show:
      in_chart: true
      datalabels: true
      in_header: false

  - entity: sensor.netatmo_devonport_tas_indoor_rain_rain_today
    name: Rain Today
    type: line
    statistics:
      type: change
      period: 5minute
      align: end
    transform: "return x < 0 ? 0 : x;"
    group_by:
      duration: 1d
      func: sum
      start_with_last: true
    show:
      in_chart: false
      in_header: true
      name_in_header: true

ROLLING 30 DAY RAINFALL

  • Daily Bars (from daily cumulative)
  • Rain Today (from daily cumulative + statistics day bucket)
  • Rain Last 30 days (rolling 30-day total from daily cumulative + statistics day bucket)

KEY IDEAS:

  • statistics: period: day, align: end → FIRST reduces the raw history to ONE value per day: the end-of-day cumulative. (This is the “second bucket” stage that avoids over-counting intra-day samples.)

  • group_by on top of that day-level series then does the per-day bar and the rolling 30-day sum accurately.

OFFSET EXPLANATION:

  • span.offset: ‘+1d’ nudges the window end forward one day so the latest day’s bar (which completes at 23:59:59) is included and renders correctly even before midnight.

          - type: custom:apexcharts-card
            header:
              title: >-
                Rain — Daily Bars (from daily cumulative) - Rain Today (from
                daily cumulative + statistics)  - Rain Last 30 days (rolling
                30-day total from daily cumulative + statistics)
              show: true
              show_states: true
            graph_span: 30d                            # <- x-axis shows last 30 days
            span:
              end: day
              offset: '+1d'                            # <- include the "current day" bar before the day fully closes
            yaxis:
              - min: 0
                decimals: 1
                apex_config:
                  labels:
                    formatter: |
                      EVAL: (v) => `${(v ?? 0).toFixed(2)} mm`
            apex_config:
              fill:
                type: gradient
                gradient:
                  type: vertical
                  shadeIntensity: 0
                  opacityFrom: 1
                  opacityTo: 0.5
                  stops:
                    - 0
                    - 100
              chart:
                height: 150px
              grid:
                show: false
                borderColor: darkslateblue
                strokeDashArray: 2
              dataLabels:
                background:
                  borderWidth: 0
                  opacity: 0
                  foreColor: white
                offsetY: -10
              plotOptions:
                bar:
                  borderRadius: 0
                  dataLabels:
                    position: top
              tooltip:
                x:
                  format: 'dd MMM yyyy'
            series:
              # HEADER STATE: Today's cumulative (live).
              - entity: sensor.netatmo_rain_today
                name: Rain Today
                type: line
                show:
                  in_chart: false
                  in_header: true
                  name_in_header: true

              # BARS: Daily totals (exact) from the daily cumulative.
              # STAGE 1 (statistics): collapse raw history to ONE value per day,
              #   using end-of-day cumulative (type: state, period: day, align: end).
              # STAGE 2 (group_by): pick the day's MAX (defensive; aligns with EOD).
              - entity: sensor.netatmo_rain_today
                name: Daily total
                color: deepskyblue
                type: column
                group_by:
                  duration: 1d                         # <- 1 bar per day
                  func: last                            # <- end-of-day cumulative
                  start_with_last: true
                  fill: zero
                statistics:
                  type: state                          # <- take the entity's state (not avg/min/max inside the day)
                  period: day                          # <- FIRST bucket to one sample per calendar day
                  align: end                           # <- choose the end-of-day value (true daily total)
                show:
                  in_chart: true
                  datalabels: true
                  in_header: false
                stroke_width: 0

              # HEADER STATE: Rolling 30-day total.
              # STAGE 1 (statistics day, align end): one value per day (EOD cumulative).
              # STAGE 2 (group_by 30d + sum): sum the last 30 *days* → true rolling 30-day rainfall.
              - entity: sensor.netatmo_rain_today
                name: Rain Last 30 days
                type: line
                group_by:
                  duration: 30d                        # <- rolling window size = 30 days
                  func: sum                            # <- sum those daily EOD values → 30-day total
                  start_with_last: true
                  fill: zero
                statistics:
                  type: state
                  period: day
                  align: end                           # <- ensure the day-level value is the EOD snapshot
                show:
                  in_chart: false
                  in_header: true
                  name_in_header: true

ROLLING 12 MONTH RAINFALL

  • Rain — Monthly Bars (from daily cumulative + statistics)
  • Rain This Month (1month totals from daily cumulative + statistics day bucket)
  • Rain Last 12 Months (rolling 12month total from daily cumulative + statistics day bucket)

SAME “SECOND BUCKET” IDEA:

  • statistics period: day, align: end → one EOD data point per day.
  • THEN group_by over 1 month with func: sum → exact month totals.

OFFSET EXPLANATION:

  • span.offset: ‘+1d’ lets the current month’s bar appear before midnight of the last day by nudging the end of the window forward.

          - type: custom:apexcharts-card
            header:
              title: >-
                Rain — Monthly Bars (from daily cumulative + statistics) - Rain
                This Month (1month totals from daily cumulative + statistics)  -
                Rain Last 12 Months (rolling 12month total from daily cumulative +
                statistics)
              show: true
              show_states: true
            graph_span: 12month                         # NOTE works in many setups; if your card requires it, use 12mo
            span:
              end: month                                # <- align buckets to calendar months
            apex_config:
              fill:
                type: gradient
                gradient:
                  type: vertical
                  shadeIntensity: 0
                  opacityFrom: 1
                  opacityTo: 0.5
                  stops: [0, 100]                       # <- array; avoids Apex error
              chart:
                height: 150px
              grid:
                show: false
                borderColor: darkslateblue
                strokeDashArray: 2
              dataLabels:
                background:
                  borderWidth: 0
                  opacity: 0
                  foreColor: white
                offsetY: -10
              plotOptions:
                bar:
                  borderRadius: 0
                  dataLabels:
                    position: top
              tooltip:
                x:
                  format: 'MMM yyyy'
            series:
              # MONTHLY BARS: exact month totals from the daily cumulative.
              # STAGE 1: statistics day/end → one EOD point per day.
              # STAGE 2: group_by month/sum → sum of those day points in that month.
              - entity: sensor.netatmo_rain_today
                name: Rain This Month
                color: deepskyblue
                type: column
                group_by:
                  func: sum                              # <- adds the daily EOD values inside each month
                  duration: 1month                       # NOTE: works in many setups; if needed, use 1mo
                  fill: zero
                statistics:
                  type: state
                  period: day
                  align: end                              # <- use end-of-day cumulative as the "daily total"
                show:
                  name_in_header: true
                  datalabels: true
                  in_chart: true
                  legend_value: false
                  extremas: false

              # HEADER STATE: rolling last 12 months (sum of month’s daily EOD values).
              # STAGE 1: statistics day/end → daily EOD points.
              # STAGE 2: group_by 12month/sum → rolling 12-month rainfall.
              - entity: sensor.netatmo_rain_today
                name: Rain Last 12 Months
                color: deepskyblue
                type: column
                group_by:
                  func: sum
                  duration: 12month                      # NOTE if your card requires, use 12mo
                  fill: zero
                statistics:
                  type: state
                  period: day
                  align: end
                show:
                  name_in_header: true                   # <- show the rolling 12-month total as a header state
                  datalabels: false
                  in_chart: false                        # <- chip only; hide from plot
                  legend_value: false

Make sure Recorder retention covers your windows (e.g., ≥ 400 days if you ever want a full 12-month rolling history without gaps).

Example Action Call that I call weekly, to ensure database stays at a reasonable size.

The filter is applied by:

  • in configuration.yaml recorder: you can choose either rule
    • include: (add sensors you want in recorder database) or;
    • exclude: (add sensors you don’t want in recorder database)

To avoid a huge database slowing your HA instance down make sure you only include the sensors you need to for 400 days.

Hi, I’m having a problem with the 30-day stats. The graph isn’t loading; it’s always loading. Here’s the code I copied and adapted with my sensors.

type: custom:apexcharts-card
header:
  title: >-
    Rain — Daily Bars (from daily cumulative) - Rain Today (from daily
    cumulative + statistics)  - Rain Last 30 days (rolling 30-day total from
    daily cumulative + statistics)
  show: true
  show_states: true
graph_span: 30d
span:
  offset: +1d
  end: day
yaxis:
  - min: 0
    decimals: 1
    apex_config:
      labels:
        formatter: |
          EVAL: (v) => `${(v ?? 0).toFixed(2)} mm`
apex_config:
  fill:
    type: gradient
    gradient:
      type: vertical
      shadeIntensity: 0
      opacityFrom: 1
      opacityTo: 0.5
      stops:
        - 0
        - 100
  chart:
    height: 150px
  grid:
    show: false
    borderColor: darkslateblue
    strokeDashArray: 2
  dataLabels:
    background:
      borderWidth: 0
      opacity: 0
      foreColor: white
    offsetY: -10
  plotOptions:
    bar:
      borderRadius: 0
      dataLabels:
        position: top
series:
  - entity: sensor.tempest_st_00032986_rain_today
    name: Rain Today
    type: line
    show:
      in_chart: false
      in_header: true
      name_in_header: true
  - entity: sensor.tempest_st_00032986_rain_today
    name: Daily total
    color: deepskyblue
    type: column
    group_by:
      duration: 1d
      func: max
      start_with_last: true
    statistics:
      type: state
      period: day
      align: end
    show:
      in_chart: true
      datalabels: true
      in_header: false
    stroke_width: 0
  - entity: sensor.tempest_st_00032986_rain_today
    name: Rain Last 30 days
    type: line
    group_by:
      duration: 30d
      func: sum
      start_with_last: true
    statistics:
      type: state
      period: day
      align: end
    show:
      in_chart: false
      in_header: true
      name_in_header: true

I will look at it today, I also have a solution for the hourly graph dropping to negatives that I will post today.

@ValMarDav the only thing I can see while on my phone is

  • missing quotes on span: offset: ‘+1’
  • array at gradient:: stops; [0, 100] rather than the list.
1 Like