SNMP bandwidth monitor using statistics

After finding that the IGP integration maxes out at 32bit counters (which is a day or less of traffic), I looked into other ways of making my internet usage visible. I looked long and hard at SNMP Bandwidth Monitor but somehow it didn’t feel right/easy.

So what I have right now seems to work as well:

sensor:
  - platform: snmp
    name: 'USG WAN in'
    host: 192.168.2.1
    baseoid: 1.3.6.1.2.1.31.1.1.1.6.2
    community: 'public'
    version: '2c'
    scan_interval: 10
  - platform: snmp
    name: 'USG WAN out'
    host: 192.168.2.1
    baseoid: 1.3.6.1.2.1.31.1.1.1.10.2
    community: 'public'
    version: '2c'
    scan_interval: 10
  - platform: statistics
    name: 'USG WAN in Stats'                      
    entity_id: sensor.usg_wan_in                  
    sampling_size: 4                              
    max_age:                                      
      hours: 24                                   
  - platform: statistics                          
    name: 'USG WAN out Stats'                     
    entity_id: sensor.usg_wan_out
    sampling_size: 4
    max_age:
      hours: 24
  - platform: template
    sensors:
      internet_in_mbps:
        value_template: "{{ (state_attr('sensor.usg_wan_in_stats_mean','change_rate')|float*8*(state_attr('sensor.usg_wan_in_stats_mean', 'sampling_size')-1)/1000000)|round(2) }}"
        unit_of_measurement: 'MBps'
        entity_id: sensor.usg_wan_in_stats_mean
      internet_out_mbps:
        value_template: "{{ (state_attr('sensor.usg_wan_out_stats_mean','change_rate')|float*8*(state_attr('sensor.usg_wan_out_stats_mean', 'sampling_size')-1)/1000000)|round(2) }}"
        unit_of_measurement: 'MBps'
        entity_id: sensor.usg_wan_out_stats_mean

This uses the 64 bit counters. If your router doesn’t have those, use 1.3.6.1.2.1.2.2.1.10.10 and 1.3.6.1.2.1.2.2.1.16.10 or similar.

I find this solution quite elegant because it only needs 3x2 sensors (SNMP, statistics, bandwidth) and the final sensor can be used in Lovelace right away.

You can customize the scan_interval and the sampling_size for smoother or more current values. When changing the latter, make sure you set sampling_size-1 as the factor in the template sensor (3 in my config because my sampling_size is 4). Scratch that, I added a state_attr to take care of that.

5 Likes

I wonder if the Edgerouter has the same OIDs as the USG?

Might try this later.

I tried SNMPwalk a while ago but found it incredibly confusing.

I’m relatively certain the OIDs are the same. These are generic SNMP MIBs that are used across many vendors. And the USG is basically an ER with some minor software differences. The only real difference could be the last number (2 in my case) because that defines the interface which is read. To find out the interface names, use

snmpbulkwalk -v 2c -c public 192.168.2.1 1.3.6.1.2.1.31.1.1.1.18

or

snmpbulkwalk -v 2c -c public 192.168.2.1 1.3.6.1.2.1.31.1.1.1.1
1 Like

Thanks for that. This is what I got for the Edgerouter X (comments show my WAN interfaces)

iso.3.6.1.2.1.31.1.1.1.1.1 = STRING: "lo"
iso.3.6.1.2.1.31.1.1.1.1.2 = STRING: "switch0"
iso.3.6.1.2.1.31.1.1.1.1.3 = STRING: "imq0"
iso.3.6.1.2.1.31.1.1.1.1.4 = STRING: "eth0" #WAN NBN
iso.3.6.1.2.1.31.1.1.1.1.5 = STRING: "eth1" #WAN 4G backup
iso.3.6.1.2.1.31.1.1.1.1.6 = STRING: "eth2"
iso.3.6.1.2.1.31.1.1.1.1.7 = STRING: "eth3"
iso.3.6.1.2.1.31.1.1.1.1.8 = STRING: "eth4"

I duplicated your sensors for my WAN interfaces, made a real mess a few times and then fixed it. Final config:

- platform: snmp
  name: 'ERX NBN WAN In'
  host: 10.1.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 NBN WAN Out'
  host: 10.1.1.1
  baseoid: 1.3.6.1.2.1.31.1.1.1.10.4
  community: 'public'
  version: '2c'
  scan_interval: 10
- platform: statistics
  name: 'ERX NBN WAN In Stats'
  entity_id: sensor.erx_nbn_wan_in
  sampling_size: 4
  max_age:
    hours: 24
- platform: statistics
  name: 'ERX NBN WAN Out Stats'
  entity_id: sensor.erx_nbn_wan_out
  sampling_size: 4
  max_age:
    hours: 24
- platform: template
  sensors:
    nbn_internet_in_mbps:
      value_template: "{{ (state_attr('sensor.erx_nbn_wan_in_stats_mean','change_rate')|float*8*(state_attr('sensor.erx_nbn_wan_in_stats_mean', 'sampling_size')-1)/1000000)|round(2) }}"
      unit_of_measurement: 'MBps'
      entity_id: sensor.erx_nbn_wan_in_stats_mean
    nbn_internet_out_mbps:
      value_template: "{{ (state_attr('sensor.erx_nbn_wan_out_stats_mean','change_rate')|float*8*(state_attr('sensor.erx_nbn_wan_out_stats_mean', 'sampling_size')-1)/1000000)|round(2) }}"
      unit_of_measurement: 'MBps'
      entity_id: sensor.erx_nbn_wan_out_stats_mean

- platform: snmp
  name: 'ERX 4G WAN In'
  host: 10.1.1.1
  baseoid: 1.3.6.1.2.1.31.1.1.1.6.5
  community: 'public'
  version: '2c'
  scan_interval: 10
- platform: snmp
  name: 'ERX 4G WAN Out'
  host: 10.1.1.1
  baseoid: 1.3.6.1.2.1.31.1.1.1.10.5
  community: 'public'
  version: '2c'
  scan_interval: 10
- platform: statistics
  name: 'ERX 4G WAN in Stats'
  entity_id: sensor.erx_4g_wan_in
  sampling_size: 4
  max_age:
    hours: 24
- platform: statistics
  name: 'ERX 4G WAN out Stats'
  entity_id: sensor.erx_4g_wan_out
  sampling_size: 4
  max_age:
    hours: 24
- platform: template
  sensors:
    4g_internet_in_mbps:
      value_template: "{{ (state_attr('sensor.erx_4g_wan_in_stats_mean','change_rate')|float*8*(state_attr('sensor.erx_4g_wan_in_stats_mean', 'sampling_size')-1)/1000000)|round(2) }}"
      unit_of_measurement: 'MBps'
      entity_id: sensor.erx_4g_wan_in_stats_mean
    4g_internet_out_mbps:
      value_template: "{{ (state_attr('sensor.erx_4g_wan_out_stats_mean','change_rate')|float*8*(state_attr('sensor.erx_4g_wan_out_stats_mean', 'sampling_size')-1)/1000000)|round(2) }}"
      unit_of_measurement: 'MBps'
      entity_id: sensor.erx_4g_wan_out_stats_mean

Thanks Heaps for this.

Screenshot_2019-08-22%20Home%20Assistant

6 Likes

Hey guys, I know this is an ancient thread, but would like to know if it’s possible to make this per client bandwidth?

I’d like to monitor my TV for example to trigger automations when I start streaming netflix…

Thanks
@tom_l @seidler

You cannot do that at the router level - the router reports (via SNMP) traffic statistics only at the interface level.

You might be able to do that if your TV is on a wired connection, and you have a switch that can report utilization on the interface connected to the TV (via SNMP).

2 Likes

Thank you, my TV is on a wired connection to a Unifi USG.
In the controller there is “Activity” under “statistics” when I click on the TV which is supposed to show me the bandwidth/throughput but it’s always showing as 0bps for some reason for any/all clients

Unifi only shows the bandwidth at the switch level anyway, so without a USW these numbers will always be 0. I can check on my switch if I can get bandwidth per port from it via SNMP, but I wouldn’t think it does that.

Yes, the USW reports counters per port, so if you have a USW you can use this plugin to monitor traffic on the switch port your TV is connected to. Other option is to put it on a separate VLAN, because that will become a new interface in the USG and that will report separate numbers.

1 Like

Thanks @seidler

Putting the TV on a separate VLAN sounds like a good workaround.

What would be the next steps? How can I set it up so HA can trigger automations based on that VLANs change in bandwidth? Also most importantly I don’t know the first thing about obtaining the OIDs for the VLAN

Thank you!

I’m struggling to find a way to put a wired client on a VLAN without having a managed switch…?

This stopped working for me in version 0.98
Anyone else having issues?

Stat sensors were renamed and will need adjusting in the templates. Check your Devloper Tools states menu for the new names.

E.g. for me, this

sensor.erx_nbn_wan_in_stats_mean

Became:

sensor.erx_nbn_wan_in_stats
3 Likes

thank you!

@tom_l Can you give me a example for your lovelace cards? i like your min max and current…

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+.