OpenWRT & Home Assistant: evaluate, visualize, automate

 

Access in your own network usually takes place centrally via the router, so certain conclusions can be drawn about its data. In addition to the utilization of the Internet access or the individual interfaces, the data from the OpenWRT router can also provide information about the status of certain devices. For example, the presence status of certain devices in the WiFi can be recorded via the device tracker. Using collectd and mqtt it is also possible to read out the CPU and RAM usage as well as the current bandwidth of individual interfaces. After using several OpenWrt devices as access points for a common for a common WLAN, Home Assistant offers the possibility to display the performance data of the individual devices in an overview.

Device Tracker

As already mentioned, the device tracker lists the presence status of all network devices. Prerequisite for the device tracker is the OpenWrt package: luci-mod-rpc, see: Home-Assistant integrations.

On the part of Home-Assistant the device tracker can be added in the configuration.yaml file.

Performance data and bandwidth -> Collectd -> MQTT -> HA

OpenWrt can collect its performance data with the Collectd deamon and send it according to the following example to a MQTT broker, which makes the data available in Home Assistant.

Setup OpenWrt

After the setup of MQTT at the router is done via SSH access, I activated the necessary packages not in the GUI, but also in the SSH session with opkg install.

First I used Putty to connect to the IP address of the first OpenWrt device:

In the terminal, the packages can then be installed with the following command:

opkg update
opkg install collectd-mod-mqtt luci-app-statistics collectd-mod-rrdtool collectd-mod-uptime collectd-mod-conntrack collectd-mod-thermal

Afterwards, in the GUI via Statistics and Setup, I adjusted the path of the collectd-deamon to "/etc/collectd":

Back to the terminal, we need the MQTT endpoint as the destination for the statistics data, which can be stored in the mqtt.conf file:

root@OpenWrt:~# cd /etc/collectd/
root@OpenWrt:/etc/collectd# mkdir conf.d
root@OpenWrt:/etc/collectd# cd conf.d
root@OpenWrt:/etc/collectd/conf.d# vi mqtt.conf

I filled the mqtt.conf file with the following content:

LoadPlugin mqtt
<Plugin "mqtt">
  <Publish "OpenWRT">
    Host "192.168.1.5"
    Port "1883"
    User "mqtt"
    Password "???"
    ClientId "OpenWRT"
    Prefix "collectd"
    Retain true
  

Of course, the IP address of the MQTT-BROKER, the username and the password for the connection must be adjusted.

After restarting the OpenWrt router, we can already display certain data in Home-Assistant from this point on. To do this, go to the settings of the MQTT integration:

On "Configure".

By means of "Listen to" and the configured topic: "collectd/OpenWrt/#" the transmitted data can be displayed:

For use in Home-Assistant as entities, I created the topics in the configuration.yaml file and prepared them using "value_template". Here is an excerpt from my configuration.yaml file for the main router. I left out my additional access points for the sake of simplicity.

[+]
# OpenWRT collectd
mqtt:
  sensor:
   -  name: OpenWRT RAM buffered
      state_topic: collectd/OpenWrt/memory/memory-buffered
      unit_of_measurement: MB
      value_template: "{{ value.split(':')[1].split('\x00')[0] | float / 1000000 }}"
      unique_id: ram_buffered
   -  name: OpenWRT RAM free
      state_topic: collectd/OpenWrt/memory/memory-free
      unit_of_measurement: MB
      value_template: "{{ value.split(':')[1].split('\x00')[0] | float / 1000000 }}"
      unique_id: ram_free
   -  name: OpenWRT RAM cached
      state_topic: collectd/OpenWrt/memory/memory-cached
      unit_of_measurement: MB
      value_template: "{{ value.split(':')[1].split('\x00')[0] | float / 1000000 }}"
      unique_id: ram_cached
   -  name: OpenWRT RAM used
      state_topic: collectd/OpenWrt/memory/memory-used
      unit_of_measurement: MB
      value_template: "{{ value.split(':')[1].split('\x00')[0] | float / 1000000 }}"
      unique_id: ram_used

# load
   -  name: OpenWRT L1
      unit_of_measurement: load
      state_topic: collectd/OpenWrt/load/load
      value_template: "{{ value.split(':')[1] | float }}"
      unique_id: L1 
   -  name: OpenWRT L5
      unit_of_measurement: load
      state_topic: collectd/OpenWrt/load/load
      value_template: "{{ value.split(':')[2] | float }}"
      unique_id: L5 
   -  name: OpenWRT L15
      unit_of_measurement: load
      state_topic: collectd/OpenWrt/load/load
      value_template: "{{ value.split(':')[3].split('\x00')[0] | float }}"
      unique_id: L15

# wan interface
   -  name: OpenWRT wan errors
      state_topic: collectd/OpenWrt/interface-wan/if_errors
      unit_of_measurement: packets
      value_template: "{{ value.split(':')[1] | int + value.split(':')[2].split('\x00')[0] | int }}"
      unique_id: br-wan-errors
   -  name: OpenWRT wan dropped
      state_topic: collectd/OpenWrt/interface-wan/if_dropped
      unit_of_measurement: packets
      value_template: "{{ value.split(':')[1] | int + value.split(':')[2].split('\x00')[0] | int }}"
      unique_id: br-wan-dropped
   -  name: OpenWRT wan TX Mbits
      state_topic: collectd/OpenWrt/interface-wan/if_octets
      unit_of_measurement: Mbits
      value_template: "{{ value.split(':')[2].split('\x00')[0] | float * 8 / 1048576 }}"
      unique_id: br-wan-tx-transfer
   -  name: OpenWRT wan RX Mbits
      state_topic: collectd/OpenWrt/interface-wan/if_octets
      unit_of_measurement: Mbits
      value_template: "{{ value.split(':')[1] | float * 8 / 1048576 }}"
      unique_id: br-wan-rx-transfer
   -  name: OpenWRT wan packets
      state_topic: collectd/OpenWrt/interface-wan/if_packets
      unit_of_measurement: packets/s
      value_template: "{{ value.split(':')[1] | int + value.split(':')[2].split('\x00')[0] | int }}"
      unique_id: br-wan-packets

# br-lan interface
   -  name: OpenWRT br-lan errors
      state_topic: collectd/OpenWrt/interface-br-lan/if_errors
      unit_of_measurement: packets
      value_template: "{{ value.split(':')[1] | int + value.split(':')[2].split('\x00')[0] | int }}"
      unique_id: br-lan-errors    
   -  name: OpenWRT br-lan dropped
      state_topic: collectd/OpenWrt/interface-br-lan/if_dropped
      unit_of_measurement: packets
      value_template: "{{ value.split(':')[1] | int + value.split(':')[2].split('\x00')[0] | int }}"
      unique_id: br-lan-dropped
   -  name: OpenWRT br-lan TX Mbits
      state_topic: collectd/OpenWrt/interface-br-lan/if_octets
      unit_of_measurement:  Mbits
      value_template: "{{ value.split(':')[1] | float * 8 / 1048576 }}"
      unique_id: br-lan-tx-transfer
   -  name: OpenWRT br-lan RX Mbits
      state_topic: collectd/OpenWrt/interface-br-lan/if_octets
      unit_of_measurement: Mbits
      value_template: "{{ value.split(':')[2].split('\x00')[0] | float * 8 / 1048576 }}"
      unique_id: br-lan-rx-transfer
   -  name: OpenWRT br-lan packets
      state_topic: collectd/OpenWrt/interface-br-lan/if_packets
      unit_of_measurement: packets/s
      value_template: "{{ value.split(':')[1] | int + value.split(':')[2].split('\x00')[0] | int }}"

# uptime
   -  name: OpenWRT uptime
      state_topic: collectd/OpenWrt/uptime/uptime
      unit_of_measurement: days
      value_template: "{{ value.split(':')[1].split('\x00')[0] | int / 86400 | round(2) }}"
      unique_id: ap_uptime

# connections
   -  name: OpenWRT connections
      state_topic: collectd/OpenWrt/conntrack/conntrack
      unit_of_measurement: connections
      value_template: "{{ value.split(':')[1].split('\x00')[0] | int }}"
      unique_id: connections

# wifi main
   -  name: OpenWRT 5G clients
      state_topic: collectd/OpenWrt/iwinfo-wlan0/stations
      unit_of_measurement: clients
      value_template: "{{ value.split(':')[1].split('\x00')[0] | int }}"
      unique_id: ap_clients
   -  name: OpenWRT 5G TX Mbits
      state_topic: collectd/OpenWrt/interface-wlan0/if_octets
      unit_of_measurement: Mbits      
      value_template: "{{ value.split(':')[1] | float * 8 / 1048576 }}"
      unique_id: iwinfo-wlan0-tx-transfer_1
   -  name: OpenWRT 5G RX Mbits
      state_topic: collectd/OpenWrt/interface-wlan0/if_octets
      unit_of_measurement: Mbits
      value_template: "{{ value.split(':')[2].split('\x00')[0] | float * 8 / 1048576 }}"
      unique_id: iwinfo-wlan0-rx-transfer_1
   -  name: OpenWRT 2.4G clients
      state_topic: collectd/OpenWrt/iwinfo-wlan1/stations
      unit_of_measurement: clients
      value_template: "{{ value.split(':')[1].split('\x00')[0] | int }}"
      unique_id: ap_clients_2
   -  name: OpenWRT 2.4G TX Mbits
      state_topic: collectd/OpenWrt/interface-wlan1/if_octets
      unit_of_measurement: Mbits      
      value_template: "{{ value.split(':')[1] | float * 8 / 1048576 }}"
      unique_id: iwinfo-wlan1-tx-transfer_2
   -  name: OpenWRT 2.4G RX Mbits
      state_topic: collectd/OpenWrt/interface-wlan1/if_octets
      unit_of_measurement: Mbits      
      value_template: "{{ value.split(':')[2].split('\x00')[0] | float * 8 / 1048576 }}"
      unique_id: iwinfo-wlan1-rx-transfer_2

# temperature
   -  name: OpenWRT temp
      state_topic: collectd/OpenWrt/thermal-thermal_zone0/temperature
      unit_of_measurement: °C
      value_template: "{{ value.split(':')[1].split('\x00')[0] | int }}"
      unique_id: temp

briefly tested: HACS Integration

Since there is a custom HACS integration for OpenWrt, I also tested it briefly, unfortunately only a few counters are provided for my router: WRT3200: https://github.com/kvj/hass_openwrt. In contrast to the MQTT connection described here, Home Assistant actively connects to the OpenWrt device, for which a custom user and permissions are used on the router:

First, the following packages are needed for the mentioned HACS integration on the OpenWrt:

opkg install uhttpd uhttpd-mod-ubus rpcd rpcd-mod-iwinfo

In addition, a file named hass.json is required on the router:

vi /usr/share/rpcd/acl.d/hass.json

Content:

[+]
{
  "hass": {
    "description": "Home Assistant OpenWrt integraion permissions",
    "read": {
      "ubus": {
        "network.wireless": ["status"],
        "network.device": ["status"],
        "iwinfo": ["info", "assoclist"],
        "hostapd.*": ["get_clients", "wps_status"],
        "system": ["board"],
        "mwan3": ["status"]
      },
    },
    "write": {
      "ubus": {
        "system": ["reboot"],
        "hostapd.*": ["wps_start", "wps_cancel"]
      }
    }
  }
}

For the connection to the router, a separate user can be created:

opkg install shadow-useradd
useradd -r -s /bin/false hass

So that the user has the necessary rights, I have adapted the last line of the following files:

File: /etc/passwd:

hass:x:10001:10001:hass:/var:/bin/false

File: /etc/shadow

hass:x:0:0:99999:7:::

At last I adjusted the file /etc/config/rpcd as follows:

[+]
config rpcd
        option socket /var/run/ubus/ubus.sock
        option timeout 30

config login
        option username 'root'
        option password '$p$root'
        list read '*'
        list write '*'

config login
        option username 'hass'
        option password '$p$hass'
        list read hass
        list read unauthenticated
        list write hass
~

In Home Assistant, the repository can be downloaded and the integration added:

Conclusion

Both OpenWrt as well as Home Assistant are two systems that rely on open standards. This allows, for example, the performance data of the router and the access points to be visualized in Home Assistant, or the presence status of individual WLAN devices to be displayed for certain automations be used for certain automations.

positive Bewertung({{pro_count}})
Rate Post:
{{percentage}} % positive
negative Bewertung({{con_count}})

THANK YOU for your review!

Questions / Comments


(sorted by rating / date) [all comments(newest first)]

✍anonym
2024-01-13 00:19
Thank you, exactly what I was looking for.

By continuing to browse the site, you agree to our use of cookies. More Details