Startseite | Kategorien: Heimautomatisierung - Netzwerk

Performance von FHEM verbessern, Troubleshooting

Das Heimautomatisierungswerkzeug meiner Wahl, FHEM, ist sehr mächtig. Einerseits hat man eine große Auswahl an Modulen und Funktionen, andererseits belastet jedes weitere Device den Kern von FHEM, und kann zu Verzögerungen bei der Abarbeitung von Befehlen führen. Eine über mittlerweile zwei Jahre gewachsene Installation schleppt dabei unter umständen viele Altlasten mit sich herum, die durch modernere Module abgelöst wurden. Im Folgenden Beitrag möchte ich meine Erfahrungen teilen und Tipps geben, wie ihr eure Installation optimieren könnt.

Probleme mit meiner FHEM-Installation

Meine Installation ist ständig gewachsen, ich nutze FHEM mittlerweile mit 1-Wire, Homematic, Max!, Intertechno-Funksteckdosen, dblog und Multimedia-Modulen wie z.B. das Squeezebox Modul. Hierbei kommt man mittelfristig an Problemen nicht vorbei. Ein Problem über welches man auch im FHEM-Forum häufiger stolpert ist das disconnecten des HMLAN-Adapters. Hier ein Beispiel aus meiner Logfile:

2014.02.05 10:18:04 1: HMLAN_Parse: hmlan new condition ok
2014.02.05 10:18:02 1: HMLAN_Parse: hmlan new condition init
2014.02.05 10:18:02 1: hmlan:1000 reappeared (hmlan)
2014.02.05 10:18:02 1: HMLAN_Parse: hmlan new condition disconnected
2014.02.05 10:18:02 1: hmlan:1000 disconnected, waiting to reappear
2014.02.05 10:16:42 1: HMLAN_Parse: hmlan new condition ok
2014.02.05 10:16:38 1: HMLAN_Parse: hmlan new condition init
2014.02.05 10:16:38 1: hmlan:1000 reappeared (hmlan)
2014.02.05 10:16:38 1: HMLAN_Parse: hmlan new condition disconnected
2014.02.05 10:16:38 1: hmlan:1000 disconnected, waiting to reappear
2014.02.05 10:14:47 1: HMLAN_Parse: hmlan new condition ok
2014.02.05 10:14:46 1: HMLAN_Parse: hmlan new condition init
2014.02.05 10:14:46 1: hmlan:1000 reappeared (hmlan)
2014.02.05 10:14:46 1: HMLAN_Parse: hmlan new condition disconnected
2014.02.05 10:14:46 1: hmlan:1000 disconnected, waiting to reappear  

Hier ist zu erkennen dass FHEM regelmäßig die Verbindung zu meinem HMLAN-Adapter verliert. Ein Problem auf Netzwerkebene kann ich ausschließen. Über dieses Thema gibt es bereits diverse Threads im FHEM-Forum (1, 2, 3, um nur einige zu nennen). Festhalten kann man dass es sich hierbei in der Regel um Performanceprobleme handelt (bspw. weil FHEM auf zu langsamer Hardware wie z.B. einer Fritzbox ausgeführt wird, oder die Hardware mit anderen Sachen zu viel zu tun hat).

Ein weiteres Problem an meiner Installation sind lange Ladezeiten des Webinterfaces. Bis vor kurzem hatte ich FHEM auf einem RaspberryPi installiert. Für FHEM ist der Pi absolut ausreichend, sobald hier jedoch, wie in meinem Fall, auch andere Dienste drauf laufen wird es schnell eng.

Folgende Punkte haben Probleme behoben oder mir bei der Fehlersuche geholfen:

1) FHEM auf leistungsfähiger Hardware laufen lassen

Wie bereits erwähnt reicht in meinem Fall der RaspberryPi als Plattform für FHEM nicht mehr aus. Als Konsequenz habe ich mich auf die Suche nach neuer Hardware gemacht. Ein klassischer Server kommt für mich aufgrund des Stromverbrauchs nicht in Frage, daher musste wieder ein sparsamer Einplatinencomputer her, diesmal jedoch leistungsfähiger als der RaspberryPi. Auf der Suche nach dem heiligen Gral der Einplatinencomputer kommt man nicht am BeagleBoneBlack vorbei. Kostet, wenn überhaupt, nur unwesentlich mehr als der Pi, hat jedoch eine deutlich stärkere CPU. Diverse Benchmarks zeigen eine Verdopplung der Leistung im Vergleich zum Pi. Gekauft habe ich mir letzten Endes das CubieBoard2, da es 1GB Arbeitsspeicher und eine Dualcore CPU hat. Der Vorteil des RaspberryPi ist die riesige Community die um das kleine Platinchen gewachsen ist, da können weder das BBB noch das Cubieboard mithalten. Mit etwas Linux-Erfahrung sind jedoch auch diese Geräte ohne große Probleme in Betrieb zu nehmen. Gekauft habe ich mein Cubieboard2 hier, als Image nutze ich Cubian.

cubieboard2

Die Performance mit dem Cubieboard ist deutlich besser. Der durchschnittliche Load ist von 0.50 mit dem RaspberryPi auf unter 0.10 mit dem Cubieboard2 gesunken. Der Seitenaufbau geschieht spürbar schneller, vor allem SVG-Plots bauen sich blitzschnell auf.

2) Analysieren des Event-Monitors

Nehmt euch mal die Zeit und beobachtet einige Minuten den Event-Monitor. Jede Zeile die dort auftaucht löst ein Event aus. Ein Event kann wiederum bspw. ein Notify oder einen Log-Eintrag auslösen. Jedes Event bedeutet aber auch eine unter Umständen unnötige Belastung für FHEM. Ein Grundsatz für die Events sollte lauten: So viele wie nötig, so wenig wie möglich. Das bringt mich zu meinem nächsten Punkt:

3) Nutzen von event-on-change-reading

Um die Flut von Events in den Griff zu bekommen gibt uns FHEM einige Werkzeuge an die Hand: event-on-update-reading, event-on-change-reading und event-min-interval (siehe Commandref). Die meisten Module verwenden die standardisierte “readings” Aktualisierung der fhem.pl, und damit auch die oben angesprochenen Attribute. Das Mittel der Wahl sollte event-on-change-readingsein. Der Befehl set [devicename] attr event-on-change-reading .* bewirkt, dass ein Reading nur dann ein Event auslöst wenn es sich geändert hat. Dies hat jedoch auch den Effekt dass der Wert nur dann gelogged (FileLog oder dblog) wird wenn er sich verändert. Das kann dazu führen dass Plots abgeschnittene, oder sogar garkeine Kurven anzeigen, wenn für den gewählten Zeitraum keine Daten gelogged wurden.

cubieboard2

Das Attribut event-on-change-reading kann auch noch weiter spezifiziert werden, für den Fall dass nicht jedes Reading ein Event auslösen soll. Mit set [devicename] attr event-on-change-reading humidity,temperature lösen nur die beiden angegebenen Readings humidity und temperature ein Event aus wenn sie sich geändert haben, andere Readings erzeugen keine Events mehr.

Grundsätzlich kann dieses Attribut ohne weitere Nebeneffekte an jedes Device gehängt werden, eine Ausnahme ist jedoch bspw. ein Bewegungsmelder, welcher im Falle einer Bewegung immer das selbe Reading erzeugt.

Im Anschluss lohnt sich ein erneuter Blick auf den Event-Monitor. Ich konnte meine Events und Logeinträge um ca. 70% reduzieren. Das spart CPU, schont den Datenträger und spart Platz.

4) Nur das loggen was ihr wirklich braucht

Durch event-on-change-reading haben wir die Anzahl der Logeinträge schon deutlich reduziert. Mit regulären Ausdrücken kann das Logging noch weiter optimiert werden. Speziell wenn ihr diverse Anleitungen zu dblog befolgt loggt FHEM unter Umständen alles was ein Event auslöst. Meine dblog-Definition sieht folgendermaßen aus:

define myDbLog DbLog ./db.conf .*:.*(temperature|desiredTemperature|valveposition|humidity |humidity_absolute|dewpoint|tempdiff_avg_day|tempdiff).*

Damit werden die in der Definition angegebenen Readings aller Devices gelogged, sofern sie diese zur Verfügung stellen.

Um einzelne Devices oder Readings vom logging auszuschließen gibt es das Attribut DbLogExclude welches an jedes Device gehängt werden kann.

attr temp_trockner DbLogExclude temperature

Damit schließe ich das Reading temperature vom Device temp_trockner aus, obwohl es gemäß der DbLog-Definition gelogged werden sollte.

5) Nutzen des PerformanceMonitors und Apptime

Um den Performanceproblemen weiter auf die Spur zu gehen bieten sich zwei weitere Module an: PerformanceMonitor und AppTime.

Der PerformanceMonitor erzeugt einen Eintrag in der FHEM-Logfile wenn Ablaufverzögerungen von mehr als 1000ms auftreten, also FHEM in dieser Zeit “hängt". In kombination mit attr global verbose 5 (Achtung: Nun wird wirklich jede Meldung gelogged, eure FHEM-Logfile wird in kurzer Zeit stark wachsen) könnt ihr nun untersuchen welche Komponente diese Verzögerungen erzeugt.

Das zweite Modul welches ich euch ans Herz legen möchte ist Apptime. Die simple Eingabe von apptime in der Konsole von FHEM erzeugt folgende Ausgabe:

name             function    max  count    total  average maxDly

Ab jetzt beginnt AppTime seine Arbeit. Jede weitere Eingabe von apptime erzeugt eine Liste von Aufrufen und Funktionen und deren maximaler Laufzeit. Hier ein Beispiel aus meiner Installation:

                                name             function    max  count    total  average maxDly
       tmr-OWDevice_UpdateValues      HASH(0x1733290)    809      6     4790   798.33      2 HASH(0x1733290)
       tmr-OWDevice_UpdateValues      HASH(0x1732cc0)    802      7     5578   796.86      3 HASH(0x1732cc0)
       tmr-OWDevice_UpdateValues       HASH(0xc7ca98)    790      1      790   790.00      2 HASH(0xc7ca98)
       tmr-OWDevice_UpdateValues       HASH(0xda5558)    781      3     2334   778.00      2 HASH(0xda5558)
       tmr-OWDevice_UpdateValues      HASH(0x1731ae8)    763      1      763   763.00      2 HASH(0x1731ae8)
       tmr-OWDevice_UpdateValues      HASH(0x1731800)    732      1      732   732.00      2 HASH(0x1731800)
           tmr-Weather_GetUpdate       HASH(0xc3f870)    366      1      366   366.00      0 HASH(0xc3f870)
                 tmr-MAXLAN_Poll      HASH(0x16ea258)    136      6      581    96.83    415 HASH(0x16ea258)
       tmr-OWDevice_UpdateValues      HASH(0x11ad418)    112      1      112   112.00      2 HASH(0x11ad418)
                           hmlan           HMLAN_Read     87     29      100     3.45      0 HASH(0xdacb98)
                         myDbLog            DbLog_Log     83     21      530    25.24      0 HASH(0x12ac3b8); HASH(0xc3f870)
    FHEMWEB:192.168.40.199:54592              FW_Read     56      8       63     7.88      0 HASH(0x1a6aa38)
             struct_gesamtstatus        structure_Set     53      1       53    53.00      0 HASH(0x14bd350); struct_gesamtstatus; ?
           struct_alle_batterien        structure_Set     29      2       56    28.00      0 HASH(0x14bd098); struct_alle_batterien; ?
             struct_alle_fenster        structure_Set     21      2       31    15.50      0 HASH(0x12a7a80); struct_alle_fenster; ?
         tmr-SB_PLAYER_GetStatus      HASH(0x1170c28)     13      1       13    13.00      1 HASH(0x1170c28)
     tmr-PRESENCE_StartLocalScan      HASH(0x161a848)     11     12       80     6.67      2 HASH(0x161a848)
                             lms       SB_SERVER_Read     11     15       41     2.73      0 HASH(0x15f1890)
     tmr-PRESENCE_StartLocalScan      HASH(0x1827038)      8     11       72     6.55      2 HASH(0x1827038)
             tmr-SB_SERVER_Alive      HASH(0x15f1890)      8      8       42     5.25      1 HASH(0x15f1890)
              fenster_wohnzimmer              MAX_Set      6      5       10     2.00      0 HASH(0xcbc030); fenster_wohnzimmer; ?

Was bedeuten die Werte in dieser Anzeige? Dafür möchte ich gerne Martin aus dem FHEM-Forum zitieren:

name : entity, für die es ausgeführt wird
funktion: name der Funktion, die ausgeführt wird
param max call: input parameter an die Funktion beim längsten aufruf
max: maximale laufzeit in ms
count: anzahl der Aufrufe
total: accumulierte Laufzeit der Funtion in ms
average: durchschnittliche Laufzeit (total/count) in ms. 

wenn 'tmr-' vor dem Namen steht ist es durch einen timer (InternalTimer) aufgerufen worden. 
Bei timern es etwas anders. Da ist der 
name : Funktion 
funktion: parameter der Funktion
param max call: parameter der Funktion

Für nicht-programmierer erst mal schwere Kost. Die wichtigste Spalte in der Ausgabe ist max, nach der die Ausgabe in absteigender Reihenfolge auch schon sortiert ist. Werte über 1000ms sollten genauer betrachtet werden. Wurde die betroffene Funktion häufig aufgerufen (siehe count)? Dann besteht Handlungsbedarf!

6) Vermeidung von Net::Ping

Um weitere Aktionen zu triggern erfasse ich den Status diverser Netzwerkgeräte, wie zum Beispiel den meines AV-Receivers. Ist er an, wird (abhängig von der Tageszeit/dem Sonnenstand) zusätzlich Licht eingeschaltet und mein Sat-Receiver geweckt. Hierfür habe ich seinerzeit eine Funktion geschrieben welche Net::Ping nutzt (siehe Wiki). Dies kann jedoch zu einem Stillstand von FHEM über mehrere Sekunden führen (da sind wir wieder bei der Fehlersuche aufgrund der HMLAN-disconnects).

Für das pingen von Netzwerkgeräten bietet sich mittlerweile das Presence-Modul an (Link zum Wiki, Link zur Commandref). Hierdurch entstehen keine Verzögerungen mehr.

Folgendes Beispiel überprüft alle 30 Sekunden ob ein Netzwerkgerät anpingbar ist:

define iPhone PRESENCE lan-ping 192.168.179.21

Fazit

Das Optimieren der Heimautomatisierung ist ein ständiger Begleiter, welcher auch viel Zeit in Anspruch nehmen kann. Mir persönlich macht es jedoch Spaß nach weiterem Optimierungspotenzial zu suchen. Problemlos ist meine Installation leider immer noch nicht. Der Performancemonitor meldet sich regelmäßig, auch mit Werten jenseits der 5 Sekunden. Vielleicht muss ich die Ursache nicht nur bei FHEM suchen, sondern auch bei den anderen Diensten die auf meinem Cubieboard2 laufen.

© 2014 by chanoa.de | Impressum