| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241 |
- #
- #
- # 02_RSS.pm
- # written by Dr. Boris Neubert 2012-03-24
- # e-mail: omega at online dot de
- #
- ##############################################
- # $Id: 02_RSS.pm 12529 2016-11-08 15:02:11Z borisneubert $
- 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)= @_;
- 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.</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
|