Advanced SNMP monitoring, part one: Asuswrt routers (Merlin build)

I think I know why: the initial post was made with exec directive which was deprecated and extend was only added in version 384.8 https://www.asuswrt-merlin.net/changelog-382

As 380.69 is a legacy firmware (released way before 384.8) it means no extend support.

Change extend to exec in all the scripts and then run snmpwalk again to get the OIDs (the values of OIDs from my post will not work).

Well, changing extend -> exec helped - at least values can be read by snmpwalk.
Here is a csv-table with added data:

So here are my sensors:

  - platform: snmp
    host: !secret router_1_ip
    port: 161
    community: fortress
    baseoid: 1.3.6.1.2.1.25.1.8.101.1
    name: snmp_router_1_dhcp_leases
    accept_errors: true
    default_value: 0
    value_template: "{{ value | float | round(0) }}"
    version: 2c
    unit_of_measurement: ' '
    scan_interval: 60

  - platform: snmp
    host: !secret router_1_ip
    port: 161
    community: fortress
    baseoid: 1.3.6.1.2.1.25.1.9.101.1
    name: snmp_router_1_connected
    accept_errors: true
    default_value: 0
    value_template: "{{ value | float | round(0) }}"
    version: 2c
    unit_of_measurement: ' '
    scan_interval: 60

  - platform: snmp
    host: !secret router_1_ip
    port: 161
    community: fortress
    baseoid: 1.3.6.1.2.1.25.1.10.101.1
    name: snmp_router_1_24_temp
    accept_errors: true
    default_value: 0
    value_template: "{{ (((value | float) / (2 | float)) + (20 | float)) | round(0) }}"
    version: 2c
    unit_of_measurement: "\u00b0C"
    scan_interval: 60

  - platform: snmp
    host: !secret router_1_ip
    port: 161
    community: fortress
    baseoid: 1.3.6.1.2.1.25.1.11.101.1
    name: snmp_router_1_5_temp
    accept_errors: true
    default_value: 0
    value_template: "{{ (((value | float) / (2 | float)) + (20 | float)) | round(0) }}"
    version: 2c
    unit_of_measurement: "\u00b0C"
    scan_interval: 60

  - platform: snmp
    host: !secret router_1_ip
    port: 161
    community: fortress
    baseoid: 1.3.6.1.2.1.25.1.12.101.1
    name: snmp_router_1_mem_used
    accept_errors: true
    default_value: 0
    value_template: "{% set mem_total = 239524 -%}
                     {{ ((((value | replace('K','')) | float) / (mem_total | float)) * (100 | float)) | round(0) }}"
    version: 2c
    unit_of_measurement: '%'
    scan_interval: 60

  - platform: snmp
    host: !secret router_1_ip
    port: 161
    community: fortress
    baseoid: 1.3.6.1.2.1.25.1.13.101.1
    name: snmp_router_1_proc_load
    accept_errors: true
    default_value: 0
    version: 2c
    value_template: "{{ (100 - ((value  | replace('%','')) | float)) | round(2) }}"
    unit_of_measurement: '%'
    scan_interval: 60

  - platform: snmp
    host: !secret router_1_ip
    port: 161
    community: fortress
    baseoid: 1.3.6.1.2.1.25.1.15.101.1
    name: snmp_router_1_jffs_used
    accept_errors: true
    default_value: 0
    version: 2c
    value_template: "{{ ((value | replace('%','')) | float) | round(2) }}"
    unit_of_measurement: '%'
    scan_interval: 60

Notes:

  1. For “mem” sensor I used a value “239524” - total RAM of AC66U.
  2. Changed a formula for “mem” a bit.
  3. To get a proper wifi chip temperature, you must use a formula T=Tcommand / 2 +20

Thank you very much for the help!

Can someone please explain how can I implement this to the setup Petricia explained above? thanks in advance

Should we be using SNMPv2 or v3?
What are the “SNMP get community” and “set”? Should these two names be different or the same?

Screen Shot 2021-09-06 at 11.39.34 AM

I figured out a way to extend Petrica’s implementation to include wan transmit and receive speed using the script in pnakashian’s link. Mbit/s is used to match what the ASUSWRT integration. Warning, this works for me but I’m new to SNMP so please feel free to let me know if I did something wrong.

You’ll need the following 2 scripts which are almost identical except for the last line. There’s probably a more elegant way to do this with just 1 script and passing a variable but I wasn’t sure how to do that when calling the script though SNMP.

NOTE: The scripts will produce errors the first few times as they need to create /tmp/ files. This was also the case with the original script.

download.sh

#!/bin/sh

maxint=4294967295
scriptname=${0##*/}
old="/tmp/$scriptname.data.old"
new="/tmp/$scriptname.data.new"
old_epoch_file="/tmp/$scriptname.epoch.old"

old_epoch=`cat $old_epoch_file`
new_epoch=`date "+%s"`
echo $new_epoch > $old_epoch_file

interval=`expr $new_epoch - $old_epoch` # seconds since last sample

if [ -f $new ]; then
    awk -v old=$old -v interval=$interval -v maxint=$maxint '{
        getline line < old
        bytes  = $1 - line
        if(bytes < 0) {bytes = bytes + maxint}
        mbps  = (8 * (bytes) / interval) / 1024 / 1024    # mbits per second
        printf "%.2f \n", mbps
    }' $new 
    mv $new $old
fi

cat /proc/net/dev | tail -1 | tr ':|' '  ' | awk '{print $2}' > $new

upload.sh

#!/bin/sh

maxint=4294967295
scriptname=${0##*/}
old="/tmp/$scriptname.data.old"
new="/tmp/$scriptname.data.new"
old_epoch_file="/tmp/$scriptname.epoch.old"

old_epoch=`cat $old_epoch_file`
new_epoch=`date "+%s"`
echo $new_epoch > $old_epoch_file

interval=`expr $new_epoch - $old_epoch` # seconds since last sample

if [ -f $new ]; then
    awk -v old=$old -v interval=$interval -v maxint=$maxint '{
        getline line < old
        bytes  = $1 - line
        if(bytes < 0) {bytes = bytes + maxint}
        mbps  = (8 * (bytes) / interval) / 1024 / 1024     # mbits per second
        printf "%.2f\n", mbps
    }' $new
    mv $new $old
fi

cat /proc/net/dev | tail -1 | tr ':|' '  ' | awk '{print $10}' > $new

Add the following to /jffs/configs/snmpd.conf.add

extend .1.3.6.1.2.1.25.1.17 download /bin/sh /jffs/scripts/snmp/download.sh
extend .1.3.6.1.2.1.25.1.18 upload /bin/sh /jffs/scripts/snmp/upload.sh

Lastly, add this to your home assistant config

  - platform: snmp
    host: my_ip
    community: public
    baseoid: 1.3.6.1.2.1.25.1.17.3.1.1.8.100.111.119.110.108.111.97.100 # Found via snmpwalk, but looks unusually long
    name: bespin_download_speed_negative # Negative value looks better in history graph
    accept_errors: true
    default_value: 0
    version: 2c
    value_template: '-{{value | float | round (2)}}'
    unit_of_measurement: 'Mbit/s' # Use the same units as the ASUSWRT integration
    scan_interval: 15
  - platform: snmp
    host: my_ip
    community: public
    baseoid: 1.3.6.1.2.1.25.1.18.3.1.1.6.117.112.108.111.97.100 
    name: bespin_upload_speed
    accept_errors: true
    default_value: 0
    version: 2c
    value_template: '{{value | float | round (2)}}'
    unit_of_measurement: 'Mbit/s' # Use the same units as the ASUSWRT integration
    scan_interval: 15

This is tested on an ASUS RT-AX86U. If it’s not working on your router then it could be that the order of devices in /proc/net/dev is different.