| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243 |
- #
- #
- # 02_RSS.pm
- # written by Dr. Boris Neubert 2012-03-24
- # e-mail: omega at online dot de
- #
- ##############################################
- # $Id: 02_RSS.pm 14405 2017-05-28 17:30:51Z neubert $
- package main;
- use strict;
- use warnings;
- use GD;
- use feature qw/switch/;
- use vars qw(%data);
- use HttpUtils;
- #require "98_SVG.pm"; # enable use of plotAsPng()
- sub plotAsPng(@); # forward declaration will be enough
- # to ensure correct function
- # and will avoid reloading 98_SVG.pm
- # during fhem startup/rereadcfg
- my @cmd_halign= qw(halign thalign ihalign);
- my @cmd_valign= qw(valign tvalign ivalign);
- my @valid_valign = qw(top center base bottom);
- my @valid_halign = qw(left center right justified);
- # we can
- # use vars qw(%FW_types); # device types,
- # use vars qw($FW_RET); # Returned data (html)
- # use vars qw($FW_wname); # Web instance
- # use vars qw($FW_subdir); # Sub-path in URL for extensions, e.g. 95_FLOORPLAN
- # use vars qw(%FW_pos); # scroll position
- # use vars qw($FW_cname); # Current connection name
- # http://blogs.perl.org/users/mike_b/2013/06/a-little-nicer-way-to-use-smartmatch-on-perl-518.html
- #no if $] >= 5.017011, warnings => 'experimental::smartmatch';
- no if $] >= 5.017011, warnings => 'experimental';
- #########################
- sub
- RSS_addExtension($$$) {
- my ($func,$link,$friendlyname)= @_;
-
- my $url = "/" . $link;
- $data{FWEXT}{$url}{FUNC} = $func;
- $data{FWEXT}{$url}{LINK} = "+$link";
- $data{FWEXT}{$url}{NAME} = $friendlyname;
- $data{FWEXT}{$url}{SCRIPT} = "RSS.js";
- $data{FWEXT}{$url}{FORKABLE} = 0;
- }
- ##################
- sub
- RSS_Initialize($) {
- my ($hash) = @_;
- $hash->{DefFn} = "RSS_Define";
- $hash->{UndefFn} = "RSS_Undefine";
- #$hash->{AttrFn} = "RSS_Attr";
- $hash->{AttrList} = "size itemtitle bg bgcolor tmin refresh areas autoreread:1,0 viewport noscroll urlOverride";
- $hash->{SetFn} = "RSS_Set";
- $hash->{NotifyFn} = "RSS_Notify";
- return undef;
- }
-
- ##################
- sub
- RSS_readLayout($) {
- my ($hash)= @_;
- my $filename= $hash->{fhem}{filename};
- my $name= $hash->{NAME};
- my ($err, @layoutfile) = FileRead($filename);
- if($err) {
- Log 1, "RSS $name: $err";
- $hash->{fhem}{layout}= ("text 0.1 0.1 'Error: $err'");
- } else {
- $hash->{fhem}{layout}= join("\n", @layoutfile);
- $hash->{fhem}{layout} =~ s/\n\n/\n/g;
- }
- return;
- }
-
- ##################
- sub
- RSS_Define($$) {
- my ($hash, $def) = @_;
- my @a = split("[ \t]+", $def);
- return "Usage: define <name> RSS jpg|png hostname filename" if(int(@a) != 5);
- my $name= $a[0];
- my $style= $a[2];
- my $hostname= $a[3];
- my $filename= $a[4];
- $hash->{fhem}{style}= $style;
- $hash->{fhem}{hostname}= $hostname;
- $hash->{fhem}{filename}= $filename;
- $hash->{LAYOUTFILE} = $filename;
- $hash->{NOTIFYDEV} = 'global';
- RSS_addExtension("RSS_CGI","rss","RSS");
- eval "use GD::Text::Align";
- $hash->{fhem}{useTextAlign} = ($@ ? 0 : 1 );
- if(!($hash->{fhem}{useTextAlign})) {
- Log3 $hash, 2, "$name: Cannot use text alignment: $@";
- }
-
- eval "use GD::Text::Wrap";
- $hash->{fhem}{useTextWrap} = ($@ ? 0 : 1 );
- if(!($hash->{fhem}{useTextWrap})) {
- Log3 $hash, 2, "$name: Cannot use text wrapping: $@";
- }
-
- RSS_readLayout($hash);
-
- $hash->{STATE} = 'defined'; #$name;
- return undef;
- }
- sub RSS_Undefine($$) {
- my ($hash, $arg) = @_;
- # check if last device
- my $url = '/rss';
- $data{FWEXT}{$url} = undef if int(devspec2array('TYPE=RSS')) == 1;
- return undef;
- }
- sub RSS_Notify {
- my ($hash,$dev) = @_;
- my $name= $hash->{NAME};
- return unless AttrVal($name, 'autoreread',1);
- return if($dev->{NAME} ne "global");
- return if(!grep(m/^FILEWRITE $hash->{LAYOUTFILE}$/, @{$dev->{CHANGED}}));
- Log3(undef, 4, "RSS: $name reread layout after edit.");
- RSS_readLayout($hash);
- return undef;
- }
- ##################
- sub
- RSS_Set() {
- my ($hash, @a) = @_;
- my $name = $a[0];
- # usage check
- my $usage= "Unknown argument, choose one of rereadcfg:noArg";
- if((@a == 2) && ($a[1] eq "rereadcfg")) {
- RSS_readLayout($hash);
- return undef;
- } else {
- return $usage;
- }
- }
- ####################
- #
- sub
- RSS_getURL($) {
- my ($name)= @_;
- my $url= AttrVal($name, 'urlOverride', '');
- return $url if($url ne "");
-
- my $hostname= $defs{$name}{fhem}{hostname};
- # http://hostname:8083/fhem
- my $proto = (AttrVal($FW_wname, 'HTTPS', 0) == 1) ? 'https' : 'http';
- return $proto."://$hostname:" . $defs{$FW_wname}{PORT} . $FW_ME;
- }
- # ##################
- # sub
- # RSS_Attr(@)
- # {
- # my @a = @_;
- # my $attr= $a[2];
- #
- # if($a[0] eq "set") { # set attribute
- # if($attr eq "bgdir") {
- # }
- # }
- # elsif($a[0] eq "del") { # delete attribute
- # if($attr eq "bgdir") {
- # }
- # }
- #
- # return undef;
- #
- # }
- ##################
- # list all RSS devices
- sub
- RSS_Overview {
- my ($name, $url);
- my $html= RSS_HTMLHead("RSS Overview", undef) . "<body>\n";
- foreach my $def (sort keys %defs) {
- if($defs{$def}{TYPE} eq "RSS") {
- $name= $defs{$def}{NAME};
- $url= RSS_getURL($name);
- $html.= "$name<br>\n<ul>";
- $html.= "<a href='$url/rss/$name.rss' target='_blank' >RSS</a><br>\n";
- $html.= "<a href='$url/rss/$name.html' target='_blank' >HTML</a><br>\n";
- $html.= "<a href='$url/rss/$name.png' target='_blank' >Portable Network Graphics</a><br>\n";
- $html.= "<a href='$url/rss/$name.jpg' target='_blank' >JPEG Graphics</a><br>\n";
- $html.= "</ul>\n<p>\n";
- }
- }
- $html.="</body>\n" . RSS_HTMLTail();
- return ("text/html; charset=utf-8", $html);
- }
- ##################
- sub
- RSS_splitRequest($) {
- # http://hostname:8083/fhem/rss
- # http://hostname:8083/fhem/rss/myDeviceName.rss
- # http://hostname:8083/fhem/rss/myDeviceName.jpg?t=47110.815
- # |--------- url ----------| |---name --| ext |--query--|
- my ($request) = @_;
- # http://hostname:8083/fhem/rss/myDeviceName.rss
- # http://hostname:8083/fhem/rss/myDeviceName.jpg
- # http://hostname:8083/fhem/rss/myDeviceName.png
- # http://hostname:8083/fhem/rss/myDeviceName.html
- use constant REGEXP => '^.*\/rss\/([^\/]*)\.(jpg|png|rss|html)(\?(.*))?$';
- if($request =~ REGEXP) {
- return ($1,$2,$4);
- } else {
- #main::Debug "not matched";
- return(undef,undef,undef);
- }
- }
- ##################
- sub
- RSS_returnRSS($) {
- my ($name) = @_;
- my $url= RSS_getURL($name);
- my $type = $defs{$name}{fhem}{style};
- my $mime = ($type eq 'png')? 'image/png' : 'image/jpeg';
- my $now = time();
- my $itemTitle = AttrVal($name, "itemtitle", "");
- my $titleTag = ($itemTitle ne '')? '<title>'.$itemTitle.'</title>' : '';
- my $code = "<rss version='2.0' xmlns:media='http://search.yahoo.com/mrss/'><channel><title>$name</title><ttl>1</ttl><item>$titleTag<media:content url='$url/rss/$name.$type' type='$mime'/><guid isPermaLink='false'>item_$now</guid></item></channel></rss>";
-
- return ("application/xml; charset=utf-8", $code);
- }
- ##################
- sub
- RSS_getScript() {
- my $jsTemplate = '<script type="text/javascript" src="%s"></script>';
- my $scripts= "";
- if(defined($data{FWEXT})) {
- foreach my $k (sort keys %{$data{FWEXT}}) {
- my $h = $data{FWEXT}{$k};
- next if($h !~ m/HASH/ || !$h->{SCRIPT});
- my $script = $h->{SCRIPT};
- $script = ($script =~ m,^/,) ? "$FW_ME$script" : "$FW_ME/pgm2/$script";
- $scripts .= sprintf($jsTemplate, $script) . "\n";
- }
- }
- return $scripts;
- }
- sub
- RSS_HTMLHead($$) {
- my ($name,$refresh) = @_;
-
- my ($width,$height)= split(/x/, AttrVal($name,"size","800x600"));
- my $viewportContent= AttrVal($name, "viewport", "");
-
-
- my $doctype= '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">';
- my $xmlns= 'xmlns="http://www.w3.org/1999/xhtml"';
- my $scripts= RSS_getScript();
- my $viewport= $viewportContent eq "" ? "" : "<meta name=\"viewport\" content=\"$viewportContent\"/>\n";
- my $code= "$doctype\n<html $xmlns>\n<head>\n<title>$name</title>\n$viewport$scripts</head>\n";
- }
- sub
- RSS_HTMLTail() {
- return "</html>";
- }
- sub
- RSS_returnHTML($) {
- my ($name) = @_;
- my $url= RSS_getURL($name);
- my $type = $defs{$name}{fhem}{style};
- my $img= "$url/rss/$name.$type";
- my $refresh= AttrVal($name, 'refresh', 60);
- my $noscroll= AttrVal($name, 'noscroll', 0);
- my $overflow= $noscroll ? " style=\"overflow:hidden\"" : "";
- my $areas= AttrVal($name, 'areas', "");
- my $embed= $defs{$name}{".embed"};
- my $r= "";
- if(defined($refresh) && ($refresh> 0)) {
- my $handler= "\"setTimeout(function(){reloadImage(\'img0\')},$refresh*1000);\"";
- $r= " onload=$handler onerror=$handler";
- }
- my $code= RSS_HTMLHead($name, $refresh) .
- "<body topmargin=\"0\" leftmargin=\"0\" margin=\"0\" padding=\"0\"$overflow>\n" .
- "<div id=\"rss_$name\" style=\"z-index:1;\" >\n" .
- "<img id=\"img0\" src=\"$img\" usemap=\"#map\"$r/>\n" .
- "<map name=\"map\" id=\"map\">\n$areas\n</map>\n" .
- "</div>\n" .
- "$embed\n" .
- "</body>\n" .
- RSS_HTMLTail();
- return ("text/html; charset=utf-8", $code);
- }
- ##################
- # Library
- ##################
- sub
- RSS_xy {
- my ($S,$x,$y,%params)= @_;
-
- $x = $params{x} if($x eq 'x');
- $y = $params{y} if($y eq 'y');
-
- if((-1 < $x) && ($x < 1)) { $x*= $S->width; }
- if((-1 < $y) && ($y < 1)) { $y*= $S->height; }
-
- return($x,$y);
- }
- sub
- RSS_color {
- my ($S,$rgb)= @_;
- my $alpha = 0;
- my @d= split("", $rgb);
- if(length($rgb) == 8) {
- $alpha = hex("$d[6]$d[7]");
- $alpha = ($alpha < 127) ? $alpha : 127;
- }
- return $S->colorAllocateAlpha(hex("$d[0]$d[1]"),hex("$d[2]$d[3]"),hex("$d[4]$d[5]"),$alpha);
- }
- sub
- RSS_itemText {
- my ($S,$x,$y,$text,%params)= @_;
- return unless(defined($text));
- if($params{useTextAlign}) {
- my $align = GD::Text::Align->new($S,
- color => RSS_color($S, $params{rgb}),
- valign => $params{tvalign},
- halign => $params{thalign},
- );
- $align->set_font($params{font}, $params{pt});
- $align->set_text($text);
- $align->draw($x, $y, 0);
- } else {
- $S->stringFT(RSS_color($S,$params{rgb}),$params{font},$params{pt},0,$x,$y,$text);
- }
- }
- sub
- RSS_itemTextBox {
- my ($S,$x,$y,$boxwidth,$bgcolor,$text,%params)= @_;
- return unless(defined($text));
-
- if($params{useTextWrap}) {
- if((0 < $boxwidth) && ($boxwidth < 1)) { $boxwidth*= $S->width; }
- my $wrapbox = GD::Text::Wrap->new($S,
- color => RSS_color($S, $params{rgb}),
- line_space => $params{linespace},
- text => $text,
- );
- $wrapbox->set_font($params{font}, $params{pt});
- $wrapbox->set(align => $params{thalign}, width => $boxwidth);
- my ($left, $top, $right, $bottom);
- ($left, $top, $right, $bottom) = $wrapbox->get_bounds($x,$y);
- $S->filledRectangle($left,$top,$right,$bottom,RSS_color($S,$bgcolor)) if(defined($bgcolor));
- ($left, $top, $right, $bottom) = $wrapbox->draw($x, $y);
- return $bottom;
- } else {
- RSS_itemText($S,$x,$y,$text,%params);
- return $y;
- }
- }
- sub
- RSS_itemTime {
- my ($S,$x,$y,%params)= @_;
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
- RSS_itemText($S,$x,$y,sprintf("%02d:%02d", $hour, $min),%params);
- }
- sub
- RSS_itemSeconds {
- my ($S,$x,$y,$format,%params)= @_;
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
- if ($format eq "colon")
- {
- RSS_itemText($S,$x,$y,sprintf(":%02d", $sec),%params);
- }
- else
- {
- RSS_itemText($S,$x,$y,sprintf("%02d", $sec),%params);
- }
- }
- sub
- RSS_itemDate {
- my ($S,$x,$y,%params)= @_;
- my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
- RSS_itemText($S,$x,$y,sprintf("%02d.%02d.%04d", $mday, $mon+1, $year+1900),%params);
- }
- sub
- RSS_itemImg {
- my ($S,$x,$y,$scale,$imgtype,$srctype,$arg,%params)= @_;
- return unless(defined($arg));
- return if($arg eq "");
- my $I;
- if($srctype eq "url" || $srctype eq "urlq") {
- my $data;
- if($srctype eq "url") {
- $data= GetFileFromURL($arg,3,undef,1);
- } else {
- $data= GetFileFromURLQuiet($arg,3,undef,1);
- }
- if($imgtype eq "gif") {
- $I= GD::Image->newFromGifData($data);
- } elsif($imgtype eq "png") {
- $I= GD::Image->newFromPngData($data);
- } elsif($imgtype eq "jpeg") {
- $I= GD::Image->newFromJpegData($data);
- } else {
- return;
- }
- } elsif($srctype eq "file") {
- if($imgtype eq "gif") {
- $I= GD::Image->newFromGif($arg);
- } elsif($imgtype eq "png") {
- $I= GD::Image->newFromPng($arg);
- } elsif($imgtype eq "jpeg") {
- $I= GD::Image->newFromJpeg($arg);
- } else {
- return;
- }
- } elsif($srctype eq "data") {
- if($imgtype eq "gif") {
- $I= GD::Image->newFromGifData($arg);
- } elsif($imgtype eq "png") {
- $I= GD::Image->newFromPngData($arg);
- } elsif($imgtype eq "jpeg") {
- $I= GD::Image->newFromJpegData($arg);
- } else {
- return;
- }
- } else {
- return;
- }
- eval {
- my ($width,$height)= $I->getBounds();
- if ($scale =~ s/([wh])([\d]*)/$2/) { # get the digit from width/hight to pixel entry
- #Debug "RSS scale $scale (1: $1 / 2: $2)contais px after Digit - width: $width / height: $height";
- if ($1 eq "w") {
- $scale=$scale/$width;
- } else {
- $scale=$scale/$height;
- }
- }
- my ($swidth,$sheight)= (int($scale*$width), int($scale*$height));
- given ($params{ihalign}) {
- when('center') { $x -= $swidth/2; }
- when('right') { $x -= $swidth; }
- default { } # nothing to do
- }
- given ($params{ivalign}) {
- when('center') { $y -= $sheight/2; }
- when('base') { $y -= $sheight; }
- when('bottom') { $y -= $sheight; }
- default { } # nothing to do
- }
- #Debug "RSS placing $arg ($swidth x $sheight) at ($x,$y)";
- $S->copyResampled($I,$x,$y,0,0,$swidth,$sheight,$width,$height);
- };
- if($@) {
- Log3 undef, 2, "RSS: cannot create image $srctype $imgtype '$arg': $@";
- }
- }
- sub
- RSS_itemLine {
- my ($S,$x1,$y1,$x2,$y2,$th,%params)= @_;
- $S->setThickness($th);
- $S->line($x1,$y1,$x2,$y2,RSS_color($S,$params{rgb}));
- }
- sub
- RSS_itemRect {
- my ($S,$x1,$y1,$x2,$y2,$filled,%params)= @_;
- $x2 = $x1 + $x2 if ($x2 =~ /^\+/);
- $y2 = $y1 + $y2 if ($y2 =~ /^\+/);
- if($filled) {
- $S->filledRectangle($x1,$y1,$x2,$y2,RSS_color($S,$params{rgb}));
- } else {
- $S->rectangle($x1,$y1,$x2,$y2,RSS_color($S,$params{rgb}));
- }
- }
- ##################
- sub
- RSS_evalLayout($$@) {
- my ($S,$name,$layout)= @_;
- my @layout= split("\n", $layout);
- my %pstack;
- my $pstackcount = 0;
- my %params;
- $params{font}= "Arial";
- $params{pt}= 12;
- $params{rgb}= "ffffff";
- $params{halign} = 'left';
- $params{valign} = 'base';
- $params{condition} = 1;
- # we need two pairs of align parameters
- # due to different default values for text and img
- $params{useTextAlign}= $defs{$name}{fhem}{useTextAlign};
- $params{useTextWrap}= $defs{$name}{fhem}{useTextWrap};
- $params{ihalign} = 'left';
- $params{ivalign} = 'top';
- $params{thalign} = 'left';
- $params{tvalign} = 'base';
- $params{linespace} = 0;
- $params{x}= 0;
- $params{y}= 0;
-
- $defs{$name}{".embed"}= "";
-
- my ($x,$y,$z,$x1,$y1,$x2,$y2,$scale,$bgcolor,$boxwidth,$text,$imgtype,$srctype,$arg,$format);
- my $cont= "";
- foreach my $line (@layout) {
- # kill trailing newline
- chomp $line;
- # kill comments and blank lines
- $line=~ s/\#.*$//;
- $line=~ s/\s+$//;
- $line= $cont . $line;
- if($line=~ s/\\$//) { $cont= $line; undef $line; }
- next unless($line);
- $cont= "";
- #Debug "$name: evaluating >$line<";
- # split line into command and definition
- my ($cmd, $def)= split("[ \t]+", $line, 2);
- #Debug "CMD= \"$cmd\", DEF= \"$def\"";
-
- # separate condition handling
- if($cmd eq 'condition') {
- $params{condition} = AnalyzePerlCommand(undef, $def);
- next;
- }
- next unless($params{condition});
-
- #Debug "before command $line: x= " . $params{x} . ", y= " . $params{y};
- eval {
- if($cmd eq "rgb") {
- $def= "\"$def\"" if(length($def) == 6 && $def =~ /[[:xdigit:]]{6}/);
- $params{rgb}= AnalyzePerlCommand(undef, $def);
- } elsif($cmd eq "font") {
- $params{font}= $def;
- } elsif($cmd eq "pt") {
- $def= AnalyzePerlCommand(undef, $def);
- if($def =~ m/^[+-]/) {
- $params{pt} += $def;
- } else {
- $params{pt} = $def;
- }
- $params{pt} = 6 if($params{pt} < 0);
- } elsif($cmd eq "moveto") {
- my ($tox,$toy)= split('[ \t]+', $def, 2);
- my ($x,$y)= RSS_xy($S, $tox,$toy,%params);
- $params{x} = $x;
- $params{y} = $y;
- } elsif($cmd eq "moveby") {
- my ($byx,$byy)= split('[ \t]+', $def, 2);
- my ($x,$y)= RSS_xy($S, $byx,$byy,%params);
- $params{x} += $x;
- $params{y} += $y;
- } elsif($cmd ~~ @cmd_halign) {
- my $d = AnalyzePerlCommand(undef, $def);
- if($d ~~ @valid_halign) {
- $params{ihalign}= $d unless($cmd eq "thalign");
- $params{thalign}= $d unless($cmd eq "ihalign");
- } else {
- Log3 $name, 2, "$name: Illegal horizontal alignment $d";
- }
- } elsif($cmd ~~ @cmd_valign) {
- my $d = AnalyzePerlCommand(undef, $def);
- if( $d ~~ @valid_valign) {
- $params{ivalign}= $d unless($cmd eq "tvalign");
- $params{tvalign}= $d unless($cmd eq "ivalign");
- } else {
- Log3 $name, 2, "$name: Illegal vertical alignment $d";
- }
- } elsif($cmd eq "linespace") {
- $params{linespace}= $def;
- } elsif($cmd eq "text") {
- ($x,$y,$text)= split("[ \t]+", $def, 3);
- ($x,$y)= RSS_xy($S, $x,$y,%params);
- $params{x} = $x;
- $params{y} = $y;
- my $txt= AnalyzePerlCommand(undef, $text);
- #Debug "$name: ($x,$y) $txt";
- RSS_itemText($S,$x,$y,$txt,%params);
- } elsif($cmd eq "textbox") {
- ($x,$y,$boxwidth,$text)= split("[ \t]+", $def, 4);
- ($x,$y)= RSS_xy($S, $x,$y,%params);
- my $txt= AnalyzePerlCommand(undef, $text);
- $y= RSS_itemTextBox($S,$x,$y,$boxwidth,undef,$txt,%params);
- $params{x} = $x;
- $params{y} = $y;
- } elsif($cmd eq "textboxf") {
- ($x,$y,$boxwidth,$bgcolor,$text)= split("[ \t]+", $def, 5);
- ($x,$y)= RSS_xy($S, $x,$y,%params);
- $bgcolor = ($bgcolor ne "") ? AnalyzePerlCommand(undef,$bgcolor) : undef;
- my $txt= AnalyzePerlCommand(undef, $text);
- $y= RSS_itemTextBox($S,$x,$y,$boxwidth,$bgcolor,$txt,%params);
- $params{x} = $x;
- $params{y} = $y;
- } elsif($cmd eq "line") {
- ($x1,$y1,$x2,$y2,$format)= split("[ \t]+", $def, 5);
- ($x1,$y1)= RSS_xy($S, $x1,$y1,%params);
- ($x2,$y2)= RSS_xy($S, $x2,$y2,%params);
- $format //= 1; # set format to 1 as default thickness for the line
- RSS_itemLine($S,$x1,$y1,$x2,$y2, $format,%params);
- } elsif($cmd eq "rect") {
- ($x1,$y1,$x2,$y2,$format)= split("[ \t]+", $def, 5);
- ($x1,$y1)= RSS_xy($S, $x1,$y1,%params);
- ($x2,$y2)= RSS_xy($S, $x2,$y2,%params);
- $format //= 0; # set format to 0 as default (not filled)
- RSS_itemRect($S,$x1,$y1,$x2,$y2, $format,%params);
- } elsif($cmd eq "time") {
- ($x,$y)= split("[ \t]+", $def, 2);
- ($x,$y)= RSS_xy($S, $x,$y,%params);
- $params{x} = $x;
- $params{y} = $y;
- RSS_itemTime($S,$x,$y,%params);
- } elsif($cmd eq "seconds") {
- ($x,$y,$format) = split("[ \+]", $def,3);
- ($x,$y)= RSS_xy($S, $x,$y,%params);
- $params{x} = $x;
- $params{y} = $y;
- RSS_itemSeconds($S,$x,$y,$format,%params);
- } elsif($cmd eq "date") {
- ($x,$y)= split("[ \t]+", $def, 2);
- ($x,$y)= RSS_xy($S, $x,$y,%params);
- $params{x} = $x;
- $params{y} = $y;
- RSS_itemDate($S,$x,$y,%params);
- } elsif($cmd eq "img") {
- ($x,$y,$scale,$imgtype,$srctype,$arg)= split("[ \t]+", $def,6);
- ($x,$y)= RSS_xy($S, $x,$y,%params);
- $params{x} = $x;
- $params{y} = $y;
- my $arg= AnalyzePerlCommand(undef, $arg);
- RSS_itemImg($S,$x,$y,$scale,$imgtype,$srctype,$arg,%params);
- } elsif($cmd eq "push") {
- $pstackcount++;
- while ( my ($key, $value) = each(%params) ) {
- $pstack{$pstackcount}{$key} = $value;
- }
- } elsif($cmd eq "pop") {
- return unless $pstackcount;
- while ( my ($key, $value) = each(%{$pstack{$pstackcount}}) ) {
- $params{$key} = $value;
- }
- delete $pstack{$pstackcount};
- $pstackcount--;
- } elsif($cmd eq "embed") {
- ($x,$y,$z,$format,$text,$arg) = split("[ \t]+", $def,6);
- ($x,$y)= RSS_xy($S, $x,$y,%params);
- my $arg= AnalyzePerlCommand(undef, $arg);
- $defs{$name}{".embed"} .= "<div id=\"$text\" style=\"position:".$format."; left:".$x."px; top:".$y."px; z-index:$z;\">\n";
- $defs{$name}{".embed"} .= $arg."\n";
- $defs{$name}{".embed"} .= "</div>\n";
- #main::Debug "SET EMBED=" . $defs{$name}{".embed"};
- } else {
- Log3 $name, 2, "$name: Illegal command $cmd in layout definition.";
- }
-
- #Debug "after command $line: x= " . $params{x} . ", y= " . $params{y};
- };
- if($@) {
- my $msg= "$name: Error from line \'$line\' in layout definition: $@";
- chomp $msg;
- Log3 $name, 2, $msg;
- }
- }
- }
- ##################
- sub
- RSS_returnIMG($$) {
- my ($name,$type)= @_;
- my ($width,$height)= split(/x/, AttrVal($name,"size","800x600"));
- #
- # increase counter
- #
- if(defined($defs{$name}{fhem}) && defined($defs{$name}{fhem}{counter})) {
- $defs{$name}{fhem}{counter}++;
- } else {
- $defs{$name}{fhem}{counter}= 1;
- }
- # true color
- GD::Image->trueColor(1);
-
- #
- # create the image
- #
- our $S;
- # let's create a blank image, we will need it in most cases.
- $S= GD::Image->newTrueColor($width,$height);
- my $bgcolor = AttrVal($name,'bgcolor','000000'); #default bg color = black
- $bgcolor = RSS_color($S, $bgcolor);
- # $S->colorAllocate(0,0,0); # other colors seem not to work (issue with GD)
- $S->fill(0,0,$bgcolor);
- # wrap to make problems with GD non-lethal
- eval {
- #
- # set the background
- #
- # check if background directory is set
- my $reason= "?"; # remember reason for undefined image
- my $bgdir= AttrVal($name,"bg","undef");
- if(defined($bgdir)){
- my $bgnr; # item number
- if(defined($defs{$name}{fhem}) && defined($defs{$name}{fhem}{bgnr})) {
- $bgnr= $defs{$name}{fhem}{bgnr};
- } else {
- $bgnr= 0;
- }
- # check if at least tmin seconds have passed
- my $t0= 0;
- my $tmin= AttrVal($name,"tmin",0);
- if(defined($defs{$name}{fhem}) && defined($defs{$name}{fhem}{t})) {
- $t0= $defs{$name}{fhem}{t};
- }
- my $t1= time();
- if($t1-$t0>= $tmin) {
- $defs{$name}{fhem}{t}= $t1;
- $bgnr++;
- }
- # detect pictures
- if(opendir(BGDIR, $bgdir)){
- my @bgfiles= grep {$_ !~ /^\./} readdir(BGDIR);
-
- #foreach my $f (@bgfiles) {
- # Debug sprintf("File \"%s\"\n", $f);
- #}
- closedir(BGDIR);
- # get item number
- if($#bgfiles>=0) {
- if($bgnr > $#bgfiles) { $bgnr= 0; }
- $defs{$name}{fhem}{bgnr}= $bgnr;
- my $bgfile= $bgdir . "/" . $bgfiles[$bgnr];
- my $filetype =(split(/\./,$bgfile))[-1];
- my $bg;
- $bg= newFromGif GD::Image($bgfile) if $filetype =~ m/^gif$/i;
- $bg= newFromJpeg GD::Image($bgfile) if $filetype =~ m/^jpe?g$/i;
- $bg= newFromPng GD::Image($bgfile) if $filetype =~ m/^png$/i;
- if(defined($bg)) {
- my ($bgwidth,$bgheight)= $bg->getBounds();
- if($bgwidth != $width or $bgheight != $height) {
- # we need to resize
- my ($w,$h);
- my ($u,$v)= ($bgwidth/$width, $bgheight/$height);
- if($u>$v) {
- $w= $width;
- $h= $bgheight/$u;
- } else {
- $h= $height;
- $w= $bgwidth/$v;
- }
- $S->copyResized($bg,($width-$w)/2,($height-$h)/2,0,0,$w,$h,$bgwidth,$bgheight);
- } else {
- # size is as required
- # kill the predefined image and take the original
- undef $S;
- $S= $bg;
- }
- } else {
- undef $S;
- $reason= "Something was wrong with background image \"$bgfile\".";
- }
- }
- }
- }
- #
- # evaluate layout
- #
- if(defined($S)) {
- RSS_evalLayout($S, $name, $defs{$name}{fhem}{layout});
- } else {
- Log3 $name, 2, "$name: Could not create image. $reason";
- $S= GD::Image->newTrueColor($width,$height); # return empty image
- }
- $defs{$name}{STATE} = localtime();
-
- }; #warn $@ if $@;
- if($@) {
- my $msg= $@;
- chomp $msg;
- Log3 $name, 2, $msg;
- }
-
- #
- # return image
- #
- return ("image/jpeg; charset=utf-8", $S->jpeg) if($type eq 'jpg');
- return ("image/png; charset=utf-8", $S->png) if($type eq 'png');
- }
-
- ##################
- #
- # here we answer any request to http://host:port/fhem/rss and below
- sub
- RSS_CGI(){
- my ($request) = @_; # /rss or /rss/name.rss or /rss/name.jpg or /rss/name.png
-
- my ($name,$ext,$query)= RSS_splitRequest($request); # name, ext (rss, jpg, png, html), query
- # query is unused
-
- #main::Debug "Request: $request";
- #main::Debug " Name : $name";
- #main::Debug " Ext : $ext";
- #main::Debug " Query : $query";
- if(defined($name)) {
- if($ext eq "") {
- return("text/plain; charset=utf-8", "Illegal extension.");
- }
- if(!defined($defs{$name})) {
- return("text/plain; charset=utf-8", "Unknown RSS device: $name");
- }
-
- if($ext eq "jpg") {
- return RSS_returnIMG($name,'jpg');
- } elsif($ext eq "png") {
- return RSS_returnIMG($name,'png');
- } elsif($ext eq "rss") {
- return RSS_returnRSS($name);
- } elsif($ext eq "html") {
- return RSS_returnHTML($name);
- }
- } else {
- return RSS_Overview();
- }
- }
- sub
- plotFromUrl(@)
- {
- my (@plotName) = @_;
- my @webs;
-
- @webs=devspec2array("TYPE=FHEMWEB");
- foreach(@webs) {
- if(!InternalVal($_,'TEMPORARY',undef)) {
- $FW_wname=InternalVal($_,'NAME','');
- last;
- }
- }
- my ($w, $h) = split(",", AttrVal($plotName[0],"plotsize","800,160"));
- my $url;
- $url = "<embed src=\"".
- "$FW_ME/SVG_showLog?dev=". $plotName[0].
- "&logdev=". InternalVal($plotName[0], "LOGDEVICE", "").
- "&gplotfile=". InternalVal($plotName[0], "GPLOTFILE", "").
- "&logfile=". InternalVal($plotName[0], "LOGFILE", "CURRENT");
- $url .= "&pos=". $plotName[1] if $plotName[1];
- $url .= "&zoom=". $plotName[2] if $plotName[2];
- $url .= "\"";
- $url .= " type=\"image/svg+xml\"";
- $url .= " width=\"$w\"";
- $url .= " height=\"$h\"";
- $url .= " id=\"".$plotName[0]."\" >";
- return $url;
- }
- #
- 1;
- =pod
- =item helper
- =item summary Provides a freely configurable RSS feed and HTML page.
- =item summary_DE Stellt frei konfigurierbaren RSS-Feed und HTML-Seite bereit.
- =begin html
- <a name="RSS"></a>
- <h3>RSS</h3>
- <ul>
- Provides a freely configurable RSS feed and HTML page.<p>
- The media RSS feed delivers status pictures either in JPEG or PNG format.
-
- This media RSS feed can be used to feed a status display to a
- network-enabled photo frame.<p>
-
- In addition, a periodically refreshing HTML page is generated that shows the picture
- with an optional HTML image map.<p>
- You need to have the perl module <code>GD</code> installed. This module is most likely not
- available for small systems like Fritz!Box.<p>
- RSS is an extension to <a href="#FHEMWEB">FHEMWEB</a>. You must install FHEMWEB to use RSS.<p>
-
- Beginners might find the <a href="http://forum.fhem.de/index.php/topic,22520.0.html">RSS Workshop</a> useful.<p>
-
- A note on colors: Colors are specified as 6- or 8-digit hex numbers,
- every 2 digits determining the red, green and blue color components as in HTML
- color codes. The optional 7th and 8th digit code the alpha channel (transparency from
- 00 to 7F). Examples: <code>FF0000</code> for red, <code>C0C0C0</code> for light
- gray, <code>1C1C1C40</code> for semi-transparent gray.<p>
- <a name="RSSdefine"></a>
- <b>Define</b>
- <ul>
- <code>define <name> RSS jpg|png <hostname> <filename></code><br><br>
- Defines the RSS feed. <code>jpg</code> and <code>png</code> are fixed literals to select output format.
- <code><hostname></code> is the hostname of the fhem server as
- seen from the consumer of the RSS feed. <code><filename></code> is the
- name of the file that contains the <a href="RSSlayout">layout definition</a>.<p>
- Examples
- <ul>
- <code>define FrameRSS RSS jpg host.example.org /etc/fhem/layout</code><br>
- <code>define MyRSS RSS png 192.168.1.222 /var/fhem/conf/layout.txt</code><br>
- </ul>
- <br>
- The RSS feeds are at
- <ul>
- <code>http://host.example.org:8083/fhem/rss/FrameRSS.rss</code><br>
- <code>http://192.168.1.222:8083/fhem/rss/MyRSS.rss</code><br>
- </ul>
- <br>
-
- The pictures are at
- <ul>
- <code>http://host.example.org:8083/fhem/rss/FrameRSS.jpg</code><br>
- <code>http://192.168.1.222:8083/fhem/rss/MyRSS.png</code><br>
- </ul>
- <br>
-
- The HTML pages are at
- <ul>
- <code>http://host.example.org:8083/fhem/rss/FrameRSS.html</code><br>
- <code>http://192.168.1.222:8083/fhem/rss/MyRSS.html</code><br>
- </ul>
- <br>
-
- </ul>
- <a name="RSSset"></a>
- <b>Set</b>
- <ul>
- <code>set <name> rereadcfg</code>
- <br><br>
- Rereads the <a href="RSSlayout">layout definition</a> from the file. Useful to enable
- changes in the layout on-the-fly.
- <br><br>
- </ul>
- <a name="RSSattr"></a>
- <b>Attributes</b>
- <br><br>
- <ul>
- <li>autoreread<br>If set to 1, layout is automatically reread when layout file has been changed
- by FHEMWEB file editor.</li><br>
- <li>size<br>The dimensions of the picture in the format
- <code><width>x<height></code>.</li><br>
- <li>bg<br>The directory that contains the background pictures (must be in JPEG, GIF or PNG format, file
- format is guessed from file name extension).</li><br>
- <li>bgcolor <color><br>Sets the background color. </li><br>
- <li>tmin<br>The background picture is shown at least <code>tmin</code> seconds,
- no matter how frequently the RSS feed consumer accesses the page.</li><br>
- <li>refresh <interval><br>Time in seconds after which the HTML page is automatically reloaded. Defaults to 60.
- Set <interval> to 0 to disable reloading.</li><br>
- <li>viewport<br>Adds a viewport directive to the HTML header.<br>
- Example: <code>attr FrameRSS viewport width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0</code><br>
- This scales the image to fit to the browser's viewport and inhibits zooming in or out on tablets.
- </li><br>
- <li>noscroll</br>Suppresses scrollbars in browsers, if set to 1.
- </li><br>
- <li>areas<br>HTML code that goes into the image map.<br>
- Example: <code>attr FrameRSS areas <area shape="rect" coords="0,0,200,200" href="http://fhem.de"/><area shape="rect" coords="600,400,799,599" href="http://has:8083/fhem" target="_top"/></code>
- </li><br>
- <li>itemtitle</br>Adds a title tag to the RSS item that contains the specified text.
- </li><br>
- <li>urlOverride<br>Overrides the URL in the generated feed.
- If you specify
- <code>attr <name> http://otherhost.example.org:8083/foo/bar</code>, the
- JPEG picture that is at
- <code>http://host.example.org:8083/fhem/rss/FrameRSS.jpg</code>
- will be referenced as
- <code>http://otherhost.example.org:8083/foo/bar/rss/FrameRSS.jpg</code>. This is useful when
- your FHEM URLs are rewritten, e.g. if FHEM is accessed by a Reverse Proxy.</li>
- <br>
- </ul>
- <br><br>
- <b>Usage information</b>
- <br><br>
- <ul>
- If a least one RSS feed is defined, the menu entry <code>RSS</code> appears in the FHEMWEB
- side menu. If you click it you get a list of all defined RSS feeds. The URL of any such is
- RSS feed is <code>http://hostname:port/fhem/rss/name.rss</code> with <code>hostname</code> and
- <code>name</code> from the RSS feed's <a href="RSSdefine">definition</a> and the <code>port</code>
- (usually 8083) and literal <code>/fhem</code> from the underlying <a href="#FHEMWEB">FHEMWEB</a>
- definition.<p>
- Example:
- <ul><code>http://host.example.org:8083/fhem/rss/FrameRSS.rss</code></ul><p>
- The media RSS feed points to a dynamically generated picture. The URL of the picture
- belonging to the RSS can be found by replacing the extension ".rss" in feed's URL by ".jpg" or ".png"
- depending on defined output format,<p>
- Example:
- <ul><code>http://host.example.org:8083/fhem/rss/FrameRSS.jpg</code></ul><p>
- <ul><code>http://192.168.100.200:8083/fhem/rss/FrameRSS.png</code></ul><p>
- To render the picture the current, or, if <code>tmin</code> seconds have elapsed, the next
- JPEG picture from the directory <code>bg</code> is chosen and scaled to the dimensions given
- in <code>size</code>. The background is black if no usable JPEG picture can be found. Next the
- script in the <a href="RSSlayout">layout definition</a> is used to superimpose items on
- the background.<p>
- You can directly access the URL of the picture in your browser. Reload the page to see
- how it works.<p>
- The media RSS feed advertises to refresh after 1 minute (ttl). Some photo frames ignore it and
- use their preset refresh rate. Go for a photo frame with an adjustable refresh rate (e.g
- every 5 seconds) if you have the choice!<p>
- This is how the fhem config part might look like:<p>
- <code>
- define ui FHEMWEB 8083 global<br><br>
- define FrameRSS RSS jpg host.example.org /etc/fhem/layout<br>
- attr FrameRSS size 800x600<br>
- attr FrameRSS bg /usr/share/pictures<br>
- attr FrameRSS tmin 10<br>
- </code>
- </ul>
- <a name="RSSlayout"></a>
- <b>Layout definition</b>
- <br><br>
- <ul>
- The layout definition is a script for placing items on the background. It is read top-down.
- It consists of layout control commands and items placement commands. Layout control
- commands define the appearance of subsequent items. Item placement commands actually
- render items.<p>
- Everything after a # is treated as a comment and ignored. You can fold long lines by
- putting a \ at the end.<p>
- <i>General notes</i><br>
- <ol>
- <li>Use double quotes to quote literal text if perl specials are allowed.</li>
- <li>Text alignment requires the Perl module GD::Text::Align to be installed. Text wrapping (in text boxes) require GD::Text::Wrap to be installed. Debian-based systems can install both with <code>apt-get install libgd-text-perl</code>.</li>
- </ol>
- <p>
- <i>Notes on coordinates</i><br>
- <ol>
- <li>(0,0) is the upper left corner.</li>
- <li>Coordinates equal or greater than 1 are considered to be absolute pixels, coordinates between 0 and 1 are considered to
- be relative to the total width or height of the picture.</li>
- <li>Literal <code>x</code> and <code>y</code> evaluate to the most recently used x- and y-coordinate. See also moveto and moveby below.</li>
- <!--<li>You can use <code>{ <a href="#perl"><perl special></a> }</code> for x and for y.</li>-->
- </ol>
- <p>
-
-
- <i>Layout control commands</i><p>
-
- <ul>
- <li>moveto <x> <y><br>Moves most recently used x- and y-coordinate to the given absolute or relative position.</li><br>
- <li>moveby <x> <y><br>Moves most recently used x- and y-coordinate by the given absolute or relative amounts.</li><br>
-
- <li>font "<font>"<br>Sets the font. <font> is the name of a TrueType font (e.g.
- <code>Arial</code>) or the full path to a TrueType font
- (e.g. <code>/usr/share/fonts/truetype/arial.ttf</code>),
- whatever works on your system.</li><br>
- <a name="rss_rgb"></a>
- <li>rgb "<color>"<br>Sets the color. You can use
- <code>{ <a href="#perl"><perl special></a> }</code> for <color>.</li><br>
- <li>pt <pt><br>Sets the font size in points. A + or - sign in front of the the number given
- for <pt> signifies a change of the font size relative to the current size. Otherwise the absolute
- size is set. You can use
- <code>{ <a href="#perl"><perl special></a> }</code> for <pt>.</li><br>
-
- <li>thalign|ihalign|halign "left"|"center"|"right"<br>Sets the horizontal alignment of text, image or both. Defaults to left-aligned. You can use
- <code>{ <a href="#perl"><perl special></a> }</code> instead of the literal alignment control word.</li><br>
-
- <li>tvalign|ivalign|valign "top"|"center"|"base"|"bottom"<br>Sets the vertical alignment of text, image or both. Defaults to base-aligned for text and
- top-aligned for image. You can use
- <code>{ <a href="#perl"><perl special></a> }</code> instead of the literal alignment control word.</li><br>
-
- <li>linespace <space><br>Sets the line spacing in pixels for text boxes (see textbox item below).</li><br>
-
- <li>condition <condition><br>Subsequent layout control and item placement commands except for another condition command are ignored if and only if <condition> evaluates to false.</li><br>
-
- <li>push<br>The current parameter set (position, color, font name and size, text alignment and line spacing) is
- put (saved) on top of a stack.</li><br>
-
- <li>pop<br>The most recently saved (pushed) current parameter set is pulled from the top of the stack and restored.</li><br>
-
- </ul>
- <i>Item placement commands</i><p>
- <ul>
- <li>text <x> <y> <text><br>Renders the text <text> at the
- position (<x>, <y>) using the current font, font size and color.
- You can use
- <code>{ <a href="#perl"><perl special></a> }</code> for <text> to fully
- access device readings and do some programming on the fly. See below for examples.</li><br>
- <li>textbox <x> <y> <boxwidth> <text><br>Same as before but text is rendered
- in a box of horizontal width <boxwidth>.</li><br>
-
- <li>textboxf <x> <y> <boxwidth> <bgcolor> <text><br>Same as before but
- the textbox will be filled with the given background color <bgcolor> before drawing the text.
- <bgcolor> can be used with <code>{ <a href="#perl"><perl special></a> }</code> to evalute <a href="#rss_rgb">RGB</a> value.</li><br>
-
- <li>time <x> <y><br>Renders the current time in HH:MM format.</li><br>
-
- <li>seconds <x> <y> <format><br>Renders the curent seconds. Maybe useful for a RSS Clock.</li><br>
-
- <li>date <x> <y><br>Renders the current date in DD.MM.YYYY format.</li><br>
-
- <li>line <x1> <y1> <x2> <y2> [<thickness>]<br>Draws a line from position (<x1>, <y1>) to position (<x2>, <y2>) with optional thickness (default=1).</li><br>
- <li>rect <x1> <y1> <x2> <y2> [<filled>]<br>Draws a rectangle with corners at positions (<x1>, <y1>) and (<x2>, <y2>), which is filled if the <filled> parameter is set and not zero.<br>If x2 or y2 is preceeded with a + (plus sign) then the coordinate is relative to x1 or y1, or in other words, it is the width-1 or height-1 of the rectangle, respectively.</li><br>
-
- <li>img <x> <y> <['w' or 'h']s> <imgtype> <srctype> <arg> <br>Renders a picture at the
- position (<x>, <y>). The <imgtype> is one of <code>gif</code>, <code>jpeg</code>, <code>png</code>.
- The picture is scaled by the factor <s> (a decimal value). If 'w' or 'h' is in front of scale-value the value is used to set width or height to the value in pixel. If <srctype> is <code>file</code>, the picture
- is loaded from the filename <arg>, if <srctype> is <code>url</code> or <code>urlq</code>, the picture
- is loaded from the URL <arg> (with or without logging the URL), if <srctype> is <code>data</code>, the picture
- is piped in from data <arg>. You can use
- <code>{ <a href="#perl"><perl special></a> }</code> for <arg>. See below for example.<br>
- <b>Warning</b>: do not load the image from URL that is served by fhem as it leads to a deadlock.</li><br>
- <li>embed <x> <y> <z> <position> <id> <element><br>
- For HTML output: embeds a <code>div</code> element into the HTML page at (<x>,<y>) with z-order <z> and positioning <position> (use <code>absolute</code>). <id> is the <code>id</code> attribute of the
- <code>div</code> element and <element> is its content.<br>
- <b>Note:</b> There are several issues with different browsers when using this.</li><br>
-
- </ul>
- <i>Example</i><p>
- This is how a layout definition might look like:<p>
- <code>
- font /usr/share/fonts/truetype/arial.ttf # must be a TrueType font<br>
- rgb "c0c0c0" # HTML color notation, RGB<br>
- pt 48 # font size in points<br>
- time 0.10 0.90<br>
- pt 24<br>
- text 0.10 0.95 { ReadingsVal("MyWeather","temperature","?"). "C" }<br>
- moveby 0 -25<br>
- text x y "Another text"<br>
- img 20 530 0.5 png file { "/usr/share/fhem/www/images/weather/" . ReadingsVal("MyWeather","icon","") . ".png" }<br>
- embed 0 0 2 absolute plot1 { plotFromUrl('mySVG') }
- embed 10 200 2 absolute iframe1 "<iframe width=\"420\" height=\"315\" src=\"//www.youtube.com/embed/9HShl_ufOFI\" frameborder=\"0\" allowfullscreen></iframe>"
- </code>
- <p>
-
- <i>Special uses</i><p>
-
- You can display <a href="#SVG">SVG</a> plots with the aid of the helper function <code>plotAsPng(<name>[,<zoom>[,<offset>]])</code> (in 98_SVG.pm). Examples:<p>
- <code>
- img 20 30 0.6 png data { plotAsPng("mySVGPlot") }<BR>
- img 20 30 0.6 png data { plotAsPng("mySVGPlot","qday",-1) }
- </code>
- <p>
- This requires the perl module Image::LibRSVG and librsvg. Debian-based systems can install these with <code>apt-get install libimage-librsvg-perl</code>.<p>
-
- For HTML output, you can use <code>plotFromURL(<name>[,<zoom>[,<offset>]])</code> instead.
- </ul>
- </ul>
- =end html
- =cut
|