OpenWRT & Home Assistant: auswerten-visualisieren-reagieren

 

Der Zugriff im eigenen Netzwerk findet meist zentral über den Router statt, entsprechend können über dessen Daten bestimmte Rückschlüsse gezogen werden. Die Daten eines OpenWRT-Routers können neben der Auslastung des Internetzugangs oder der einzelnen Interfaces auch Aufschluss über den Status bestimmter Geräte geben. Als Beispiel kann der Anwesenheitsstatus bestimmter Geräte im WLAN über den Device-Tracker erfasst werden. Mittels collectd und mqtt ist es zudem möglich die CPU und RAM-Auslastung sowie die aktuelle Bandbreite einzelner Interfaces auszulesen. Nachdem ich mehrere OpenWrt-Geräte als Access-Points für ein gemeinsames WLAN verwende, bietet Home Assistant die Möglichkeit die Leistungsdaten der einzelnen Geräte in einer Übersicht darzustellen.

Device-Tracker

Wie bereits erwähnt, listet der Device-Tracker den Anwesenheitsstatus aller Netzwerkgeräte. Voraussetzung für den Device-Tracker ist das OpenWrt-Paket: luci-mod-rpc, siehe: Home-Assistant-Integrationen.

Seitens Home-Assistant kann der Device-Tracker in der configuration.yaml-Datei hinzugefügt werden.

Leistungsdaten und Bandbreite -> Collectd -> MQTT -> HA

OpenWrt kann dessen Leistungsdaten mit dem Collectd-Deamon sammeln und laut dem folgenden Beispiel an einen MQTT-Broker senden, welcher die Daten in Home Assistant zur Verfügung stellt.

Setup OpenWrt

Nachdem das Einrichten von MQTT am Router über einen SSH-Zugang erfolgt, habe ich die notwendigen Pakete nicht in der GUI, sondern auch in der SSH-Session mit opkg install aktiviert.

Zunächst habe ich dazu mittels Putty eine Verbindung auf die IP-Adresse des ersten OpenWrt-Gerätes aufgebaut:

Im Terminal können die Pakete dann mit folgendem Befehl installiert werden:

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

Im Anschluss habe in der GUI über Statistics und Setup den Pfad des collectd-Deamon auf "/etc/collectd" angepasst:

Damit die Einstellungen auch im Backup vorhanden sind, habe ich den Pfad für conf.d auf einen Ordner unterhalb von /etc/config angepasst:

 

Interfaces:

RRDTool Output

Zurück ins Terminal benötigen wir als Ziel für die Statistikdaten den MQTT-Endpunkt, welcher in der mqtt.conf-Datei hinterlegt werden kann:

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

Die mqtt.conf-Datei habe ich mit folgendem Inhalt befüllt:

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

Natürlich muss die IP-Adresse des MQTT-BROKER, der Benutzername und das Passwort für die Verbindung angepasst werden.

Nach einem Neustart des OpenWrt-Routers können wir ab diesem Zeitpunkt in Home-Assistant bereits bestimmte Daten anzeigen lassen. Dazu in die Einstellungen der MQTT-Integration:

auf "Konfigurieren"

Mittels "Anhören von" und dem konfigurierten Thema: "collectd/OpenWrt/#" können die übermittelten Daten angezeigt werden:

Für die Verwendung in Home-Assistant als Entitäten habe ich die Topics in der configuration.yaml-Datei angelegt und mittels "value_template" aufbereitet. Hier ein Auszug aus meiner configuration.yaml-Datei für den Main-Router. Meine zusätzlichen Access-Points habe ich der einfachheitshalber weggelassen.

[+]
# 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

kurz getestet: HACS Integration

Nachdem für OpenWrt eine Custom HACS-Integration existiert, habe ich diese auch kurz getestet, leider werden für meinen Router: WRT3200 nur einige wenige Counter zur Verfügung gestellt: https://github.com/kvj/hass_openwrt. Im Gegensatz zu der hier beschriebenen MQTT-Anbindung verbindet sich Home Assistant aktiv auf das OpenWrt-Gerät, wofür am Router ein eigener Benutzer und Berechtigungen verwendet werden:

Zunächst werden für die erwähnte HACS-Integration auf dem OpenWrt folgende Pakete benötigt:

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

Zudem wird eine Datei mit Namen hass.json auf dem Router vorausgesetzt:

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

Inhalt:

[+]
{
  "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"]
      }
    }
  }
}

Für die Verbindung auf den Router kann ein eigener Benutzer angelegt werden:

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

Damit der User die notwendigen Rechte besitzt, habe ich die letzte Zeile der folgenden Dateien angepasst:

Datei: /etc/passwd:

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

Datei: /etc/shadow

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

Zuletzt habe ich die Datei /etc/config/rpcd wie folgt angepasst:

[+]
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 kann das Repository heruntergeladen und die Integration hinzugefügt werden:

  

 

   

Fazit

Sowohl OpenWrt als auch Home Assistant sind zwei Systeme die auf offene Standards setzen. Dadurch können als Beispiel die Leistungsdaten des Routers und der AccessPoints in Home Assistant visualisiert, oder der Anwesenheitsstatus einzelner WLAN-Geräte für bestimmte Automatisierungen verwendet werden.

positive Bewertung({{pro_count}})
Beitrag bewerten:
{{percentage}} % positiv
negative Bewertung({{con_count}})

DANKE für deine Bewertung!

Fragen / Kommentare


Durch die weitere Nutzung der Seite stimmst du der Verwendung von Cookies zu Mehr Details