############################################## # $Id$ # 95_remotecontrol # ################################################################ # # Copyright notice # # (c) 2013 Copyright: Ulrich Maass # # This file is part of fhem. # # Fhem is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 2 of the License, or # (at your option) any later version. # # Fhem is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with fhem. If not, see . # # Disclaimer: The Author takes no responsibility whatsoever # for damages potentially done by this program. # ################################################################################ # # Implementation: # 1 - set WEB rereadicons # 2 - define rc1 remotecontrol (defines fresh remotecontrol, has no keys defined yet) # 3a- get rc1 layout (display list of available "keybiard"-layouts) # 3 - set rc1 layout samsung (assigns standard-key-layout for e.g. samsungTV) # 4 - set rc1 makeweblink (creates a weblink weblink_rc1) # 4a- for testing: attr rc1 room TestRemote , attr weblink_rc1 room TestRemote # 5 - set rc1 makenotify (creates a notify of the form: define notify_rc1 notify rc1 set $EVENT) # # Published June 23, 2013 # bugfix "use strict" upon foreign makenotify - June 24, 2013 # converted to UNIX-LF - June 25, 2013 # fixed minor html-bug - June 26, 2013 # added css-tags rc_body and rc_button - June 27, 2013 # deleted leading \n at beginning of html-code - June 30, 2013 # fhemweb-detailscreen of remotecontrol now displays a preview, added htmlNoTable for RC_attr2html(), added RC_summaryFn incl attr rc_devStateIcon package main; use strict; use warnings; ######################### # Forward declaration sub RC_Define(); sub RC_Set($@); sub RC_Get($@); sub RC_Attr(@); sub RC_array2attr($@); sub RC_attr2html($@); sub RC_layout_delete($); sub RC_layout_samsung(); sub RC_layout_itunes(); sub RC_detailFn($$$$); sub RC_webCmdFn($$$); sub RC_summaryFn($$$$); ##################################### # Initialize module sub remotecontrol_Initialize($) { my ($hash) = @_; $hash->{GetFn} = "RC_Get"; $hash->{SetFn} = "RC_Set"; $hash->{AttrFn} = "RC_Attr"; $hash->{DefFn} = "RC_Define"; $hash->{AttrList} = "rc_iconpath rc_iconprefix loglevel:0,1,2,3,4,5,6 rc_devStateIcon:0,1 ". "row00 row01 row02 row03 row04 row05 row06 row07 row08 row09 ". "row10 row11 row12 row13 row14 row15 row16 row17 row18 row19"; $hash->{FW_detailFn} = "RC_detailFn"; # displays rc preview in fhemweb detail-screen $hash->{FW_summaryFn} = "RC_summaryFn"; # displays rc instead of status icon in fhemweb room-view $data{webCmdFn}{remotecontrol} = "RC_webCmdFn"; # displays rc instead of device-commands on the calling device $data{RC_layout}{samsung} = "RC_layout_samsung"; $data{RC_layout}{itunes} = "RC_layout_itunes"; # $data{RC_layout}{enigma} = "RC_layout_enigma"; # $data{RC_makenotify}{enigma} = "RC_makenotify_enigma"; } ##################################### # Initialize every new instance sub RC_Define() { my ($hash, $def) = @_; $hash->{STATE} = "initialized"; $hash->{".htmlCode"} = ""; return undef; } ##################################### # Ensure htmlcode is created from scratch after an attribute value has been changed sub RC_Attr(@) { my @a = @_; my $hash = $defs{$a[1]}; $hash->{".htmlCode"} = ""; return; } ##################################### # Digest set-commands sub RC_Set($@) { my ($hash, @a) = @_; my $nam = $a[0]; my $cmd = (defined($a[1]) ? $a[1] : ""); #command my $par = (defined($a[2]) ? $a[2] : ""); #parameter ## set layout if ($cmd eq "layout") { if ($par eq "delete") { RC_layout_delete($nam); $hash->{".htmlCode"} = ""; } else { # layout my $layoutlist = ""; my @rows; foreach my $fn (sort keys %{$data{RC_layout}}) { $layoutlist .= $fn."\n"; next if ($fn ne $par); no strict "refs"; @rows = &{$data{RC_layout}{$fn}}($fn); use strict "refs"; } if ($#rows > 0) { RC_layout_delete($nam); RC_array2attr($nam, @rows); $hash->{".htmlCode"} = ""; } else { return "Missing or invalid parameter \"$par\" for set ... layout. Use one of\n". "delete\n".$layoutlist; } } ## set makeweblink } elsif ($cmd eq "makeweblink") { my $wname = $a[2] ? $a[2] : "weblink_".$nam; fhem("define $wname weblink htmlCode {fhem(\"get $hash->{NAME} htmlcode\", 1)}"); Log 2, "[remotecontrol] Weblink created: $wname"; return "Weblink created: $wname"; ## set makenotify } elsif ($cmd eq "makenotify") { if ($a[2]) { my $ndev = $a[2]; my $fn = $defs{$ndev}{TYPE} ? $defs{$ndev}{TYPE} : undef; if (defined($fn) && defined($data{RC_makenotify}{$fn})) { #foreign makenotify no strict "refs"; my $msg = &{$data{RC_makenotify}{$fn}}($nam,$ndev); use strict "refs"; return $msg; } else { my $nname="notify_$nam"; fhem("define $nname notify $nam set $ndev ".'$EVENT',1); Log 2, "[remotecontrol] Notify created: $nname"; return "Notify created: $nname"; } } else { return "set $nam makenotify :\n name of executing device missing."; } ## set ? } elsif ($cmd eq "?") { my $ret = "Unknown argument $cmd choose one of makeweblink makenotify state .remotecontrol:remotecontrol layout:"; foreach my $fn (sort keys %{$data{RC_layout}}) { $ret .= $fn . ","; } $ret =~ s/[:,]$//; return $ret; ## set state } else { Log GetLogLevel($nam,4), "[remotecontrol] set $nam $cmd $par"; readingsSingleUpdate($hash,"state",$cmd,1) if (!$par); } } ##################################### # Digest get-commands sub RC_Get($@) { my ($hash, @a) = @_; my $arg = (defined($a[1]) ? $a[1] : ""); #command my $name = $hash->{NAME}; ## get htmlcode if($arg eq "htmlcode") { $hash->{".htmlCode"} = RC_attr2html($name) if ($hash->{".htmlCode"} eq ""); return $hash->{".htmlCode"}; ## get layout } elsif ($arg eq "layout") { my $layoutlist = "Available predefined layouts are:\n"; foreach my $fn (sort keys %{$data{RC_layout}}) { $layoutlist .= $fn."\n"; } return $layoutlist; ## get -> error } else { return "Unknown argument $arg choose one of: htmlcode layout"; } } ##################################### # Convert all rowXX-attribute-values into htmlcode sub RC_attr2html($@) { my ($name,$htmlNoTable) = @_; my $iconpath = AttrVal("$name","rc_iconpath","icons/remotecontrol"); my $iconprefix = AttrVal("$name","rc_iconprefix",""); my $rc_html; my $row; $rc_html = "
"; # $rc_html = "
"; # provokes update by longpoll $rc_html.= '' if (!$htmlNoTable); foreach my $rownr (0..19) { $rownr = sprintf("%2.2d",$rownr); $row = AttrVal("$name","row$rownr",undef); next if (!$row); $rc_html .= "\n" if (!$htmlNoTable); my @btn = split (",",$row); foreach my $btnnr (0..$#btn) { $rc_html .= '";# if (!$htmlNoTable); $rc_html .= "\n"; } $rc_html .= "\n" if (!$htmlNoTable); } $rc_html .= "
';# if (!$htmlNoTable); if ($btn[$btnnr] ne "") { my $cmd; my $img; if ($btn[$btnnr] =~ /(.*?):(.*)/) { # button has format : $cmd = $1; $img = $2; } else { # button has format or is empty $cmd = $btn[$btnnr]; $img = $btn[$btnnr]; } if ($img =~ m/\.svg/) { # convert svg-images $img = FW_makeImage($img, $cmd, "rc-button"); } else { $img = ""; } if ($cmd || $cmd eq "0") { $cmd = "cmd.$name=set $name $cmd"; $rc_html .= "$img"; } else { $rc_html .= $img; } } $rc_html .= "
" if (!$htmlNoTable); $rc_html .= "
"; return $rc_html; } ##################################### # Delete all rowXX-attributes sub RC_layout_delete($) { my $name = shift; foreach my $rownr (0..19) { $rownr = sprintf("%2.2d",$rownr); fhem("deleteattr $name row$rownr",1); } } ##################################### # Convert array-values into rowXX-attribute-values sub RC_array2attr($@) { my ($name, @row) = @_; my $ret; foreach my $rownr (0..21) { next if (!$row[$rownr]); $rownr = sprintf("%2.2d",$rownr); if ($row[$rownr] =~ m/^attr (.*?)\s(.*)/) { $ret = fhem("attr $name $1 $2"); } else { $ret = fhem("attr $name row$rownr $row[$rownr]") if ($row[$rownr]); } } } ################## #remotecontrol-specific fhemweb detail-screen sub RC_detailFn($$$$) { my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn. my $hash = $defs{$d}; $hash->{".htmlCode"} = RC_attr2html($d) if ($hash->{".htmlCode"} eq ""); return $hash->{".htmlCode"}; } ################## #remotecontrol-specific webCmdFn to be used # calling module needs to provide ".remotecontrol:remotecontrol" in its return to 'set ?' sub RC_webCmdFn($$$) { my ($FW_wname, $d, $FW_room, $cmd, $values) = @_; return undef if($values !~ m/remotecontrol/); my @args = split("[ \t]+", $cmd); return RC_attr2html($args[1],1) if ($args[1]); return undef; } ################## #remotecontrol-specific summaryFn to be used # displays the remote on the remote-device itself in FHEMWEB room-overview sub RC_summaryFn($$$$) { my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn. my $hash = $defs{$d}; my $name = $hash->{NAME}; return undef if (AttrVal($name,"rc_devStateIcon",1) != 1); return RC_attr2html($name); } ##################################### # Default-layout for samsung sub RC_layout_samsung() { my $ret; my @row; $row[0]="POWEROFF,TV,HDMI"; $row[1]=":blank,:blank,:blank"; $row[2]="1,2,3"; $row[3]="4,5,6"; $row[4]="7,8,9"; $row[5]=":blank,0,PRECH"; $row[6]=":blank,:blank,:blank"; $row[7]="VOLUP:UP,MUTE,CHUP"; $row[8]=":VOL,:blank,:PROG"; $row[9]="VOLDOWN:DOWN,CH_LIST,CHDOWN"; $row[10]="MENU,:blank,GUIDE"; $row[11]=":blank,:blank,:blank"; $row[12]="TOOLS,UP,INFO"; $row[13]="LEFT,ENTER,RIGHT"; $row[14]="RETURN,DOWN,EXIT"; $row[15]="attr rc_iconpath icons/remotecontrol"; $row[16]="attr rc_iconprefix black_btn_"; # unused available commands # AD PICTURE_SIZE SOURCE # CONTENTS W_LINK # RSS MTS SRS CAPTION TOPMENU SLEEP ESAVING # PLAY PAUSE REWIND FF REC STOP # PIP_ONOFF ASPECT return @row; } ##################################### # Default-layout for itunes sub RC_layout_itunes() { my $ret; my @row; $row[0]="play:PLAY,pause:PAUSE,prev:REWIND,next:FF,quieter:VOLDOWN,louder:VOLUP"; $row[1]="attr rc_iconpath icons/remotecontrol"; $row[2]="attr rc_iconprefix black_btn_"; # unused available commands return @row; } 1; =pod =begin html

remotecontrol

    Displays a graphical remote control. Buttons (=icons) can be chosen and arranged. Predefined layouts are available for e.g. Samsung-TV or iTunes. Any buttonclick can be forwarded to the actual fhem-device. For further explanation, please check the Wiki-Entry.

    Define
      define <rc-name> remotecontrol

      Typical steps to implement a remotecontrol:
      define rc1 remotecontrol# defines a "blank" remotecontrol
      get rc1 layout# displays all available predefined layouts
      set rc1 layout samsung# assigns keys for a SamsungTV
      set rc1 makenotify myTV# creates notify_rc1 which forwards every buttonclick to myTV for execution
      Note: keys can be changed at any time, it is not necessary to redefine the weblink
      attr rc1 row15 VOLUP,VOLDOWN

    Set
    • set <rc-name> layout [delete|<layoutname>]
      layout delete deletes all rowXX-attributes
      layout <layoutname> assigns a predefined layout to rowXX-attributes
    • set <rc-name> makeweblink [<name>]
      creates a weblink to display the graphical remotecontrol. Default-name is weblink_<rc-name> .
    • set <rc-name> makenotify <executingDevice>
      creates a notify to trigger <executingDevice> every time a button has been pressed. name is notify_<rc-name> .

    Get
      get <rc-name> [htmlcode|layout]
    • htmlcode displays htmlcode for the remotecontrol on fhem-page
    • layout shows which predefined layouts ae available

    Attributes
    • loglevel
    • rc_iconpath
      path for icons, default is "icons" . The attribute-value will be used for all icon-files except .svg .
    • rc_iconprefix
      prefix for icon-files, default is "" . The attribute-value will be used for all icon-files except .svg .
    • Note: Icon-names (button-image-file-names) will be composed as fhem/<rc_iconpath>/<rc_iconprefix><command|image>
      For .svg -icons, the access sequence is according to the FHEMWEB-attribute iconPath, default is openautomation:fhemSVG:default .
    • rc_devStateIcon
      In FHEMWEB-room-overview, displays the button-layout on the rc-device itself. Default is 1, set to 0 is the remotecontrol-device should not display its buttons in FHEMWEB roomview.

    • rowXX
      attr <rc-name> rowXX <command>[:<image>][,<command>[:<image>]][,...]
      Comma-separated list of buttons/images per row. Any number of buttons can be placed in one row. For each button, use
      • <command> is the command that will trigger the event after a buttonclick. Case sensitive.
      • <image> is the filename of the image

      • Per button for the remotecontrol, use
      • <command> where an icon with the name <command> is displayed
        Example:
        attr rc1 rc_iconprefix black_btn_ # used for ALL icons on remotecontrol rc1
        attr rc1 row00 VOLUP
        icon is black_btn_VOLUP, a buttonclick creates the event VOLUP
      • or
      • <command>:<image> where an icon with the name <rc_iconprefix><image> is displayed
        Example:
        row00=LOUDER:VOLUP
        icon is black_btn_VOLUP, a buttonclick creates the event LOUDER
        Examples:
        attr rc1 row00 1,2,3,TV,HDMI
        attr rc2 row00 play:PLAY,pause:PAUSE,louder:VOLUP,quieter:VOLDOWN
      • Hint: use :blank for a blank space, use e.g. :blank,:blank,:blank for a blank row
=end html =begin html_DE

remotecontrol

    Erzeugt eine graphische Fernbedienung. Buttons (=icons) können frei ausgewählt und angeordnet werden. Vordefinierte layouts sind verfügbar für z.B. Samsung-TV und iTunes. Jeder "Knopfdruck" kann an das entsprechende fhem-Gerät weitergegeben werden.
    Weitere Erklaerungen finden sich im Wiki-Eintrag.

    Define
      define <rc-name> remotecontrol

      Typische Schritte zur Einrichtung:
      define rc1 remotecontrol# erzeugt eine "leere" remotecontrol
      get rc1 layout# zeigt alle vorhandenen vordefinierten layouts an
      set rc1 layout samsung# laedt das layout für SamsungTV
      set rc1 makenotify myTV# erzeugt notify_rc1, das jeden Tastendruck an myTV weitergibt
      Hinweis:die Tastenbelegung kann jederzeit geaendert werden, ohne dass der weblink erneut erzeugt werden muss.
      attr rc1 row15 VOLUP,VOLDOWN

    Set
    • set <rc-name> layout [delete|<layoutname>]
      layout delete loescht alle rowXX-Attribute
      layout <layoutname> laedt das vordefinierte layout in die rowXX-Attribute
    • set <rc-name> makeweblink [<name>]
      erzeugt einen weblink zur Anzeige der remotecontrol in FHEMWEB oder FLOORPLAN. Default-Name ist weblink_<rc-name> .
    • set rc1 makenotify mySamsungTV
      erzeugt notify_rc1 das jeden Tastendruck an mySamsungTV zur Ausfuehrung weitergibt

    Attribute
    • loglevel
    • rc_iconpath
      Pfad für icons, default ist "icons" . Der Attribut-Wert wird für alle icon-Dateien verwendet ausser .svg .
    • rc_iconprefix
      Prefix für icon-Dateien, default ist "" . Der Attribut-Wert wird für alle icon-Dateien verwendet ausser .svg .
    • Note: Icon-Namen (Tasten-Bild-Datei-Namen) werden zusammengesetzt als fhem/<rc_iconpath>/<rc_iconprefix><command|image>
      Fuer .svg -icons ist die Zugriffsfolge gemaess dem FHEMWEB-Attribut iconPath, default ist openautomation:fhemSVG:default .
    • rc_devStateIcon
      Zeigt das button-layout auf dem remotecontrol-device selbst in der FHEMWEB-Raumansicht an. Default ist 1, durch setzen auf 0 erscheint in der FHEMWEB-Raumansciht nicht das layout, sondern nur der Status "Initialized".

    • rowXX
      attr <rc-name> rowXX <command>[:<image>]
      Komma-separarierte Liste von Tasten/Icons je Tastaturzeile. Eine Tastaturzeile kann beliebig viele Tasten enthalten.

    • <command> ist der event, der bei Tastendruck ausgelöst wird. Gross/Kleinschreibung beachten.
    • <image> ist der Dateiname des als Taste angezeigten icons
    • Verwenden Sie je Taste
    • <command> wobei als Taste/icon <command> angezeigt wird
      Beispiel:
      attr rc1 rc_iconprefix black_btn_ # gilt für alle Tasten/icons
      attr rc1 row00 VOLUP
      -> icon ist black_btn_VOLUP, ein Tastendruck erzeugt den event VOLUP

    • oder
    • <command>:<image> wobei als Taste/icon <rc_iconprefix><image> angezeigt wird.
      Beispiel:
      attr rc1 row00 LOUDER:VOLUP
      icon ist black_btn_VOLUP, ein Tastendruck erzeugt den event LOUDER
      Beispiele: attr rc1 row00 1,2,3,TV,HDMI
      attr rc2 row00 play:PLAY,pause:PAUSE,louder:VOLUP,quieter:VOLDOWN
    • Hinweis: verwenden Sie :blank für eine 'leere Taste', oder z.B. :blank,:blank,:blank für eine Abstands-Leerzeile.
=end html_DE =cut