HM-Dis-WM55 Funk Statusanzeige: Unterschied zwischen den Versionen

Aus FHEMWiki
K (Kategorie Statusdisplay ergänzt / Gliederungsebenen angepasst)
Keine Bearbeitungszusammenfassung
Zeile 53: Zeile 53:
  set HM-Dis-WM55_Dis_01 displayWM short line2 nc nc error
  set HM-Dis-WM55_Dis_01 displayWM short line2 nc nc error
Dann wird nur das Icon getauscht oder eben nur jenes angezeigt.
Dann wird nur das Icon getauscht oder eben nur jenes angezeigt.
== dynamische Ausgaben ==
Um das Display wirkungsvoll einzusetzen ist es angebracht Texte dynamisch - abhängig von irgendwelchen Readings und Auswertungen zu erzeugen. Dies ist möglich, bedarf bei strukturierten Einbau einiges an Installation - ist aber am Ende einfacher als es anfänglich scheint. Möglichkeiten, es zu realisieren gibt es einige - hier ein Beispiel über myUtils.
=== fhemUser.cfg ===
Da im fhem.cfg kein set kommando vorkommen soll/kann sollte man ein separates File einbinden welches definiert nach Systeminitialisierung ausgeführt wird. Hierzu erzeugt man ein File fhem_user.cfg. Im normalen fhem.cfg baut man eine Zeile ein um es auszuführen:
define userCfg notify global:INITIALIZED include fhem_user.cfg
Im fhem_user.cfg stellt man nun für die beiden Buttons des display folgende Zeilen ein
set dis_01 displayWM short  line1 e:{myLineA(1,0)}
set dis_01 displayWM short  line2 e:{myLineA(2,0)}
set dis_01 displayWM short  line3 e:{myLineA(3,0)}
set dis_01 displayWM short  line4 e:{myLineA(4,0)}
set dis_01 displayWM short  line5 e:{myLineA(5,0)}
set dis_01 displayWM short  line6 e:{myLineA(6,0)}
                                               
set dis_01 displayWM long  line1 e:{myLineA(1,1)}
set dis_01 displayWM long  line2 e:{myLineA(2,1)}
set dis_01 displayWM long  line3 e:{myLineA(3,1)}
set dis_01 displayWM long  line4 e:{myLineA(4,1)}
set dis_01 displayWM long  line5 e:{myLineA(5,1)}
set dis_01 displayWM long  line6 e:{myLineA(6,1)}
                                               
set dis_02 displayWM short  line1 e:{myLineA(1,2)}
set dis_02 displayWM short  line2 e:{myLineA(2,2)}
set dis_02 displayWM short  line3 e:{myLineA(3,2)}
set dis_02 displayWM short  line4 e:{myLineA(4,2)}
set dis_02 displayWM short  line5 e:{myLineA(5,2)}
set dis_02 displayWM short  line6 e:{myLineA(6,2)}
                                               
set dis_02 displayWM long  line1 e:{myLineA(1,3)}
set dis_02 displayWM long  line2 e:{myLineA(2,3)}
set dis_02 displayWM long  line3 e:{myLineA(3,3)}
set dis_02 displayWM long  line4 e:{myLineA(4,3)}
set dis_02 displayWM long  line5 e:{myLineA(5,3)}
set dis_02 displayWM long  line6 e:{myLineA(6,3)}
Nun wird beim Tastendruck die Funktion myLineA gesucht - diese werden wir in 99_myUtils definieren.
=== 99_myUtils ===
Hat man evtl. schon - dann kann man es erweitern. Um es auszuführen muss es aufgerufen werden. Daher wird eine Entity in fhem.cfg definiert
define mu myUtils
nun das File 99_myUtils.pm. Die instruktionen sind in den Kommentaren. Da es flexibel ist ist es auch keine strikte Anleitung.
  ##############################################
  #
  package main;
 
  use strict;
  use warnings;
  use POSIX;
  sub myLineA ($$);
 
 
  # define counter and counterlimit per press-type
  # presstype are 0: btn1 short
  # presstype are 1: btn1 long
  # presstype are 2: btn2 short
  # presstype are 3: btn2 long
 
 
  my @cnt  ; #init one counter per press
  my @cntMax; #number of entries per press
  # structure per button/itteration/press
  # insert the function to be executes to fill the line with test, color and icon
  # Number of itterations can be extended as desired. At least one should be present.
  # obey the end of the line (is open) and the number of parameters you send to the funktion
  my %lineArr = (0 =>{#============Btn Type 0: Btn1 short
                      0 =>{#-------itteration 0
                            1=>'{myTh("wz:","h_s_s2",'    #  line 1
                          ,2=>'{myTh("os:","h_s_s1",'   
                          ,3=>'{myTh("op:","h_s_aussen",'
                          ,4=>'{myPr("p:" ,"h_s_aussen",'
                          ,5=>'{myTx("","","",'           
                          ,6=>'{myTx("","","",'     
                          }
                    ,1 =>{#-------itteration 1
                            1=>'{myTh("wz:","h_s_s2",'    #  line 1
                          ,2=>'{myTh("os:","h_s_s1",'   
                          ,3=>'{myTh("op:","h_s_aussen",'
                          ,4=>'{myPr("p:" ,"h_s_aussen",'
                          ,5=>'{myTx("","","",'           
                          ,6=>'{myTx("","","",'     
                          }
                    }
                ,1 =>{#============Btn Type 0: Btn1 Long
                      0 =>{#-------itteration 0
                            1=>'{myTx("Info","green"        ,"info" ,'    #  line 1
                          ,2=>'{myHm("act:","I_actTotal"  ,"green",'
                          ,3=>'{myHm("bat:","I_sum_battery","green",'
                          ,4=>'{myHm("fl:" ,"I_fail"      ,"green",'     
                          ,5=>'{myTx(""    ,""            ,""    ,' 
                          ,6=>'{myTx(""    ,""            ,""    ,' 
                          }                                                       
                    ,1 =>{#-------itteration 0
                            1=>'{myTx(        "Error"        ,"red","error",'    #  line 1
                          ,2=>'{myHm("prt:" ,"ERR__protocol","red"  ,'           
                          ,3=>'{myHm("bat:" ,"ERR_battery"  ,"yellow",'
                          ,4=>'{myHm("prt:" ,"W__protocol"  ,"yellow",'           
                          ,5=>'{myTx(""    ,""            ,"",' 
                          ,6=>'{myTx(""    ,""            ,"",' 
                          }                                                       
                    }
                ,2 =>{#============Btn Type 2: Btn2 short
                      0 =>{#-------itteration 0
                            1=>'{myRT("ca:","h.caro.Clima",'#  line 1
                          ,2=>'{myRT("lg:","h.lnge.Clima",'
                          ,3=>'{myRT("fh:","h.fsth.Clima",'
                          ,4=>'{myRT("du:","h.dact.Clima",'
                          ,5=>'{myRT("bs:","h.bad.Clima",'
                          ,6=>'{myTx(""  ,""          ,"",' 
                          }
                    }
                ,3 =>{#============Btn Type 3: Btn2 Long
                      0 =>{#-------itteration 0
                            1=>'{myLi("Fl:","LichtF"        ,'
                          ,2=>'{myLi("Fh:","LichtFH"        ,'
                          ,3=>'{myLi("L1:","LichtL"        ,'
                          ,4=>'{myLi("Sl:","sw_Sw"          ,'
                          ,5=>'{myLi("L2:","LichtL_Sw1_V_01",'
                          ,6=>'{myLi("L3:","LichtL_Sw1_V_02",'
                          }                                                       
                    ,1 =>{#-------itteration 1
                            1=>'{myTx("off"  ,"","off"  ,'
                          ,2=>'{myTx("on"    ,"","on"    ,'
                          ,3=>'{myTx("open"  ,"","open"  ,'
                          ,4=>'{myTx("closed","","closed",'
                          ,5=>'{myTx("error" ,"","error" ,'
                          ,6=>'{myTx("ok"    ,"","ok"    ,'
                          }                                                       
                    ,2 =>{#-------itteration 2
                            1=>'{myTx("info"      ,"white" ,"info"      ,'
                          ,2=>'{myTx("newMsg"    ,"red"  ,"newMsg"    ,'
                          ,3=>'{myTx("serviceMsg","orange","serviceMsg",'
                          ,4=>'{myTx("sigGreen"  ,"yellow","sigGreen"  ,'
                          ,5=>'{myTx("sigYellow" ,"green" ,"sigYellow" ,'
                          ,6=>'{myTx("sigRed"    ,"blue"  ,"sigRed"    ,'
                          }                                                       
                    }
    );
 
 
  sub myUtils_Initialize($$) {
    my ($hash) = @_;
 
  # Normal devices
    $hash->{DefFn}  = "myUtil_Define";
    $hash->{UndefFn} = "myUtil_Undef";
    $hash->{AttrList}= $readingFnAttributes;
   
    @cntMax = (scalar keys %{$lineArr{0}}
              ,scalar keys %{$lineArr{1}}
              ,scalar keys %{$lineArr{2}}
              ,scalar keys %{$lineArr{3}});
    push @cnt,"0" foreach (keys %lineArr);
  }
  sub myUtil_Define($$) {########################################################
    my ($hash, $def) = @_;
    return ;
  }
  sub myUtil_Undef($$) {#########################################################
    my ($hash, $arg) = @_;
    return undef;
  }
 
  sub myLineA($$){# main entry - do not change!!!
    my ($line,$type) = @_;
    $cnt[$type] = ($cnt[$type] +1)%$cntMax[$type] if ($line == 1); # rotate counter per type
 
    return (eval $lineArr{$type}{$cnt[$type]}{$line}.'"t")}'
          ,eval $lineArr{$type}{$cnt[$type]}{$line}.'"c")}'
          ,eval $lineArr{$type}{$cnt[$type]}{$line}.'"i")}'
          );
  }
  sub myRT($$$){ # function to return information of an RT.
    # line 't' calculates the text
    # line 'c' calculates the color
    # line 'i' calculates the icon
    my ($p,$e,$t) = @_;
    if($t eq "t"){return $p.ReadingsVal($e,"desired-temp","no")."-".ReadingsVal($e,"measured-temp","no");  }
    if($t eq "c"){return    ReadingsVal($e,"measured-temp",0)>20 ? "red" : "blue" }
    if($t eq "i"){return    ReadingsVal($e,"ValvePosition",0)    ? "on"  : "off"  }
    return "nix";
  }
  sub myTh($$$){#temp sensor
    my ($p,$e,$t) = @_;
    if($t eq "t"){return $p.ReadingsVal($e,"temperature","no")."-".ReadingsVal($e,"humidity","");  }
    if($t eq "c"){return    ReadingsVal($e,"temperature",0)>20 ? "red" : "blue" }
    if($t eq "i"){return    ReadingsVal($e,"battery",0)    ? "ok"  : "no"  }
    return "nix";
  }
  sub myPr($$$){#Sensor Pressure
    my ($p,$e,$t) = @_;
    if($t eq "t"){return $p.ReadingsVal($e,"pressure","no")."-".ReadingsVal($e,"luminosity","-");  }
    if($t eq "c"){return    ReadingsVal($e,"luminosity",0)>1000 ? "green" : "red" }
    if($t eq "i"){return    ReadingsVal($e,"battery",0)        ? "ok"  : "no"  }
    return "nix";
  }
  sub myLi($$$){#Light
    my ($p,$e,$t) = @_;
    if($t eq "t"){return $p.ReadingsVal($e,"state","xx");  }
    if($t eq "c"){return    ReadingsVal($e,"timedOn",0) eq "off" ? "green" : "red" }
    if($t eq "i"){return    ReadingsVal($e,"phyLevel",ReadingsVal($e,"level","1")) ? "on"  : "off"  }
    return "nix";
  }
  sub myTx($$$$){#text only
    my ($p,$c,$icon,$t) = @_;
    if($t eq "t"){return $p;  }
    if($t eq "c"){return ($c?$c:"white");}
    if($t eq "i"){return ($icon?$icon:"noIcon");}
    return $p;
  }
  sub myHm($$$$){#HMInfo readings
    my ($p,$e,$c,$t) = @_;
    if($t eq "t"){return $p.join(",", grep !/:0/
                                    , map{s/^(.).*?:/$1:/;;$_;;}
                                      split ","
                                    , ReadingsVal("hm",$e,"-"))
                }
    if($t eq "c"){return ($c?$c:"white");}
    if($t eq "i"){return "noIcon";}
    return $p;
  }
 
  1;
Die Definition, was angezeigt werden soll wird nun in der Struktur %lineArr festgelegt.
Die Typen der Ausgaben - z.B. Darstellung eines Werts eines RT - wird in der jeweiligen Funktion "myTh" festgelegt. Hier kann man so viele - nach den gleichen Regeln wie die Erste - definieren und in der Struktur nutzen.
In der Struktur werden die Namen der auszuwertenden Entities eingetragen.
Mit den Einträgen zur Itteration kann man erreichen dass beim Tastendruck der Text alterniert. Beim ersten Druck eine Seite, beim 2. eine weitere, nach der Letzten wieder die Erste.


== Links ==
== Links ==

Version vom 25. Mai 2015, 19:05 Uhr

HM-Dis-WM55

HomeMatic Funk-Statusanzeige WM55

Features

Technische Daten:

  • Farbiges OLED-Display mit 128 x 128 RGB-Bildpunkten
  • Frei programmierbar über HomeMatic-WebUI
  • Dynamische Zuweisung von Anzeigeplätzen, Texten, Zustand von Systemvariablen, Symbolen
  • In den Anzeigerahmen integrierte Taster für Anmeldung, Seitenfortschaltung und Auslösen von Zentralenprogrammen, z. B. Abfrage von Fensterzuständen bei Verlassen des Hauses
  • Nur 19 mm flach, Schraub- oder Klebmontage, ortsunabhängiger Batteriebetrieb
  • Lieferung mit weißem Rahmen, alternativ integrierbar in 55-mm-Installationsrahmen zahlreicher Installationsserien (Berker, ELSO, GIRA, merten, JUNG)

Allgemeines

Die Funk-Statusanzeige hat 10 Kanäle (HM-Dis-WM55_Dis_01 bis HM-Dis-WM55_Dis_10). Jedem der Kanäle können 2 Texte zugewiesen werden. Kanal 1 und 2 kommt eine Doppelrolle zu. Sie enthalten sowohl Texte, sind aber auch die beiden Tasten. Und so wird auch die Ausgabe der Displayanzeige auf diese beiden Kanäle gegeben.

Das Display hat 6 Zeilen zur Darstellung.

Die Zeilen können einzeln befüllt und getauscht werden, dies muss nicht in einem Rutsch passieren.

Probleme

Es gibt hin und wieder Probleme die Register auszulesen. Abhilfe ist msgrepeat auf 3 zu setzten und hartnäckig bleiben.

Betrieb mit FHEM

Das Gerät wird zur Zeit experimentell unterstützt. msgrepeat sollte auf 3 gestellt werden, sonst gibt es öfters Timeouts:

attr HM-Dis-WM55 msgRepeat 3

Die Kanäle 1 und 2 sollten mit FHEM gepeered (zusätzlich zum pairing) werden

set HM-Dis-WM55_Dis_01 peerBulk <fhemID>01
set HM-Dis-WM55_Dis_02 peerBulk <fhemID>01 

Um einen Kanal mit Text zu befüllen dient der text Befehl auf einen Kanal. Es werden beide Texte in einen Kanal gleichzeitig geschrieben. Will ich einen Text tauschen muss ich den anderen mit neu setzten. Für ein Leerzeichen \_ einsetzten

set HM-Dis-WM55_Dis_01 text Fenster\_auf Fenster\_zu

zum Übernehmen der Konfiguration den Config Taster auf der Rückseite nehmen und über das Menü übernehmen

Nun kann man z.B. mit einem notify die Information an den Schalter senden, wenn ein Fenster offen und oder zu ist:

set HM-Dis-WM55_Dis_01 displayWM short line2 txt01_1 red error

short bedeutet bei einem kurzen Tastendruck (es geht auch long). line bezieht sich auf die Zeile in die es geschrieben wird. Anschließend folgt der Text, die Farbe in der der Text angezeigt werden soll, sowie das Icon.

Mit

set HM-Dis-WM55_Dis_01 displayWM help

kann eine Übersicht der gesetzten Texte angezeigt werden. Sowie der möglichen Farben und Icons.

Folgende Farben und Icons gibt es:

color is one white, red, orange, yellow, green, blue
icon is one closed, error, ic12, ic13, info, newMsg, noIcon, off, ok, on, open, serviceMsg, sigGreen, sigYellow, sigred

Soll kein Text eingeblendet werden oder dieser nicht geändert werden kann man einfach nc schreiben Beispiel

set HM-Dis-WM55_Dis_01 displayWM short line2 nc nc error

Dann wird nur das Icon getauscht oder eben nur jenes angezeigt.

dynamische Ausgaben

Um das Display wirkungsvoll einzusetzen ist es angebracht Texte dynamisch - abhängig von irgendwelchen Readings und Auswertungen zu erzeugen. Dies ist möglich, bedarf bei strukturierten Einbau einiges an Installation - ist aber am Ende einfacher als es anfänglich scheint. Möglichkeiten, es zu realisieren gibt es einige - hier ein Beispiel über myUtils.

fhemUser.cfg

Da im fhem.cfg kein set kommando vorkommen soll/kann sollte man ein separates File einbinden welches definiert nach Systeminitialisierung ausgeführt wird. Hierzu erzeugt man ein File fhem_user.cfg. Im normalen fhem.cfg baut man eine Zeile ein um es auszuführen:

define userCfg notify global:INITIALIZED include fhem_user.cfg


Im fhem_user.cfg stellt man nun für die beiden Buttons des display folgende Zeilen ein

set dis_01 displayWM short  line1 e:{myLineA(1,0)}
set dis_01 displayWM short  line2 e:{myLineA(2,0)}
set dis_01 displayWM short  line3 e:{myLineA(3,0)}
set dis_01 displayWM short  line4 e:{myLineA(4,0)}
set dis_01 displayWM short  line5 e:{myLineA(5,0)}
set dis_01 displayWM short  line6 e:{myLineA(6,0)}
                                                
set dis_01 displayWM long   line1 e:{myLineA(1,1)}
set dis_01 displayWM long   line2 e:{myLineA(2,1)}
set dis_01 displayWM long   line3 e:{myLineA(3,1)}
set dis_01 displayWM long   line4 e:{myLineA(4,1)}
set dis_01 displayWM long   line5 e:{myLineA(5,1)}
set dis_01 displayWM long   line6 e:{myLineA(6,1)}
                                                
set dis_02 displayWM short  line1 e:{myLineA(1,2)}
set dis_02 displayWM short  line2 e:{myLineA(2,2)}
set dis_02 displayWM short  line3 e:{myLineA(3,2)}
set dis_02 displayWM short  line4 e:{myLineA(4,2)}
set dis_02 displayWM short  line5 e:{myLineA(5,2)}
set dis_02 displayWM short  line6 e:{myLineA(6,2)}
                                                
set dis_02 displayWM long   line1 e:{myLineA(1,3)}
set dis_02 displayWM long   line2 e:{myLineA(2,3)}
set dis_02 displayWM long   line3 e:{myLineA(3,3)}
set dis_02 displayWM long   line4 e:{myLineA(4,3)}
set dis_02 displayWM long   line5 e:{myLineA(5,3)}
set dis_02 displayWM long   line6 e:{myLineA(6,3)}

Nun wird beim Tastendruck die Funktion myLineA gesucht - diese werden wir in 99_myUtils definieren.

99_myUtils

Hat man evtl. schon - dann kann man es erweitern. Um es auszuführen muss es aufgerufen werden. Daher wird eine Entity in fhem.cfg definiert

define mu myUtils

nun das File 99_myUtils.pm. Die instruktionen sind in den Kommentaren. Da es flexibel ist ist es auch keine strikte Anleitung.

 ##############################################
 #
 package main;
 
 use strict;
 use warnings;
 use POSIX;
 sub myLineA ($$);
 
 
 # define counter and counterlimit per press-type
 # presstype are 0: btn1 short
 # presstype are 1: btn1 long
 # presstype are 2: btn2 short
 # presstype are 3: btn2 long
 
 
 my @cnt   ; #init one counter per press
 my @cntMax; #number of entries per press
 # structure per button/itteration/press
 # insert the function to be executes to fill the line with test, color and icon
 # Number of itterations can be extended as desired. At least one should be present.
 # obey the end of the line (is open) and the number of parameters you send to the funktion
 my %lineArr = (0 =>{#============Btn Type 0: Btn1 short
                     0 =>{#-------itteration 0
                           1=>'{myTh("wz:","h_s_s2",'    #  line 1
                          ,2=>'{myTh("os:","h_s_s1",'    
                          ,3=>'{myTh("op:","h_s_aussen",'
                          ,4=>'{myPr("p:" ,"h_s_aussen",'
                          ,5=>'{myTx("","","",'             
                          ,6=>'{myTx("","","",'      
                         }
                    ,1 =>{#-------itteration 1
                           1=>'{myTh("wz:","h_s_s2",'    #  line 1
                          ,2=>'{myTh("os:","h_s_s1",'    
                          ,3=>'{myTh("op:","h_s_aussen",'
                          ,4=>'{myPr("p:" ,"h_s_aussen",'
                          ,5=>'{myTx("","","",'             
                          ,6=>'{myTx("","","",'      
                         }
                    }
               ,1 =>{#============Btn Type 0: Btn1 Long
                     0 =>{#-------itteration 0
                           1=>'{myTx("Info","green"        ,"info" ,'    #  line 1
                          ,2=>'{myHm("act:","I_actTotal"   ,"green",'
                          ,3=>'{myHm("bat:","I_sum_battery","green",'
                          ,4=>'{myHm("fl:" ,"I_fail"       ,"green",'      
                          ,5=>'{myTx(""    ,""             ,""     ,'  
                          ,6=>'{myTx(""    ,""             ,""     ,'  
                         }                                                        
                    ,1 =>{#-------itteration 0
                           1=>'{myTx(        "Error"        ,"red","error",'    #  line 1
                          ,2=>'{myHm("prt:" ,"ERR__protocol","red"   ,'            
                          ,3=>'{myHm("bat:" ,"ERR_battery"  ,"yellow",'
                          ,4=>'{myHm("prt:" ,"W__protocol"  ,"yellow",'            
                          ,5=>'{myTx(""     ,""             ,"",'  
                          ,6=>'{myTx(""     ,""             ,"",'  
                         }                                                        
                    }
               ,2 =>{#============Btn Type 2: Btn2 short
                     0 =>{#-------itteration 0
                           1=>'{myRT("ca:","h.caro.Clima",'#  line 1
                          ,2=>'{myRT("lg:","h.lnge.Clima",'
                          ,3=>'{myRT("fh:","h.fsth.Clima",'
                          ,4=>'{myRT("du:","h.dact.Clima",'
                          ,5=>'{myRT("bs:","h.bad.Clima",' 
                          ,6=>'{myTx(""   ,""           ,"",'  
                         }
                    }
               ,3 =>{#============Btn Type 3: Btn2 Long
                     0 =>{#-------itteration 0
                           1=>'{myLi("Fl:","LichtF"         ,' 
                          ,2=>'{myLi("Fh:","LichtFH"        ,' 
                          ,3=>'{myLi("L1:","LichtL"         ,' 
                          ,4=>'{myLi("Sl:","sw_Sw"          ,' 
                          ,5=>'{myLi("L2:","LichtL_Sw1_V_01",' 
                          ,6=>'{myLi("L3:","LichtL_Sw1_V_02",' 
                         }                                                        
                    ,1 =>{#-------itteration 1
                           1=>'{myTx("off"   ,"","off"   ,'
                          ,2=>'{myTx("on"    ,"","on"    ,'
                          ,3=>'{myTx("open"  ,"","open"  ,'
                          ,4=>'{myTx("closed","","closed",'
                          ,5=>'{myTx("error" ,"","error" ,'
                          ,6=>'{myTx("ok"    ,"","ok"    ,'
                         }                                                        
                    ,2 =>{#-------itteration 2
                           1=>'{myTx("info"      ,"white" ,"info"      ,'
                          ,2=>'{myTx("newMsg"    ,"red"   ,"newMsg"    ,'
                          ,3=>'{myTx("serviceMsg","orange","serviceMsg",'
                          ,4=>'{myTx("sigGreen"  ,"yellow","sigGreen"  ,'
                          ,5=>'{myTx("sigYellow" ,"green" ,"sigYellow" ,'
                          ,6=>'{myTx("sigRed"    ,"blue"  ,"sigRed"    ,'
                         }                                                        
                    }
    );
 
 
 sub myUtils_Initialize($$) {
   my ($hash) = @_;
 
 # Normal devices
   $hash->{DefFn}   = "myUtil_Define";
   $hash->{UndefFn} = "myUtil_Undef";
   $hash->{AttrList}= $readingFnAttributes;
   
   @cntMax = (scalar keys %{$lineArr{0}}
             ,scalar keys %{$lineArr{1}}
             ,scalar keys %{$lineArr{2}}
             ,scalar keys %{$lineArr{3}});
   push @cnt,"0" foreach (keys %lineArr);
 }
 sub myUtil_Define($$) {########################################################
   my ($hash, $def) = @_;
   return ;
 }
 sub myUtil_Undef($$) {#########################################################
   my ($hash, $arg) = @_;
   return undef;
 }
 
 sub myLineA($$){# main entry - do not change!!!
   my ($line,$type) = @_;
   $cnt[$type] = ($cnt[$type] +1)%$cntMax[$type] if ($line == 1); # rotate counter per type
 
   return (eval $lineArr{$type}{$cnt[$type]}{$line}.'"t")}'
          ,eval $lineArr{$type}{$cnt[$type]}{$line}.'"c")}'
          ,eval $lineArr{$type}{$cnt[$type]}{$line}.'"i")}'
          );
 }
 sub myRT($$$){ # function to return information of an RT. 
   # line 't' calculates the text
   # line 'c' calculates the color
   # line 'i' calculates the icon
   my ($p,$e,$t) = @_;
   if($t eq "t"){return $p.ReadingsVal($e,"desired-temp","no")."-".ReadingsVal($e,"measured-temp","no");  }
   if($t eq "c"){return    ReadingsVal($e,"measured-temp",0)>20 ? "red" : "blue" }
   if($t eq "i"){return    ReadingsVal($e,"ValvePosition",0)    ? "on"  : "off"  }
   return "nix";
 }
 sub myTh($$$){#temp sensor 
   my ($p,$e,$t) = @_;
   if($t eq "t"){return $p.ReadingsVal($e,"temperature","no")."-".ReadingsVal($e,"humidity","");  }
   if($t eq "c"){return    ReadingsVal($e,"temperature",0)>20 ? "red" : "blue" }
   if($t eq "i"){return    ReadingsVal($e,"battery",0)    ? "ok"  : "no"  }
   return "nix";
 }
 sub myPr($$$){#Sensor Pressure
   my ($p,$e,$t) = @_;
   if($t eq "t"){return $p.ReadingsVal($e,"pressure","no")."-".ReadingsVal($e,"luminosity","-");  }
   if($t eq "c"){return    ReadingsVal($e,"luminosity",0)>1000 ? "green" : "red" }
   if($t eq "i"){return    ReadingsVal($e,"battery",0)        ? "ok"  : "no"  }
   return "nix";
 }
 sub myLi($$$){#Light
   my ($p,$e,$t) = @_;
   if($t eq "t"){return $p.ReadingsVal($e,"state","xx");  }
   if($t eq "c"){return    ReadingsVal($e,"timedOn",0) eq "off" ? "green" : "red" }
   if($t eq "i"){return    ReadingsVal($e,"phyLevel",ReadingsVal($e,"level","1")) ? "on"  : "off"  }
   return "nix";
 }
 sub myTx($$$$){#text only
   my ($p,$c,$icon,$t) = @_;
   if($t eq "t"){return $p;  }
   if($t eq "c"){return ($c?$c:"white");}
   if($t eq "i"){return ($icon?$icon:"noIcon");}
   return $p;
 }
 sub myHm($$$$){#HMInfo readings
   my ($p,$e,$c,$t) = @_;
   if($t eq "t"){return $p.join(",", grep !/:0/
                                   , map{s/^(.).*?:/$1:/;;$_;;} 
                                     split ","
                                   , ReadingsVal("hm",$e,"-"))
                }
   if($t eq "c"){return ($c?$c:"white");}
   if($t eq "i"){return "noIcon";}
   return $p;
 }
 
 1;

Die Definition, was angezeigt werden soll wird nun in der Struktur %lineArr festgelegt. Die Typen der Ausgaben - z.B. Darstellung eines Werts eines RT - wird in der jeweiligen Funktion "myTh" festgelegt. Hier kann man so viele - nach den gleichen Regeln wie die Erste - definieren und in der Struktur nutzen. In der Struktur werden die Namen der auszuwertenden Entities eingetragen. Mit den Einträgen zur Itteration kann man erreichen dass beim Tastendruck der Text alterniert. Beim ersten Druck eine Seite, beim 2. eine weitere, nach der Letzten wieder die Erste.


Links