neue Features: ereignisgesteuertes Perl - DOIF-Perl

Begonnen von Damian, 25 Februar 2018, 21:29:16

Vorheriges Thema - Nächstes Thema

Damian

#180
Das dürfte mit den allgemeinen FHEM-Mechanismen zu tun haben.

Dein Eventblock wird durch ein externes Event, ausgelöst durch setreading ...., beendet.

Innerhalb eines Eventblocks darf es wohl keine fremden Events geben.

Du wirst in diesem Falle auf Einzelereignisse ausweichen müssen, z. B. set_Reading ("Anzeige", "off",1);
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

lichtimc

#181
Danke Damian für deine Antwort.

Das hab ich inzwischen schon rausgefunden und entsprechend angepasst... (siehe EDIT: im vorigen Post.)

Dennoch bleibt das Problem, dass, wenn ein fhem("...") vor einem set_Reading kommt, das set_Reading nicht ausgeführt wird.


Gibt es noch einen anderen Weg ein Reading eines anderen DEVICE zu setzen?

Damian

Zitat von: lichtimc am 20 Februar 2020, 16:37:02
Dennoch bleibt das Problem, dass, wenn ein fhem("...") vor einem set_Reading kommt, das set_Reading nicht ausgeführt wird.

Das kann ich nicht nachvollziehen:

ZitatInternals:
   CFGFN     
   DEF        { [FS];
  fhem"setreading bla test 20";
  set_Reading ("test",10,1);
}
   DOIFDEV    ^global$|^FS$
   FUUID      5e4ec793-f33f-c0d4-e280-b5f5748457aec9b4
   MODEL      Perl
   NAME       di_setreading
   NR         642
   NTFY_ORDER 50-di_setreading
   STATE      initialized
   TYPE       DOIF
   VERSION    20929 2020-01-10 09:44:35
   READINGS:
     2020-02-20 18:55:38   Device          FS
     2020-02-20 18:55:38   block_01        executed
     2020-02-20 18:55:38   e_FS_STATE      ???
     2020-02-20 18:55:13   mode            enabled
     2020-02-20 18:53:23   state           initialized
     2020-02-20 18:55:38   test            10

Internals:
   FUUID      5d63fc90-f33f-c0d4-a3fd-a78da754aa533c52
   NAME       bla
   NR         16
   STATE      on
   TYPE       dummy
   READINGS:
     2019-11-09 19:03:09   state           on
     2020-02-20 18:55:38   test            20
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

der-Lolo

Guten Morgen Damian,
ich knobbel gerade an meinem Rasensprenger - mir fehlt aber der Ansatz...
Ziel ist es drei Buttons zu haben 5, 10 und 15 die jeweils 5, 10 oder 15 minuten on-for-timer wiederspiegeln.
Das schaltende Device ist ein ModbusCoil und versteht on-for-timer
set Rasensprenger on-for-timer 300 wären also 5 minuten.

Kannst Du mir hier eine kurze hilfe geben - im Doku wirwar blicke ich nicht durch..


moskito

#184
Hi der-Lolo,
schau doch mal, ob das in die Richtung geht was du suchst:

defmod dfp.rasensprenger DOIF init {set_State("off")}{["$SELF:bla"];;set_State("on");;fhem_set"Rasensprenger on-for-timer 300";;set_Exec("",300,'set_State("off")')}
attr dfp.rasensprenger devStateIcon on:radio_checked@red off:radio_checked@green:bla


Ist ein Codefragment von Damian, das ich mal irgendwo aufgeschnappt hatte.
Evtl. ein Nachteil: Es wird nicht der wirkliche Schaltzustand des Rasensprengers wiedergegeben.

Gruß
Danny
FHEM auf Intel NUC/Proxmox & Debian 12 + HM-CFG-USB + zigbee2mqtt + Zwave + Enocean

der-Lolo

Naja - noch nicht ganz, wenn ich alles richtig verstehe starte ich so ja auch zwei Timer...

Damian

Hier mal ganz primitiv über webCmd:

defmod di_butten DOIF {["$SELF:Timer1"];;fhem_set("Rasensprenger on-for-timer 300")}\
{["$SELF:Timer2"];;fhem_set("Rasensprenger on-for-timer 600")}\
{["$SELF:Timer3"];;fhem_set("Rasensprenger on-for-timer 900")}\

attr di_butten webCmd Timer1:Timer2:Timer3
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

mumpitzstuff

#187
Ich habe mal versucht ein sehr komplexes DOIF aufzusetzen und dabei den Perl Modus zu verwenden. Das hat am Anfang auch ganz gut funktioniert, aber irgendwann bin ich an den Punkt gekommen, an dem ich [] innerhalb eines Regex oder für den Zugriff auf ein Array verwenden musste. Dann habe ich die Möglichkeit gefunden subs {} zu verwenden und auch getan. Leider bekommen aber die hier definierten subs keinen Zugriff auf die globalen Variablen mehr. Gibt es dafür einen Ausweg?

Beispiel:

subs {
  sub test() {
    $test = 'mist';
  }
}
{
  my $test;

}


Ich erhalte dann solche Fehler:

Global symbol "$test" requires explicit package name (did you forget to declare "my $test"?) at (eval 7924) line 16.

PS: Mit $DOIF::<variable> scheint es irgendwie weiter zu gehen oder alternativ mit package DOIF. Ich muss noch prüfen ob nur keine Fehler mehr kommen oder es jetzt wirklich geht...

Warum wird subs { } nicht standardmäßig in den DOIF Namensraum gelegt?

Damian

Zitat von: mumpitzstuff am 10 Juni 2020, 01:17:43
Ich habe mal versucht ein sehr komplexes DOIF aufzusetzen und dabei den Perl Modus zu verwenden. Das hat am Anfang auch ganz gut funktioniert, aber irgendwann bin ich an den Punkt gekommen, an dem ich [] innerhalb eines Regex oder für den Zugriff auf ein Array verwenden musste. Dann habe ich die Möglichkeit gefunden subs {} zu verwenden und auch getan. Leider bekommen aber die hier definierten subs keinen Zugriff auf die globalen Variablen mehr. Gibt es dafür einen Ausweg?

Beispiel:

subs {
  sub test() {
    $test = 'mist';
  }
}
{
  my $test;

}


Ich erhalte dann solche Fehler:

Global symbol "$test" requires explicit package name (did you forget to declare "my $test"?) at (eval 7924) line 16.

PS: Mit $DOIF::<variable> scheint es irgendwie weiter zu gehen oder alternativ mit package DOIF. Ich muss noch prüfen ob nur keine Fehler mehr kommen oder es jetzt wirklich geht...

Warum wird subs { } nicht standardmäßig in den DOIF Namensraum gelegt?
subs werden im Namensraum DOIF gelegt. Du hast aber eine lokale Variable deklarieret, die ist außerhalb der Methode nicht bekannt. Das ist so ziemlich in allen Sprachen so.

Was du brauchst sind Instanzvariablen (hier Device-Variablen genannt). Auch dafür habe ich vorgesorgt, siehe https://fhem.de/commandref_DE.html#DOIF_Device-Variablen
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

mumpitzstuff

Verstehe ich nicht. Ein Script in dieser Form macht keine Probleme:


my $mist;

sub test()
{
  $mist = '';
}


Was genau DOIF mit den zwei Blöcken da macht ist mir ja nicht bekannt. Ich war davon ausgegangen, das die beiden Dinge intern irgendwie als Einheit betrachtet werden. Vielleicht ist es auch nur das Problem, das ich den subs Block zuerst definiert habe? War gestern schon spät, ich spiele heute mal noch ein wenig rum.

Damian

#190
Außerhalb der Perl-Blöcke gibt es kein Perl (neuerdings gibt es dort Template-Definitionen), da kann man auch keine Perlvariablen nutzen.

Jeder Block wird per eval ausgeführt. mit $_<Variablenname> oder $VAR{<Variablenname>} kann man innerhalb der Perl-Blöcke blockübergreifend mit sog. Device-Variablen hantieren.

subs {

$_bla=1;

}


block {

print ($_bla);

}



 
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

mumpitzstuff

Lustig. Ein bischen geht schon mal (das wahrscheinlich fetteste DOIF aller Zeiten). Muss ich aber noch etwas verfeinern...

PS: Port 7072 muss ohne Passwort per telnet erreichbar sein, damit es funktioniert. Außerdem muss man für den initialen Download die Bedingung temporär anpassen, bis diese einmalig ausgeführt wurde.

[00:05|Mo Do]


defmod doif_TEST DOIF subs\
{\
  use utf8;;\
  use Date::Parse;;\
  # sudo apt-get install libxml-bare-perl\
  use XML::Bare 0.53 qw(forcearray);;\
  use Blocking;;\
  \
  ### CONFIG AREA ###\
  $_channelFilter = qr/^(?:ARD\.|ZDF\.|Sat1\.|RTL2?\.|Pro(?:7|SiebenMaxx)\.|DMax\.|Vox\.|Kabel(?:EinsClassic|EinsDoku)?\.|ntv\.|Sixx\.|TLC\.|N24Doku\.|SonyEntertainmentTV\.|AandE\.|TNT(?:Serie|Film)\.|AnimalPlanet\.|History\.|Kinowelt\.|NatGeoHD\.|PLANET\.|Silverline\.|13thStreet\.|AXN\.|SciFi\.)/;;\
  $_timeAdjust = 0;;\
  $_path = '/opt/fhem/';;\
  $_dataFile = $_path.'rytecDE_Basic';;\
  # enable/disable unused channel filtering on filemerge (enabled = small file = faster)\
  $_filterChannels = 1;;\
  \
\
  sub filterText($)\
  {\
    my $text = shift;;\
\
    $text =~ s/["`;;'\r]//g;;\
    $text =~ s/[\n]/<br>/g;;\
\
    return $text;;\
  }\
  \
  sub xmltv2epoch($)\
  {\
    my $t = shift;;\
\
    return Time::Piece->strptime($t, '%Y%m%d%H%M%S %z')->epoch;;\
  }\
\
  sub FmtDateTime($)\
  {\
    my @t = localtime(shift);;\
    return sprintf("%04d-%02d-%02d %02d:%02d:%02d", $t[5]+1900, $t[4]+1, $t[3], $t[2], $t[1], $t[0]);;\
  }\
\
  sub tvParse($;;$)\
  {\
    my ($device, $mode) = @_;;\
    my $obj;;\
    my $xml;;\
    my $lastChannel = '';;\
    my $reading = '';;\
    my $i = 999;;\
    my $n = 999;;\
    my $k = 0;;\
    my $primeTime = substr(FmtDateTime(time() + $_timeAdjust), 0, 11).'20:14:00';;\
    my $sendTelnet = '';;\
\
    $obj = XML::Bare->new(file => $_dataFile);;\
    $xml = $obj->parse();;\
\
    if (!$@)\
    {\
      my $old = time() + $_timeAdjust;;\
\
      foreach (@{forcearray($xml->{'tv'}{'programme'})})\
      {\
        if ((0 != $_filterChannels) ||\
            ($_->{'channel'}{'value'} =~ $_channelFilter))\
        {\
          my $stop = xmltv2epoch($_->{'stop'}{'value'});;\
\
          # filter old stuff\
          if ($stop > $old)\
          {\
            if ($lastChannel ne $_->{'channel'}{'value'})\
            {\
              $lastChannel = $_->{'channel'}{'value'};;\
              $reading = $_->{'channel'}{'value'};;\
              $reading =~ s/[\.\s]//g;;\
              $reading =~ s/de$//;;\
              $n = 0;;\
              $i = 0;;\
            }\
\
            if ($i < 3 && 'next' eq $mode)\
            {\
              my $fi = sprintf("%03d", $i);;\
              my $start = xmltv2epoch($_->{'start'}{'value'});;\
              my $readingName;;\
              my $readingValue;;\
\
              $readingName = 'next_'.$reading.'_'.$fi.'_bdate';;\
              $readingValue = substr(FmtDateTime($start), 0, 10);;\
              $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
              $readingName = 'next_'.$reading.'_'.$fi.'_btime';;\
              $readingValue = substr(FmtDateTime($start), 11, 8);;\
              $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
              $readingName = 'next_'.$reading.'_'.$fi.'_title';;\
              $readingValue = filterText(@{forcearray($_->{'title'})}[0]->{'value'});;\
              $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
              $readingName = 'next_'.$reading.'_'.$fi.'_stitle';;\
              if (exists($_->{'sub-title'}{'value'}))\
              {\
                $readingValue = filterText($_->{'sub-title'}{'value'});;\
              }\
              else\
              {\
                $readingValue = 'na';;\
              }\
              $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
              $readingName = 'next_'.$reading.'_'.$fi.'_desc';;\
              if (exists($_->{'desc'}{'value'}))\
              {\
                $readingValue = filterText($_->{'desc'}{'value'});;\
              }\
              else\
              {\
                $readingValue = 'na';;\
              }\
              $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
              $k++;;\
              $i++;;\
            }\
\
            if ($n < 3 && 'prime' eq $mode)\
            {\
              my $start = xmltv2epoch($_->{'start'}{'value'});;\
              my $fmtStart = FmtDateTime($start);;\
              my $bdate = substr($fmtStart, 0, 10);;\
              my $btime = substr($fmtStart, 11, 8);;\
\
              if ($bdate.' '.$btime gt $primeTime)\
              {\
                my $fn = sprintf("%03d", $n);;\
                my $readingName;;\
                my $readingValue;;\
\
                $readingName = 'prime_'.$reading.'_'.$fn.'_bdate';;\
                $readingValue = substr(FmtDateTime($start), 0, 10);;\
                $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
                $readingName = 'prime_'.$reading.'_'.$fn.'_btime';;\
                $readingValue = substr(FmtDateTime($start), 11, 8);;\
                $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
                $readingName = 'prime_'.$reading.'_'.$fn.'_title';;\
                $readingValue = filterText(@{forcearray($_->{'title'})}[0]->{'value'});;\
                $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
                $readingName = 'prime_'.$reading.'_'.$fn.'_stitle';;\
                if (exists($_->{'sub-title'}{'value'}))\
                {\
                  $readingValue = filterText($_->{'sub-title'}{'value'});;\
                }\
                else\
                {\
                  $readingValue = 'na';;\
                }\
                $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
                $readingName = 'prime_'.$reading.'_'.$fn.'_desc';;\
                if (exists($_->{'desc'}{'value'}))\
                {\
                  $readingValue = filterText($_->{'desc'}{'value'});;\
                }\
                else\
                {\
                  $readingValue = 'na';;\
                }\
                $sendTelnet .= ";;setreading $device $readingName $readingValue";;\
\
                $k++;;\
                $n++;;\
              }\
            }\
\
            if ($k >= 10)\
            {\
              `perl /opt/fhem/fhem.pl 7072 "$sendTelnet"`;;\
\
              $k = 0;;\
              $sendTelnet = '';;\
            }\
          }\
        }\
      }\
\
      if ('' ne $sendTelnet)\
      {\
        `perl /opt/fhem/fhem.pl 7072 "$sendTelnet"`;;\
      }\
    }\
  }\
  \
  sub tvMerge($;;$)\
  {\
    my ($dstName, $srcName) = @_;;\
    my $fh;;\
    my $dst;;\
    my $src;;\
    my $start = '';;\
    my $channels1 = '';;\
    my $channels1_flt = '';;\
    my $channels2 = '';;\
    my $channels2_flt = '';;\
    my $programms1 = '';;\
    my $programms1_flt = '';;\
    my $programms2 = '';;\
    my $programms2_flt = '';;\
    my $end = '';;\
    my $pos;;\
\
    open($fh, '<', $dstName) or die "Can't open file $!";;\
    read($fh, $dst, -s $fh);;\
    close($fh);;\
\
    if (defined($srcName))\
    {\
      open($fh, '<', $srcName) or die "Can't open file $!";;\
      read($fh, $src, -s $fh);;\
      close($fh);;\
    }\
\
    if (-1 != ($pos = index($dst, '<channel ')))\
    {\
      $start = substr($dst, 0, $pos);;\
    }\
\
    if (-1 != ($pos = rindex($dst, '</programme>')))\
    {\
      $end = substr($dst, $pos + 12);;\
    }\
\
    while ($dst =~ /(\s*<channel\s.*?id="(.*?)".*?<\/channel>)/sg)\
    {\
      if (0 != $_filterChannels)\
      {\
        $_ = $1;;\
\
        if ($2 =~ $_channelFilter)\
        {\
          $channels1_flt .= $_;;\
        }\
      }\
      else\
      {\
        $channels1 .= $1;;\
      }\
    }\
\
    while ($dst =~ /(\s*<programme\s.*?channel="(.*?)".*?<\/programme>)/sg)\
    {\
      if (0 != $_filterChannels)\
      {\
        $_ = $1;;\
\
        if ($2 =~ $_channelFilter)\
        {\
          $programms1_flt .= $_;;\
        }\
      }\
      else\
      {\
        $programms1 .= $1;;\
      }\
    }\
\
    if (defined($srcName))\
    {\
      while ($src =~ /(\s*<channel\s.*?id="(.*?)".*?<\/channel>)/sg)\
      {\
        if (0 != $_filterChannels)\
        {\
          $_ = $1;;\
\
          if ($2 =~ $_channelFilter)\
          {\
            $channels2_flt .= $_;;\
          }\
        }\
        else\
        {\
          $channels2 .= $1;;\
        }\
      }\
\
      while ($src =~ /(\s*<programme\s.*?channel="(.*?)".*?<\/programme>)/sg)\
      {\
        if (0 != $_filterChannels)\
        {\
          $_ = $1;;\
\
          if ($2 =~ $_channelFilter)\
          {\
            $programms2_flt .= $_;;\
          }\
        }\
        else\
        {\
          $programms2 .= $1;;\
        }\
      }\
    }\
\
    if (0 != $_filterChannels)\
    {\
      open($fh, '>', $dstName) or die "Can't open file $!";;\
\
      if (defined($srcName))\
      {\
        print $fh $start.$channels1_flt.$channels2_flt.$programms1_flt.$programms2_flt.$end;;\
      }\
      else\
      {\
        print $fh $start.$channels1_flt.$programms1_flt.$end;;\
      }\
\
      close($fh);;\
    }\
    else\
    {\
      open($fh, '>', $dstName) or die "Can't open file $!";;\
\
      if (defined($srcName))\
      {\
        print $fh $start.$channels1.$channels2.$programms1.$programms2.$end;;\
      }\
      else\
      {\
        print $fh $start.$channels1.$programms1.$end;;\
      }\
\
      close($fh);;\
    }\
  }\
\
  sub tvDownload()\
  {\
    my $output = '';; \
    \
    # other server\
    # http://www.xmltvepg.nl/rytecDE_Basic.xz\
    # http://91.121.106.172/~rytecepg/epg_data/rytecDE_Basic.xz\
    # http://www.vuplus-community.net/rytec/rytecDE_Common.xz\
    # http://www.xmltvepg.nl/rytecDE_Common.xz\
    # http://91.121.106.172/~rytecepg/epg_data/rytecDE_Common.xz\
    # http://www.vuplus-community.net/rytec/rytecDE_SportMovies.xz\
    # http://www.xmltvepg.nl/rytecDE_SportMovies.xz\
    # http://91.121.106.172/~rytecepg/epg_data/rytecDE_SportMovies.xz\
    $output .= qx(wget http://www.vuplus-community.net/rytec/rytecDE_Basic.xz -O /opt/fhem/rytecDE_Basic.xz 2>&1);;\
    $output .= qx(xz -df /opt/fhem/rytecDE_Basic.xz 2>&1);;\
\
    if (0 != $_filterChannels)\
    {\
      tvMerge($_dataFile);;\
    }\
    \
    return $output;;\
  }\
\
  sub tvDownloadMerge()\
  {\
    my $output = '';; \
    \
    # other server\
    # http://www.xmltvepg.nl/rytecDE_Basic.xz\
    # http://91.121.106.172/~rytecepg/epg_data/rytecDE_Basic.xz\
    # http://www.vuplus-community.net/rytec/rytecDE_Common.xz\
    # http://www.xmltvepg.nl/rytecDE_Common.xz\
    # http://91.121.106.172/~rytecepg/epg_data/rytecDE_Common.xz\
    # http://www.vuplus-community.net/rytec/rytecDE_SportMovies.xz\
    # http://www.xmltvepg.nl/rytecDE_SportMovies.xz\
    # http://91.121.106.172/~rytecepg/epg_data/rytecDE_SportMovies.xz\
    $output .= qx(wget http://www.vuplus-community.net/rytec/rytecDE_Basic.xz -O /opt/fhem/rytecDE_Basic.xz 2>&1);;\
    $output .= qx(xz -df /opt/fhem/rytecDE_Basic.xz 2>&1);;\
    $output .= qx(wget http://www.vuplus-community.net/rytec/rytecDE_Common.xz -O /opt/fhem/rytecDE_Common.xz 2>&1);;\
    $output .= qx(xz -df /opt/fhem/rytecDE_Common.xz 2>&1);;\
    \
    tvMerge($_dataFile, $_path.'rytecDE_Common');;\
\
    # download and merge other files here if needed\
    \
    return $output;;\
  }\
  \
  \
  sub startDownload($)\
  {\
    my $name = shift;;\
    \
    if (defined($_blockingcalls{PID_DOWNLOAD}))\
    {\
      ::Log3 $name, 3, $name.': Blocking call already running (download).';;\
\
      ::BlockingKill($_blockingcalls{PID_DOWNLOAD});;\
    }\
\
    $_blockingcalls{PID_DOWNLOAD} = ::BlockingCall('DOIF::doDownload', $name, 'DOIF::endDownload', 300, 'DOIF::abortDownload', $name);;\
  }\
  \
  sub DOIF::doDownload($)\
  {\
    my $name = shift;;\
    my $output = '';;\
    \
    $output = tvDownloadMerge();;\
    \
    return $name.'|'.$output;;\
  }\
  \
  sub DOIF::endDownload($)\
  {\
    my ($name, $output) = split("\\|", shift);;\
    \
    ::Log3 $name, 5, $name.': Blocking call finished to download tv data.';;\
    \
    delete($_blockingcalls{PID_DOWNLOAD});;\
  }\
  \
  sub DOIF::abortDownload($)\
  {\
    my $name = shift;;\
    \
    delete($_blockingcalls{PID_DOWNLOAD});;\
    \
    ::Log3 $name, 1, $name.': Blocking call aborted (download).';;\
  }\
  \
  sub startParse($$)\
  {\
    my ($name, $mode) = @_;;\
    \
    if (defined($_blockingcalls{PID_PARSE}))\
    {\
      ::Log3 $name, 3, $name.': Blocking call already running (parse).';;\
\
      ::BlockingKill($_blockingcalls{PID_PARSE});;\
    }\
\
    $_blockingcalls{PID_PARSE} = ::BlockingCall('DOIF::doParse', $name.'|'.$mode, 'DOIF::endParse', 300, 'DOIF::abortParse', $name);;\
  }\
  \
  sub DOIF::doParse($)\
  {\
    my ($name, $mode) = split("\\|", shift);;\
        \
    tvParse($name, $mode);;\
    \
    return $name;;\
  }\
  \
  sub DOIF::endParse($)\
  {\
    my $name = shift;;\
    \
    ::Log3 $name, 5, $name.': Blocking call finished to parse tv data.';;\
    \
    delete($_blockingcalls{PID_PARSE});;\
  }\
  \
  sub DOIF::abortParse($)\
  {\
    my $name = shift;;\
    \
    delete($_blockingcalls{PID_PARSE});;\
    \
    ::Log3 $name, 1, $name.': Blocking call aborted (parse).';;\
  }\
}\
{\
  if ([00:05|Mo Do])\
  {\
    startDownload("$SELF");;\
  }\
  \
  if ([+00:15]) \
  {\
    startParse("$SELF", 'next');;\
  }\
  \
  if ([00:30])\
  {\
    startParse("$SELF", 'prime');;\
  }\
}
attr doif_TEST alias Aktuelles TV-Programm
attr doif_TEST room TEST
attr doif_TEST uiTable {\
  package ui_Table;;\
\
  $SHOWNOSTATE=1;;\
\
  $TR{0,31} = "style='color:yellow;;text-align:center;;font-weight:bold;;font-size:18px'";;\
  $TD{0..29,31..60}{2,4} = "style='font-size:16px;;border-right-style:solid;;border-color:#CCCCCC;;border-right-width:1px;;'";;\
  $TD{0..29,31..60}{0} = "align='center' style='border-right-style:solid;;border-color:#CCCCCC;;border-right-width:1px;;'";;\
  $TD{0..60}{1,3,5,6} = "style='font-size:16px;;'";;\
  $TD{30}{1..6} = "border-top-style:solid;;border-bottom-style:solid;;border-color:#CCCCCC;;border-top-width:1px;;border-bottom-width:1px;;'";;\
\
  sub rgUnfold\
  {\
    my ($title, $desc) = @_;;\
    $title = 'na' if (!defined($title));;\
    $desc = 'na'."\n\n".'na' if (!defined($desc));;\
\
    $title =~ s/(.{1,45}|\S{46,})(?:\s[^\S\r\n]*|\Z)/$1<br>/g;;\
    $desc =~ s/<br>/\n/g;;\
    $desc =~ s/(.{1,65}|\S{66,})(?:\s[^\S\r\n]*|\Z)/$1<br>/g;; \
    $desc =~ s/[\r\'\"]/ /g;;\
    $desc =~ s/[\n]|\\n/<br>/g;;\
    return "<a href=\"#!\" onclick=\"FW_okDialog('".$desc."')\">".$title."</a>";;\
  }\
}\
\
DEF TPL_TV(ICON("tv/$4")|substr([$1:$2_$3_000_btime],0,5)|rgUnfold([$1:$2_$3_000_title],[$1:$2_$3_000_stitle]."\n\n".[$1:$2_$3_000_desc])|substr([$1:$2_$3_001_btime],0,5)|rgUnfold([$1:$2_$3_001_title],[$1:$2_$3_001_stitle]."\n\n".[$1:$2_$3_001_desc])|substr([$1:$2_$3_002_btime],0,5)|rgUnfold([$1:$2_$3_002_title],[$1:$2_$3_002_stitle]."\n\n".[$1:$2_$3_002_desc]))\
\
"Sender"|"ab"|"Aktuelle Sendung"|"ab"|"Nächste Sendung"|"ab"|"Sendung"\
TPL_TV($SELF,next,ARD,ard)\
TPL_TV($SELF,next,ZDF,zdf)\
TPL_TV($SELF,next,Sat1,sat1)\
TPL_TV($SELF,next,RTL,rtl)\
TPL_TV($SELF,next,RTL2,rtl2)\
TPL_TV($SELF,next,Pro7,pro7)\
TPL_TV($SELF,next,DMax,dmax)\
TPL_TV($SELF,next,Vox,vox)\
TPL_TV($SELF,next,Kabel,kabel1)\
TPL_TV($SELF,next,KabelEinsClassic,kabel1classic)\
TPL_TV($SELF,next,13thStreet,13thstreet)\
TPL_TV($SELF,next,Silverline,silverline)\
TPL_TV($SELF,next,TNTFilm,tntfilm)\
TPL_TV($SELF,next,AXN,axn)\
TPL_TV($SELF,next,SonyEntertainmentTV,sonytv)\
TPL_TV($SELF,next,Kinowelt,kinowelt)\
TPL_TV($SELF,next,ProSiebenMaxx,pro7maxx)\
TPL_TV($SELF,next,Sixx,sixx)\
TPL_TV($SELF,next,TNTSerie,tntserie)\
TPL_TV($SELF,next,SciFi,syfy)\
TPL_TV($SELF,next,ntv,ntv)\
TPL_TV($SELF,next,N24Doku,n24)\
TPL_TV($SELF,next,History,history)\
TPL_TV($SELF,next,PLANET,planet)\
TPL_TV($SELF,next,KabelEinsDoku,kabel1doku)\
TPL_TV($SELF,next,AnimalPlanet,animalplanet)\
TPL_TV($SELF,next,NatGeoHD,natgeo)\
TPL_TV($SELF,next,TLC,tlc)\
TPL_TV($SELF,next,AandE,ae)\
"&nbsp;;"|"&nbsp;;"|"&nbsp;;"|"&nbsp;;"|"&nbsp;;"|"&nbsp;;"|"&nbsp;;"\
"Sender"|"ab"|"Sendung"|"ab"|"Sendung"|"ab"|"Sendung"\
TPL_TV($SELF,prime,ARD,ard)\
TPL_TV($SELF,prime,ZDF,zdf)\
TPL_TV($SELF,prime,Sat1,sat1)\
TPL_TV($SELF,prime,RTL,rtl)\
TPL_TV($SELF,prime,RTL2,rtl2)\
TPL_TV($SELF,prime,Pro7,pro7)\
TPL_TV($SELF,prime,DMax,dmax)\
TPL_TV($SELF,prime,Vox,vox)\
TPL_TV($SELF,prime,Kabel,kabel1)\
TPL_TV($SELF,prime,KabelEinsClassic,kabel1classic)\
TPL_TV($SELF,prime,13thStreet,13thstreet)\
TPL_TV($SELF,prime,Silverline,silverline)\
TPL_TV($SELF,prime,TNTFilm,tntfilm)\
TPL_TV($SELF,prime,AXN,axn)\
TPL_TV($SELF,prime,SonyEntertainmentTV,sonytv)\
TPL_TV($SELF,prime,Kinowelt,kinowelt)\
TPL_TV($SELF,prime,ProSiebenMaxx,pro7maxx)\
TPL_TV($SELF,prime,Sixx,sixx)\
TPL_TV($SELF,prime,TNTSerie,tntserie)\
TPL_TV($SELF,prime,SciFi,syfy)\
TPL_TV($SELF,prime,ntv,ntv)\
TPL_TV($SELF,prime,N24Doku,n24)\
TPL_TV($SELF,prime,History,history)\
TPL_TV($SELF,prime,PLANET,planet)\
TPL_TV($SELF,prime,KabelEinsDoku,kabel1doku)\
TPL_TV($SELF,prime,AnimalPlanet,animalplanet)\
TPL_TV($SELF,prime,NatGeoHD,natgeo)\
TPL_TV($SELF,prime,TLC,tlc)\
TPL_TV($SELF,prime,AandE,ae)

Damian

#192
Was mir dazu einfällt:

Ich hoffe, du benutzt Codemirror oder einen externen Editor.

Längere Definitionen würde ich in eine externe Datei auslagern (myutils-sonstwas, mit package DOIF), die man mit einem vernünftigen Programm-Editor bearbeiten kann. Ich weiß nicht, wann sich der im DEF-Editor verabschiedet.

Im subs-Block ist man im DOIF-Package, da braucht man kein "DOIF::" davorzustellen.

Wenn du "init" als Blocknamen wählst, wird dieser nach seiner Definition bzw. nach dem Hochfahren sofort ausgeführt.
Programmierte FHEM-Module: DOIF-FHEM, DOIF-Perl, DOIF-uiTable, THRESHOLD, FHEM-Befehl: IF

mumpitzstuff

externe Datei = halb so viel Spass :)

Das DOIF:: habe ich nur bei BlockingCall Funktionen verwendet. Das hatte so in der Hilfe gestanden, deshalb habe ich mich daran gehalten.

Das mit dem init Block habe ich übernommen. Danke.

PS: Das DOIF ist heute denke ich fertig geworden (selektives update habe ich noch erweitert). Ich stelle es dann die nächsten Tage noch mal separat zur Verfügung, nachdem ich es noch 1-2 Tage habe laufen lassen. Ist aber wirklich super was alles in so einem DOIF geht. Vielen Dank für das tolle Modul.

weini

Gibt es eine Möglichkeit, im Perl-Modus auf den Status zu triggern?
Ich möchte mir ein "Überwachtungs-DOIF" für meinen ganzen CUL/LaCrosse/sDuino etc. Zoo definieren. Die einzelnen Module haben schlauerweise unterschiedliche Stati für "alles ok". Mal ist das "Initialized", mal "Connected" usw. Das lässt sich mit dem Template-Ansatz von DOIF im Prinzip sehr schön erschlagen.

Mein Problem ist nur, dass bei einem Disconnect eines Devices kein Event erzeugt wird, sondern das verantwortliche Modul nur einfach den state entsprechen setzt.
Ist der Perl-Modus damit ausgehebelt?

VG, weini