Lüfter beim ZyXEL NBG7815 (Armor G5) unter OpenWRT automatisch ansteuern

Seit einiger Zeit schon verwende ich einen ZyXEL NBG7815 Router („Armor G5“) als Access Point mit OpenWRT, da ich diesen sehr günstig bekommen konnte. Der ZyXEL besitzt zwar einen Qualcomm-SOC (IPQ8074A), wird aber dennoch unterstützt. Natürlich mit der üblichen Einschränkung, dass die proprietäre NSS-Engine des SOCs nicht unterstützt wird, wodurch NAT, Routing, etc. nicht in Hardware beschleunigt werden können – für den Betrieb als Access Point fällt das aber nicht ins Gewicht. Wer den Armor G5 tatsächlich als Router benutzen möchte, dem empfehle ich allerdings den NSS-Build von asvio auf GitHub. Für mich bringt dieser Build hingegen sogar primär Nachteile, da die VLAN-Konfiguration mit NSS nicht bzw. nur mit einem Workaround funktioniert und man natürlich für Updates auf die Maintainer des NSS-Builds angewiesen ist.

Ein weiteres Problem hat das Standard-OpenWRT mit dem Armor G5 noch, und zwar besitzt der Router einen kleinen Lüfter, der von OpenWRT allerdings nicht angesteuert wird. Den Lüfter braucht er auch durchaus, wenn die CPU beansprucht wird. Das ist bei der Verwendung als AP zwar tendenziell wenig der Fall, aber dennoch war mir nicht richtig wohl dabei, dass die CPU sich ohne den Lüfter auch bei geringer Last bei >85 °C einpendelt. Der oben verlinkte NSS-Build löst dieses Problem, indem er den Lüfter ansteuert. Wer aber wie ich lieber beim Standard-OpenWRT bleiben möchte, der kann die Lüftersteuerung auch einfach per Skript implementieren – und genau darum soll es heute gehen.

Dieser Guide bezieht sich auf die OpenWRT-Version 24.10.2, sollte aber auch bei zukünftigen Versionen funktionieren. Zunächst müsst ihr ein Paket installieren, mit dem das Skript den Lüfter über die entsprechende GPIO-Schnittstelle ansteuern kann – verbindet euch hierfür per SSH mit dem Router:

opkg update
opkg install gpiod-tools

Mithilfe von gpioinfo könnt ihr anschließend die verfügbaren Schnittstellen auflisten, was allerdings wenig hilfreich ist. Glücklicherweise wurde bereits von findigen Nutzern des OpenWRT-Forums herausgefunden, dass der Lüfter die Zeile 21 ist. Mit dieser Information können wir nun in /etc/init.d ein Skript anlegen, ich habe es fancontrol genannt:

#!/bin/sh /etc/rc.common

START=96
STOP=10

CHIP="gpiochip0"
LINE=21

# Messintervall und Schwellenwerte für Lüfter an bzw. aus
INTERVAL=10       # Sek.
ON_THRESHOLD=76000   # 76 °C
OFF_THRESHOLD=70000  # 70 °C

start() {
  FAN_STATE=0     # 0=aus, 1=an
  (
    while true; do
      temp=$(cat /sys/class/thermal/thermal_zone9/temp) #Temperatursensor abfragen

      if [ "$FAN_STATE" -eq 0 ] && [ "$temp" -ge "$ON_THRESHOLD" ]; then
        gpioset -t0 -c "$CHIP" "$LINE"=1 >/dev/null 2>&1
        FAN_STATE=1
      elif [ "$FAN_STATE" -eq 1 ] && [ "$temp" -le "$OFF_THRESHOLD" ]; then
        gpioset -t0 -c "$CHIP" "$LINE"=0 >/dev/null 2>&1
        FAN_STATE=0
      fi

      sleep "$INTERVAL"
    done
  ) &
  echo $! > /var/run/fancontrol.pid
}

stop() {
  kill "$(cat /var/run/fancontrol.pid)" 2>/dev/null || true
  gpioset -t0 -c "$CHIP" "$LINE"=0 >/dev/null 2>&1
}

Um zu verhindern, dass der Lüfter sich permanent an- und wieder ausschaltet, habe ich eine sog. Hysterese implementiert, bei welcher die An- bzw. Abschalttemperatur des Lüfters 6 °C auseinander liegt, hier im Beispiel 76 °C für das Aktivieren des Lüfters und 70 °C für das Abschalten. Ich empfehle, dass ihr diese Werte für eure konkreten Begebenheiten testet und bei Bedarf anpasst. Die CPU-Temperatur könnt ihr im Terminal ganz einfach mit dem folgenden Befehl abfragen, der auch gleich das Umrechnen in Grad Celsius übernimmt:

awk '{ printf "%.1f°C\n", $1/1000 }' /sys/class/thermal/thermal_zone9/temp

Als Temperatur habe ich mir den „Cluster“-Wert ausgesucht, der die gemittelte Temperatur der 4 CPU-Kerne ausgeben sollte. Ihr könnt aber bei Bedarf auch einen anderen Wert wählen, der folgende Snippet gibt euch alle Temperaturwerte des SOCs aus:

for zone in /sys/class/thermal/thermal_zone*; do
  [ -f "$zone/temp" ] || continue
  typ=$(cat "$zone/type" 2>/dev/null)
  t=$(cat "$zone/temp")
  echo "$(basename "$zone") ($typ): $((t/1000))°C"
done

Habt ihr das gemacht und seid mit den eingestellten Schwellenwerten zufrieden, könnt ihr den Service aktivieren und anschließend starten:

chmod +x /etc/init.d/fancontrol
/etc/init.d/fancontrol enable
/etc/init.d/fancontrol start

Damit sollte der Lüfter dann basierend auf der Temperatur des SOCs aktiviert bzw. deaktiviert werden. Leider ist der Lüfter ja gut hörbar, also könnt ihr leicht kontrollieren, ob alles wie gewünscht funktioniert – unglücklicherweise war ich nicht in der Lage, den tatsächlichen Status des Lüfters per gpioget abzufragen, da dies unabhängig vom Status immer „inactive“ zurückgab.

Das war’s schon! Damit sollte euer Router einen deutlich kühleren Kopf bewahren.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden.