Neuigkeiten:

Am Sonntag den 8.12.2024 kann es ab ca. 8:00 Uhr zu kurzzeitigen Einschränkungen / Ausfällen bei den Diensten des FHEM Vereines kommen.
Die Server müssen mal gewartet und dabei neu gestartet werden ;)

Hauptmenü

[gelöst] readingsGroup: Refresh-/Update-, Wildcard- oder Konzeptproblem

Begonnen von GaiusMarius, 15 Juli 2020, 15:03:00

Vorheriges Thema - Nächstes Thema

GaiusMarius

Eines einer langen Liste von Readings refresht sich nicht. Und ich weiß nicht, wie ich das ändern kann.

Die betreffende readingsGroup soll die Zustände aller meiner netzwerkfähigen Audio-Player (Typ "Squeezebox") anzeigen und bedienbar machen.
Das ist mir (Selbstbeweihräucherung, siehe erstes Bild ::)) sowohl optisch als auch funktional gut gelungen. Das zweite Bild zeigt noch einmal das Reading explizit.

Das widerspenstige Reading ist ein direkt im define definierter Text, der Perl, welches das zu zeigende Icon und den beim Icon-Klick auszuführenden Befehl zurückgibt, enthält.

Die readingsGroup enthält die folgende Definition
(weiter unten auch vollständig aufgeführt)

define readingsGroup_SB_PLAYER readingsGroup [...] SB_PLAYER_.*:[...],<{if(ReadingsVal($DEVICE,'volumeStraight','')<0){"%im_volume-mute2\@Orange%set+$DEVICE+mute"}else{"%im_volume-medium\@Green%set+$DEVICE+mute"}}>,[...]

Das Reading volumeStraight enthält dabei den Mute-Status des Audio-Players. Sein Wertebereich sind die ganzzahligen Zahlen, sowohl im positiven als auch im negativen Bereich. Eine negative Zahl symbolisiert, dass das Audiogerät gemutet ist, eine positive Zahl, dass kein Mute vorliegt. Der reine, absolute, Zahlenwert repräsentiert die aktuelle Lautstärke. Der Befehl set $DEVICE mute toggelt zwischen den beiden Zuständen hin und her.

Ich hätte diese Definition gerne auf die Attribute valueIcon und commands aufgeteilt. Die übrigen nach diesem Muster angelegten Readings funktionieren nämlich. Allerdings müsste ich eine Wildcard einfügen:
(nur sinnbildlich!)

attr readingsGroup_SB_PLAYER commands {\
 
[...],\
  volumeStraight.-\d+ => "set %DEVICE mute", volumeStraight.\d+ => "set %DEVICE mute",\
 
[...]\
}

|
|
|
|
|
attr readingsGroup_SB_PLAYER valueIcon {\
 
[...],\
  volumeStraight.-\d+ => 'im_volume-mute2@Orange', volumeStraight.\d+ => 'im_volume-medium@Green',\
 
[...]\
}

Das gelang mir natürlich nicht.
Ist hier überhaupt eine Wildcard möglich? Lässt sich eine andere Lösung finden?
Die Lösung, die Icons und die Befehle in das define zu stecken, habe ich aus der commandref übernommen...

Ich würde mich freuen, wenn du mit mir über das Problem grübeln würdest!  ;)

Die readingsGroup:defmod readingsGroup_SB_PLAYER readingsGroup <Status>,<Squeezebox/Lautstärke>,<An/Mute>,<Stopp/zurück>,<Pause/vor>,<Album>,<Sender-Playlist/Wecker>,<Künstler/Stück>\
SB_PLAYER_.*:?icon,?alias,state,playStatus,<{"%fa_pause\@Gainsboro%set+$DEVICE+pause"}>,uR_coverarturl,currentPlaylistName,currentArtist,<br>,presence,volume,<{if(ReadingsVal($DEVICE,'volumeStraight','')<0){"%im_volume-mute2\@Orange%set+$DEVICE+mute"}else{"%im_volume-medium\@Green%set+$DEVICE+mute"}}>,<{"%fa_fast_backward\@Gainsboro%set+$DEVICE+prev"}>,<{"%fa_fast_forward\@Gainsboro%set+$DEVICE+next"}>,currentAlbum,alarmsEnabled,currentTitle,<hr>
attr readingsGroup_SB_PLAYER alias Squeezeboxen
attr readingsGroup_SB_PLAYER cellStyle {\
  "c:6" => 'style="text-align:center"'\
}
attr readingsGroup_SB_PLAYER commands {\
  'state.on' =>  "set %DEVICE off", 'state.off' =>  "set %DEVICE on",\
  'playStatus.playing' => "set %DEVICE stop", 'playStatus.paused' => "set %DEVICE play", 'playStatus.stopped' => "set %DEVICE play",\
  'volume' => "volume:slider,0,1,100",\
  'alarmsEnabled.on' => "set %DEVICE alarmsEnabled-off", 'alarmsEnabled.off' => "set %DEVICE alarmsEnabled-on"\
}
attr readingsGroup_SB_PLAYER group Squeezebox
attr readingsGroup_SB_PLAYER headerRows 1
attr readingsGroup_SB_PLAYER nonames 1
attr readingsGroup_SB_PLAYER room Multimedia
attr readingsGroup_SB_PLAYER sortDevices 1
attr readingsGroup_SB_PLAYER valueIcon {\
  'icon' => $VALUE,\
  'state.on' => 'fa__485@Green', 'state.off' => 'fa__484@Orange',\
  'playStatus.playing' => 'fa_play@Green', 'playStatus.paused' => 'fa_pause@Orange', 'playStatus.stopped' => 'fa_stop@Darksalmon',\
  'uR_coverarturl' => "<div align=\"center\"><img src=$VALUE></div>",\
  'presence.present' => 'fa__303@Green', 'presence.absent' => 'fa__303@Red',\
  'alarmsEnabled.on' => 'fa_bell_alt@Green', 'alarmsEnabled.off' => 'fa__471@Orange'\
}


Ein Player:
defmod SB_PLAYER_0004202b459d SB_PLAYER 00:04:20:2b:45:9d
attr SB_PLAYER_0004202b459d DbLogInclude signalstrength,presence
attr SB_PLAYER_0004202b459d IODev XX_XX_XX_SqueezeBoxServer
attr SB_PLAYER_0004202b459d alias Squeezebox Arbeitszimmer (Radio schwarz)
attr SB_PLAYER_0004202b459d amplifier play
attr SB_PLAYER_0004202b459d cmdIcon mute:im_volume-mute2@Gainsboro pause:fa_pause@Gainsboro next:fa_fast_forward@Gainsboro prev:fa_fast_backward@Gainsboro
attr SB_PLAYER_0004202b459d coverartheight 100
attr SB_PLAYER_0004202b459d coverartwidth 100
attr SB_PLAYER_0004202b459d devStateIcon 1.present:fa__303@Green 1.absent:fa__303@Red\
2.on:fa__485@Green:off 2.off:fa__484@Orange:on\
3.playing:fa_play@Green:stop 3.paused:fa_pause@Orange:play 3.stopped:fa_stop@Darksalmon:play\
4.-\d+:im_volume-mute2@Orange:mute 4.\d+:im_volume-medium@Green:mute\
5.on:fa_bell_alt@Green:alarmsEnabled-off 5.off:fa__471@Orange:alarmsEnabled-on
attr SB_PLAYER_0004202b459d do_not_notify 0
attr SB_PLAYER_0004202b459d donotnotify false
attr SB_PLAYER_0004202b459d event-on-change-reading alarmsEnabled,uR_coverarturl,currentPlaylistName,currentArtist,currentAlbum,currentTitle,playStatus,presence,signalstrength,state,volume,volumeStraight
attr SB_PLAYER_0004202b459d eventMap /alarmsEnabled on:alarmsEnabled-on/alarmsEnabled off:alarmsEnabled-off/
attr SB_PLAYER_0004202b459d fadeinsecs 1
attr SB_PLAYER_0004202b459d group Squeezebox
attr SB_PLAYER_0004202b459d icon TR_Logitech_Squeezebox_Radio_schwarz
attr SB_PLAYER_0004202b459d room Multimedia
attr SB_PLAYER_0004202b459d stateFormat 1:presence\
&nbsp;;\
2:state\
&nbsp;;\
3:playStatus\
&nbsp;;\
4:volumeStraight\
&nbsp;;\
5:alarmsEnabled
attr SB_PLAYER_0004202b459d statusRequestInterval 1
attr SB_PLAYER_0004202b459d ttslanguage de
attr SB_PLAYER_0004202b459d ttslink http://translate.google.com/translate_tts?ie=UTF-8&tl=<LANG>&q=<TEXT>&client=tw-ob
attr SB_PLAYER_0004202b459d userReadings uR_coverarturl {\
  (my $coverarturl = ReadingsVal($NAME, 'coverarturl', '')) =~ s/&x=\d+//;;\
  return $coverarturl;;\
}
attr SB_PLAYER_0004202b459d volumeLimit 100
attr SB_PLAYER_0004202b459d volumeStep 1
attr SB_PLAYER_0004202b459d webCmd volume:pause:prev:next

setstate SB_PLAYER_0004202b459d 1:present\
&nbsp;;\
2:on\
&nbsp;;\
3:playing\
&nbsp;;\
4:16\
&nbsp;;\
5:off
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 alarmsDefaultVolume 50
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 alarmsEnabled off
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 alarmsFadeIn on
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 alarmsFadeSeconds 20
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 alarmsSnooze 9
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 alarmsTimeout 60
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 connected 1
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 coverarturl http://LXC-logitechmediaserver:9000/music/current/cover_100x100.jpg?player=00:04:20:2b:45:9d&x=85099
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 currentAlbum Arrival
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:30 currentArtist ABBA
setstate SB_PLAYER_0004202b459d 2020-07-15 14:50:12 currentMedia file:///media/Multimedia/Audio/Alben/ABBA/1973-1981%C2%B7ABBA%C2%B7The%20Albums%C2%B7Ring%20Ring%C2%B7Waterloo%C2%B7ABBA%C2%B7Arrival%C2%B7The%20Album%C2%B7Voulez-Vous%C2%B7Super%20Trouper%C2%B7The%20Visitors/403%C2%B7ABBA%C2%B7Arrival%C2%B7My%20Love,%20My%20Life.mp3
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 currentPlaylistName -
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 currentPlaylistUrl
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 currentTitle My Love, My Life
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 currentTrackPosition 129
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 duration 234
setstate SB_PLAYER_0004202b459d 2020-07-14 12:46:27 favorites -
setstate SB_PLAYER_0004202b459d 2020-07-15 09:48:30 lastir ?
setstate SB_PLAYER_0004202b459d 2020-07-15 14:10:24 lastunknowncmd displaynotify showbriefly HASH(0x55688a97f4f8) HASH(0x55688a8ea7a8)
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 playStatus playing
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 playlistCurrentTrack 14
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 playlistTracks 100
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 playlists -
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 power on
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 presence present
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 repeat off
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 shuffle off
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 signalstrength 100
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 state on
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 synced none
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 uR_coverarturl http://LXC-logitechmediaserver:9000/music/current/cover_100x100.jpg?player=00:04:20:2b:45:9d
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 volume 16
setstate SB_PLAYER_0004202b459d 2020-07-15 14:52:31 volumeStraight 16

GaiusMarius

Ich antworte mir mal selber:

Zitat von: GaiusMarius am 15 Juli 2020, 15:03:00Ist hier überhaupt eine Wildcard möglich? Lässt sich eine andere Lösung finden?
Ja, natürlich, guckst du einfach
Zitat von: justme1968 am 21 Oktober 2016, 14:35:10..., '' => '{...}', ...

zwischen die {} dann etwas perl code in der art:

  $VALUE eq "0" ? "batterie" : "batterie\@red"

Damitsieht die Definition nun so aus:defmod readingsGroup_SB_PLAYER readingsGroup <Status>,<Squeezebox/Lautstärke>,<An/Mute>,<Stopp/zurück>,<Pause/vor>,<Album>,<Sender-Playlist/Wecker>,<Künstler/Stück>\
SB_PLAYER_.*:?icon,?alias,state,playStatus,<{"%fa_pause\@Gainsboro%set+$DEVICE+pause"}>,coverarturl,currentPlaylistName,currentArtist,<br>,presence,volume,volumeStraight,<{"%fa_fast_backward\@Gainsboro%set+$DEVICE+prev"}>,<{"%fa_fast_forward\@Gainsboro%set+$DEVICE+next"}>,currentAlbum,alarmsEnabled,currentTitle,<hr>
attr readingsGroup_SB_PLAYER alias Squeezeboxen
attr readingsGroup_SB_PLAYER cellStyle {\
  "c:6" => 'style="text-align:center"'\
}
attr readingsGroup_SB_PLAYER commands {\
  'state.on'           => "set %DEVICE off", 'state.off' => "set %DEVICE on",\
  'playStatus.playing' => "set %DEVICE stop", 'playStatus.paused' => "set %DEVICE play", 'playStatus.stopped' => "set %DEVICE play",\
  'volume'             => "volume:slider,0,1,100",\
  'volumeStraight'     => "set %DEVICE mute",\
  'alarmsEnabled.on'   => "set %DEVICE alarmsEnabled-off", 'alarmsEnabled.off' => "set %DEVICE alarmsEnabled-on"\
}
attr readingsGroup_SB_PLAYER group Squeezebox
attr readingsGroup_SB_PLAYER headerRows 1
attr readingsGroup_SB_PLAYER nonames 1
attr readingsGroup_SB_PLAYER room Multimedia
attr readingsGroup_SB_PLAYER sortDevices 1
attr readingsGroup_SB_PLAYER valueIcon {\
  'icon'               => $VALUE,\
  'state.on'           => 'fa__485@Green', 'state.off' => 'fa__484@Orange',\
  'playStatus.playing' => 'fa_play@Green', 'playStatus.paused' => 'fa_pause@Orange', 'playStatus.stopped' => 'fa_stop@Darksalmon',\
  'coverarturl'        => "<div align=\"center\"><img src=%VALUE></div>",\
  'presence.present'   => 'fa__303@Green', 'presence.absent' => 'fa__303@Red',\
  'volumeStraight'     => '{($VALUE lt "0") ? "im_volume-mute2\@Orange" : "im_volume-mute2\@Green"}',\
  'alarmsEnabled.on'   => 'fa_bell_alt@Green', 'alarmsEnabled.off' => 'fa__471@Orange'\
}
War doch gar nicht schwierig, oder?  :P

Lieber Marius, denk doch nicht immer so kompliziert!  8)

Dr.McKay

Hallo,

ich habe ein (vermutlich) ähnliches Problem, an welchem ich nun seit Tagen verzweifle. Ich habe mehrere Hue-Lampen, welche teilweise auch mit "structure" zusammengefasst sind. Ich möchte in einer Übersicht den Ein/Aus-Zustand und die jeweilige Farbe der Lampen in einem einzigen Icons darstellen, die zudem noch anklickbar zum ein/ausschalten sein sollen. Das Icon soll bei eingeschaltetem Zustand die Farbe anzeigen und bei ausgeschaltetem grau sein. Ich dachte, das geht am besten mit einer ReadingsGroup, in der ich die Readings "rgb" und "onoff" für jeweils eine Lampe aus der Struktur abfrage. Zuerst hatte ich die Lampenreadings "rgb" und "onoff" als userreading in der Struktur hinterlegt und wollte in der ReadingsGroup dann diese Readings abfragen, aber aus irgendeinem, mir nicht verständlichen Grund wollte es nicht so recht funktionieren. Ein Problem war u.a., dass die Readings erst nach einiger Zeit aktualiert wurden, sofern man nicht den Browser selbst refresht. Das ist natürlich keine Lösung für ein Wanddisplay. Also habe ich ReadingsGroup so umgestellt, dass sie die Lampenreadings direkt abfragt. Das funktoniert zwar soweit, aber es will mir einfach nicht gelingen, in einem Icon den rgb-Wert und den onoff-Wert so darzustellen, dass sich dieses Icon automatisch aktualisiert, sobald sich eines der Readings ändert. Ich habe, weiß der Fuchs wieviele Forenbeiträge gewälzt, die CommandRef durchgesehen, aber das Brett vor meinem Kopf will nicht verschwinden. Dazu kann ich leider auch nicht behaupten mich sonderlich mit Perl auszukennen, sodass ich auch nichts mit den Codeschnipseln aus den Forenbeiträgen sowie aus den (sehr rudimentären) Erklärungen in der CommandRef zusammenbasteln kann, was funktioniert. D.h. nicht, dass ich es nicht versucht hätte, aber mittlerweile bin ich am verzweifeln. Ich weiß nichtmal, ob die ReadingsGroup der richtige Weg ist. Möglw. geht es über devStateIcon besser, aber auch da stellen sich mir die Frage:
1.) wie ich es anstelle, ein eigenes Icon zu defineren welches beide Zustände (onoff, rgb) erfasst und auch ankklickbar ist (Ich habe bereits mit FW_makeImage funktionierende Bsp. mit eigenen Icons in Äbhängigkeit von den Reading-Werten erstellt, aber diese erfassen nur ein Reading und sind nicht anklickbar)
2.) was für ein Device ist da am besten zu verwenden? Die Lampe, oder Struktur als Device fällt schonmal weg, da ich in verschiedenen Floorplänen andere Ansichten benötige. ReadigsProxy? Das würde bedeuten, ich benötige jeweils für ein Device und eine Ansicht einen eigenen readingsProxy und das können sehr viele am Ende werden. ReadingsGroup? Geht das überhaupt mit devStateIcon?

Zu meinen bisherigen Versuchen:
Ich habe mit ReadingsGroup bisher folgendes probiert
define Lampenzustand readingsGroup hueBridge_HUEDevice3:rgb,onoff hueBridge_HUEDevice5:rgb hueBridge_HUEDevice6:rgb hueBridge_HUEDevice2:rgb
attr Lampenzustand noheading 0
attr Lampenzustand nonames 1
attr Lampenzustand notime 1
attr Lampenzustand valueIcon {'onoff.1' => 'colorbutton@#'.ReadingsVal($DEVICE,"rgb",""), 'onoff.0' => 'colorbutton@#808080'}
und
define Lampenzustand readingsGroup hueBridge_HUEDevice3:rgb,onoff hueBridge_HUEDevice5:rgb,onoff
attr Lampenzustand noheading 0
attr Lampenzustand nonames 1
attr Lampenzustand notime 1
attr Lampenzustand valueFormat { if ($READING eq 'rgb' && ReadingsVal($DEVICE, "onoff", "0") eq '1') {"colorbutton@#".ReadingsVal($DEVICE, "rgb", "ffffff")}else{"colorbutton@#808080"} }
attr Lampenzustand valueIcon %VALUE
als auch über eine Subroutine in myUtils mit der RG
define Lampenzustand readingsGroup hueBridge_HUEDevice3:<{myUtils_lampeneinaus($DEVICE)}>,rgb,onoff hueBridge_HUEDevice5:{myUtils_lampeneinaus($DEVICE)} hueBridge_HUEDevice6:{myUtils_lampeneinaus($DEVICE)}
und der Subroutine
sub
myUtils_lampeneinaus($)
{
  my($DEVICE) = @_;
  my $icon;
  my $link;
     if (ReadingsVal($DEVICE,"onoff","" ) eq '0') {
        $icon = "colorbutton_off@#808080";
        $link = fhem("set $DEVICE off");
     }
     elsif (ReadingsVal($DEVICE,"onoff","" ) eq '1') {
        $icon = "colorbutton@#".ReadingsVal($DEVICE,"rgb","" );
        $link = fhem("set $DEVICE on");     
 }

    my $ret = "%$icon";
  $ret .= "%$link" if( $link );

  return $ret;

}

In den oberen beiden Bsp. wird das Icon nur aktualisiert, wenn ein Reading sich ändert. Ändert sich das andere Reading bleibt das Icon. Wie gesagt, wenn man den Webbrowser refresht, dann stimmt das Icon mit beiden Readings überein. Im unteren Bsp. mit der Subroutine ändert sich das Icon überhaupt nicht automatisch, egal welches Reading sich ändert, nur bei Browserrefresh zeigt das Icon das richtige an.
Das Anklicken zum Umschalten funktioniert natürlich auch nicht, aber solange ich das eine Problem nicht gelöst bekomme brauche ich gar nicht erst weiterzumachen.
Ich hoffe, dass der Ein-oder Andere mich auf den richtigen Pfad bringen kann. Meine Frau ist auch schon langsam genervt. >:(

Dr.McKay

Update:
nach langem Herumprobieren und Nachdenken bin ich zu dem Schluss gekommen, dass es vermutlich nicht möglich ist ein Icon von 2 Readings abhängig zu machen, wenn diese readings getrennt in der RG erfast werden. Eine Aktualisierung des Icons findet nur statt, wenn sich das Reading ändert, für welches das valueIcon gestzt wurde, also in meinem Bsp. entweder "rgb" oder "onoff". Also bestand die Lösung für mich, beide Readings mit Userreading im Parent Device zusammenzufassen. In der RG kann dann das Kombireading erfasst werden und eine Änderung ist immer gewährleistet, wenn sich eines der beiden Teilreadings ändert. In einer Subroutine wird dann das Komireading wieder zerlegt und das Icon in Abhängigkeit der Teilreadings gesetzt. Jetzt funzt es wie gewünscht. Ebenso die "Toggle"-Funktion konnte mit wenig Aufwand umgesetzt werden wo das Kommando an die Gruppe übergeben wird:

Setzen des Userreadings in der Lampe:
attr hueBridge_HUEDevice3 event-on-change-reading zustand
attr hueBridge_HUEDevice3 event-on-update-reading zustand
attr hueBridge_HUEDevice3 userReadings zustand {ReadingsVal($name,'rgb','FFFFFF').','.ReadingsVal($name,'onoff','1')}
Die RG-Definition:
define Lampenzustand readingsGroup hueBridge_HUEDevice3:zustand ...
attr Lampenzustand commands {'zustand' => '{if ($DEVICE eq "hueBridge_HUEDevice3") {"set hueBridge_HUEGroup3 toggle"}elsif(...){...}}'}
attr Lampenzustand noheading 1
attr Lampenzustand nonames 1
attr Lampenzustand notime 1
attr Lampenzustand valueIcon {'zustand' => '{ HUEvalueFormat($DEVICE,$READING,$VALUE)}'}
Und noch die Subroutine für das Icon:
sub
HUEvalueFormat($$$)
{
  my ($DEVICE,$READING,$VALUE) = @_;
  if( ReadingsVal($DEVICE, "zustand", "") =~ qr/(......),(0|1)/p) {
    my $farbe = $1;
    my $einaus = $2;
    if( $einaus eq '0') {
       return 'colorbutton_off@#808080';
       }
    else {
       return 'colorbutton@#'.$farbe;
       }
    }
}
Danke an alle Forenteilnehmer für ihre Beiträge; mithilfe der Code-Schnipsel konnte ich die Perl-Logik allmählich nachvollziehen :)