SNMP bandwidth monitor using statistics

cards:
  - cards:
      - color_thresholds:
          - color: '#e45e65'
            value: 10
          - color: '#e0b400'
            value: 5
          - color: '#0da035'
            value: -1
        color_thresholds_transition: hard
        entities:
          - sensor.nbn_internet_in_mbps
        group: false
        hour24: true
        line_width: 6
        points_per_hour: 1
        show:
          extrema: true
          fill: fade
          icon: true
          labels: false
          name: true
          state: true
        style: |
          ha-card {
            border: solid 2px var(--primary-color);
          }
        type: 'custom:mini-graph-card'
      - color_thresholds:
          - color: '#e45e65'
            value: 2
          - color: '#e0b400'
            value: 1
          - color: '#0da035'
            value: -1
        color_thresholds_transition: hard
        entities:
          - sensor.nbn_internet_out_mbps
        group: false
        hour24: true
        line_width: 6
        points_per_hour: 1
        show:
          extrema: true
          icon: true
          labels: false
          name: true
          state: true
        style: |
          ha-card {
            border: solid 2px var(--primary-color);
          }
        type: 'custom:mini-graph-card'
    type: horizontal-stack
  - cards:
      - color_thresholds:
          - color: '#e45e65'
            value: 10
          - color: '#e0b400'
            value: 5
          - color: '#0da035'
            value: -1
        color_thresholds_transition: hard
        entities:
          - sensor.4g_internet_in_mbps
        group: false
        hour24: true
        line_width: 6
        points_per_hour: 1
        show:
          extrema: true
          fill: fade
          icon: true
          labels: false
          name: true
          state: true
        style: |
          ha-card {
            border: solid 2px var(--primary-color);
          }
        type: 'custom:mini-graph-card'
      - color_thresholds:
          - color: '#e45e65'
            value: 2
          - color: '#e0b400'
            value: 1
          - color: '#0da035'
            value: -1
        color_thresholds_transition: hard
        entities:
          - sensor.4g_internet_out_mbps
        group: false
        hour24: true
        line_width: 6
        points_per_hour: 1
        show:
          extrema: true
          fill: fade
          icon: true
          labels: false
          name: true
          state: true
        style: |
          ha-card {
            border: solid 2px var(--primary-color);
          }
        type: 'custom:mini-graph-card'
    type: horizontal-stack
type: vertical-stack

@seidler first off, thanks for this post! I already started to implement the other alternative you linked and did not like it either. Your solution seems much nicer!

Sorry for bringing this up so late, but what exactly is the value_template calculation doing for us? I looked at my values, and it seems to me that the change_rate attribute already is bytes/s basically. Also when looking into the source, it seems to me that this is already what we want (see https://github.com/home-assistant/core/blob/6d24a65313f0c8413c71feeca79f2f0ff79d2b60/homeassistant/components/statistics/sensor.py#L270). Am I missing something here?

The conversion to Mbit/s makes sense, but the division by sampling_size - 1 I can’t follow right now.

Thanks for this. I Struggled to find my own OID, but I got it to work.
But I noticed that sometimes some negatives values are calculated for both in and out sensors (mbps).
Did you notice any issue like this? So the graph turns to be a mess. But most of the time, numbers seem to be right.
image

Hi,

Based on this topic I tried to port this to my own situation, using a Unifi 8 port 60W switch.
Actually it is working, but for some reason the calculation back to Mbps is not in sync what I see on my Unifi controller, for example:

My ISP max download speed is 60Mbps, and while I download at full speed the sensor shows 210Mbps.

I am using the uplink of the switch towards my ISP router, which should not carry more than my max ISP speeds (and the Unifi Controller is reporting only the maximum ISP speeds)

Probably somebody has an idea what might do the trick in my situation?
This is what my config looks like:

  - platform: snmp
    name: 'Internet incoming'
    host: 192.168.3.200
    baseoid: 1.3.6.1.2.1.31.1.1.1.6.1
    community: 'public'
    version: '2c'
    scan_interval: 10
  - platform: snmp
    name: 'Internet outgoing'
    host: 192.168.3.200
    baseoid: 1.3.6.1.2.1.31.1.1.1.10.1
    community: 'public'
    version: '2c'
    scan_interval: 10
  - platform: statistics
    name: 'Internet in Stats'                      
    entity_id: sensor.internet_incoming                  
    sampling_size: 4                              
    max_age:                                      
      hours: 24                                   
  - platform: statistics                          
    name: 'Internet out Stats'                     
    entity_id: sensor.internet_outgoing
    sampling_size: 4
    max_age:
      hours: 24
  - platform: template
    sensors:
      internet_in_mbps:
        value_template: "{{ (state_attr('sensor.internet_in_stats','change_rate')|float*8*(state_attr('sensor.internet_in_stats', 'sampling_size')-1)/1000000)|round(2) }}"
        unit_of_measurement: 'MBps'
        entity_id: sensor.internet_in_stats
      internet_out_mbps:
        value_template: "{{ (state_attr('sensor.internet_out_stats','change_rate')|float*8*(state_attr('sensor.internet_out_stats', 'sampling_size')-1)/1000000)|round(2) }}"
        unit_of_measurement: 'MBps'
        entity_id: sensor.internet_out_stats

Yes, and I used to get warning in my logs about it.

I have to figure out this monitor as it was adding about 20% overhead on my RP3B+.

So i found the part about SNMP here very helpful but i couldn’t wrap my head around the template and the stats part.

and the values i measured was way off (sometimes 1500Mbs when the router reported 500Mbs and other times 160Mbs when the router reported 140Mbs ) but i think i have found the problem and an alternative solution

i believe (not at all sure) that the change rate on the statistics is just how much the value changes for each update without any regards to time, but what you really want for this (turning the running total into Mb/s) is the derivative of the value you get from the router and luckily enough there is a build in sensor for that that will calculate the derivation and take the time between updates into account.

i have done it like this:

platform: snmp
name: 'ER lite WAN In'
host: 192.168.3.1
baseoid: 1.3.6.1.2.1.31.1.1.1.6.2
community: 'public'
version: '2c'
scan_interval: 10

platform: derivative
source: sensor.er_lite_wan_in
unit_time: s
unit: B
name: erl_wan_in_derivative

platform: template
sensors:
  erl_wan_in_mbps:
    value_template:  "{{ ((states('sensor.erl_wan_in_derivative')|float*8)/1000000)|round(2) }}"
    unit_of_measurement: 'Mbps'
    entity_id: sensor.erl_wan_in_derivative
    friendly_name: Internet in Dev

i did a little test with this where i integrated both this and the approach described other places in this thread where i would pick to points where i had a value on each and calculate how many MB had been transferred in that time span and then calculate an error for each of the approaches and i think the results speak for them self:

image

i hope this can help someone.

8 Likes

I tried your method and found it considerably more accurate. Thanks!

glad to hear it helped you.
keep in mind when comparing this to whatever you use to verify against that what ever you are comparing to is probably doing the same thing but at a different Δt so they might not be the same but booth values can be true. (because they are essentially average transfer rates over different times.)

Yeah for sure.

I was using the erx’s built in monitoring for comparison, it has a 2 sec updating bar graph that has about 80 seconds of history visible. Comparing this to my previous sensor ( averaged over a minute) the old sensor was obviously reading up to10x too high. Your version of the sensor is spot on compared to the erx’s monitor.

Thanks, the derivative method has been giving me more accurate readings. Except every once in a while, it was resulting up with a really large negative numbers (which screws up the graph view). Not sure what’s causing it (possibly my router misreporting…), but added a max function to ignore those results.

  - platform: snmp
    name: wan_in
    baseoid: 1.3.6.1.2.1.2.2.1.10.4
    host: !secret zeus_hostname
    version: !secret zeus_snmp_version
    accept_errors: true
    scan_interval: 10
  - platform: snmp
    name: wan_out
    baseoid: 1.3.6.1.2.1.2.2.1.16.4
    host: !secret zeus_hostname
    version: !secret zeus_snmp_version
    accept_errors: true
    scan_interval: 10
  - platform: derivative
    name: wan_in_der
    source: sensor.wan_in
    unit_time: s
    unit: B
  - platform: derivative
    name: wan_out_der
    source: sensor.wan_out
    unit_time: s
    unit: B
  - platform: template
    sensors:
      wan_in_mbps:
        value_template:  "{{ [((states('sensor.wan_in_der')|float*8)/1000000)|round(2),0]|max }}"
        unit_of_measurement: 'Mbps'
        entity_id: sensor.wan_in_der
        friendly_name: "WAN In"
      wan_out_mbps:
        value_template:  "{{ [((states('sensor.wan_out_der')|float*8)/1000000)|round(2),0]|max }}"
        unit_of_measurement: 'Mbps'
        entity_id: sensor.wan_out_der
        friendly_name: "WAN Out"
2 Likes

I’m wondering if with this data I can create a new template sensor or something like that to view the total traffic by day and month, would be possible?

Sure just use the wan in and wan out sensors (not the derivative sensors) in the utility meter.

1 Like

See my post.

1 Like

Thanks! I tried to to use the utility meter but when I put the sensor on a History Graph Card Configuration I’m getting strange results:

Screen Shot 2020-11-05 at 10.57.37

sensor:
    
  - platform: snmp
    name: 'ERX WAN In'
    host: 192.168.1.1
    baseoid: 1.3.6.1.2.1.31.1.1.1.6.4
    community: 'public'
    version: '2c'
    scan_interval: 10
    
  - platform: snmp
    name: 'ERX WAN Out'
    host: 192.168.1.1
    baseoid: 1.3.6.1.2.1.31.1.1.1.10.4
    community: 'public'
    version: '2c'
    scan_interval: 10
      
  - platform: derivative
    source: sensor.erx_wan_in
    unit_time: s
    unit: B
    name: erx_wan_in_derivative 
    
  - platform: derivative
    source: sensor.erx_wan_out
    unit_time: s
    unit: B
    name: erx_wan_out_derivative 
  
  - platform: template
    sensors:
      erx_wan_in_mbps:
        value_template:  "{{ ((states('sensor.erx_wan_in_derivative')|float*8)/1000000)|round(2) }}"
        unit_of_measurement: 'Mbps'
        entity_id: sensor.erx_wan_in_derivative
        friendly_name: Internet in Dev
    
      erx_wan_out_mbps:
        value_template:  "{{ ((states('sensor.erx_wan_in_derivative')|float*8)/1000000)|round(2) }}"
        unit_of_measurement: 'Mbps'
        entity_id: sensor.erx_wan_out_derivative
        friendly_name: Internet out Dev
  
utility_meter:
  wan_in_monthly:
    source: sensor.erx_wan_in
    cycle: monthly 
    
  wan_in_daily:
    source: sensor.erx_wan_in
    cycle: daily
    
  wan_out_monthly:
    source: sensor.erx_wan_out
    cycle: monthly 
    
  wan_out_daily:
    source: sensor.erx_wan_out
    cycle: daily       

What I did wrong?

I cant see your image. The host is blocked here. Just drag your image file into the post on the forum.

EDIT: ok that is because the sensors do not have a unit. You will probably want to change that from bytes to MB anyway. Also you have a few errors in your templates (using the in sensor for the out template).

If you are on version 0.117.x this should work:

sensor:
    
  - platform: snmp
    name: 'ERX WAN In'
    host: 192.168.1.1
    baseoid: 1.3.6.1.2.1.31.1.1.1.6.4
    community: 'public'
    version: '2c'
    scan_interval: 10
    
  - platform: snmp
    name: 'ERX WAN Out'
    host: 192.168.1.1
    baseoid: 1.3.6.1.2.1.31.1.1.1.10.4
    community: 'public'
    version: '2c'
    scan_interval: 10
      
  - platform: derivative
    source: sensor.erx_wan_in
    unit_time: s
    unit: B
    name: erx_wan_in_derivative 
    
  - platform: derivative
    source: sensor.erx_wan_out
    unit_time: s
    unit: B
    name: erx_wan_out_derivative 
  
  - platform: template
    sensors:
      erx_wan_in_mbps:
        value_template:  "{{ (states('sensor.erx_wan_in_derivative')|float*8/1000000)|round(2) }}"
        unit_of_measurement: 'Mbps'
        friendly_name: Internet in Dev
    
      erx_wan_out_mbps:
        value_template:  "{{ (states('sensor.erx_wan_out_derivative')|float*8/1000000)|round(2) }}"
        unit_of_measurement: 'Mbps'
        friendly_name: Internet out Dev

      erx_wan_download_mib:
        value_template:  "{{ (states('sensor.erx_wan_in')|float/1000000)|round(2) }}"
        unit_of_measurement: 'MiB'
        friendly_name: Internet in Dev
    
      erx_wan_upload_mib:
        value_template:  "{{ (states('sensor.erx_wan_out')|float/1000000)|round(2) }}"
        unit_of_measurement: 'MiB'
        friendly_name: Internet out Dev
  
utility_meter:
  wan_in_monthly:
    source: sensor.erx_wan_download_mib
    cycle: monthly 
    
  wan_in_daily:
    source: sensor.erx_wan_download_mib
    cycle: daily
    
  wan_out_monthly:
    source: sensor.erx_wan_upload_mib
    cycle: monthly 
    
  wan_out_daily:
    source: sensor.erx_wan_upload_mib
    cycle: daily       

1 Like

Thanks! Now the graph is looking right!

Now I’m going to wait an see how to improve the visualization of this data.

1 Like

I think there is something wrong with your template. There’s no way you are using 6 petabytes (10 to the power of 15) in 20 minutes.

GiB would probably be a better unit for general WAN use anyway (I used MiB as I took the template from my 4G cellular connection). Try this:

      erx_wan_download_gib:
        value_template:  "{{ (states('sensor.erx_wan_in')|float/1000000000)|round(2) }}"
        unit_of_measurement: 'GiB'
        friendly_name: Internet in Dev
    
      erx_wan_upload_gib:
        value_template:  "{{ (states('sensor.erx_wan_out')|float/1000000000)|round(2) }}"
        unit_of_measurement: 'GiB'
        friendly_name: Internet out Dev
  
utility_meter:
  wan_in_monthly:
    source: sensor.erx_wan_download_gib
    cycle: monthly 
    
  wan_in_daily:
    source: sensor.erx_wan_download_gib
    cycle: daily
    
  wan_out_monthly:
    source: sensor.erx_wan_upload_gib
    cycle: monthly 
    
  wan_out_daily:
    source: sensor.erx_wan_upload_gib
    cycle: daily
1 Like

I was selecting the wrong sensors, now I think is right:

1 Like

Much better. If you still want to get rid of those extra zeros the template in my post above will measure in GiB.

1 Like

One minor correction. I got my units back to front. It should be MB or GB, not MiB or GiB.

MiB is a power of 2, MB is a power of 10.

2 Likes