2017-02-07 16:10:16 +00:00
|
|
|
|
# $Id$
|
|
|
|
|
|
|
|
|
|
=for comment
|
2015-01-26 15:13:11 +00:00
|
|
|
|
##############################################
|
|
|
|
|
#
|
|
|
|
|
# 55_InfoPanel.pm written by betateilchen
|
|
|
|
|
#
|
|
|
|
|
# forked from 02_RSS.pm by Dr. Boris Neubert
|
|
|
|
|
#
|
|
|
|
|
##############################################
|
2015-02-13 23:08:22 +00:00
|
|
|
|
#
|
|
|
|
|
# This module uses vTicker,
|
|
|
|
|
# a jQuery plug-in that adds scrolling vertical tickers
|
|
|
|
|
#
|
|
|
|
|
# vTicker is published under MIT and BSD licenses
|
|
|
|
|
#
|
|
|
|
|
# Copyright (c) 2009–2011
|
|
|
|
|
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
|
# of this software and associated documentation files (the "Software"), to deal
|
|
|
|
|
# in the Software without restriction, including without limitation the rights
|
|
|
|
|
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
|
|
|
# copies of the Software, and to permit persons to whom the Software is
|
|
|
|
|
# furnished to do so, subject to the following conditions:
|
|
|
|
|
# The above copyright notice and this permission notice shall be included in
|
|
|
|
|
# all copies or substantial portions of the Software.
|
|
|
|
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
|
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
|
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
|
|
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
|
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
|
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
|
|
|
# THE SOFTWARE.
|
|
|
|
|
#
|
|
|
|
|
##############################################
|
2015-02-14 12:16:52 +00:00
|
|
|
|
#
|
|
|
|
|
# 2015-02-06 - 7892 - module moved from ./contrib to ./FHEM
|
|
|
|
|
# 2015-02-08 - 7921 - changed: additional modules are optional
|
|
|
|
|
# 2015-02-10 - 7931 - added: direct link to circle,ellipse,rect
|
|
|
|
|
# 2015-02-11 - 7933 - added: item counter
|
|
|
|
|
# 2015-02-11 - 7944 - added: items push/pop
|
|
|
|
|
# 2015-02-12 - 7947 - changed: turtle added to new elements
|
2015-02-25 10:33:21 +00:00
|
|
|
|
# 2015-02-14 - 7967 - added: item ticker
|
2015-02-14 12:16:52 +00:00
|
|
|
|
# changed: img syntax
|
2015-02-25 10:33:21 +00:00
|
|
|
|
# 2015-02-15 - 7989 - added: item embed
|
2015-02-15 17:07:26 +00:00
|
|
|
|
# 7995 - added: xcondition (can be overridden by set)
|
2015-02-15 13:11:13 +00:00
|
|
|
|
# set ovClear,ovDisable,ovEnable
|
|
|
|
|
# get counter, layout, overrides
|
2015-02-16 12:28:29 +00:00
|
|
|
|
# - removed: trashcan due to performance issues
|
2015-02-15 17:07:26 +00:00
|
|
|
|
# - added: break condition for includes
|
2015-02-25 10:33:21 +00:00
|
|
|
|
# 2015-02-24 - 8092 - added: longpoll support (experimental)
|
2015-03-07 19:38:33 +00:00
|
|
|
|
# 2015-02-25 - 8095 - changed: iframe handling for secret div
|
2015-03-22 16:40:46 +00:00
|
|
|
|
# 2015-03-07 - 8168 - fixed: handling for bg img (Bugzilla #8)
|
2015-03-29 18:53:39 +00:00
|
|
|
|
# 2015-03-22 - 8268 - added: attribute showTime
|
|
|
|
|
# 2015-03-24 - 8281 - added: BACK as special link to return
|
2015-03-24 12:41:28 +00:00
|
|
|
|
# to $FW_httpheader{Referer}
|
|
|
|
|
# changed: limit refresh to at least 60 secs
|
|
|
|
|
# to prevent performance issues
|
2015-03-29 18:53:39 +00:00
|
|
|
|
# 2015-03-29 - 8334 - changed: commandref updated
|
2015-09-25 12:25:49 +00:00
|
|
|
|
# 2015-09-25 - - changed: support ReadingsVal() in ticker
|
|
|
|
|
# with \n in text
|
2023-05-12 14:08:48 +00:00
|
|
|
|
#
|
2016-09-04 11:30:54 +00:00
|
|
|
|
# 2016-09-04 - 12114 - added: movecalculated
|
2023-05-12 14:08:48 +00:00
|
|
|
|
# 2016-11-05 - 12506 - changed: fix perl 5.24 compatibility (each on hash)
|
|
|
|
|
#
|
|
|
|
|
# 2017-01-09 - 13023 - added: attribute mobileApp
|
|
|
|
|
# 2017-02-19 - 13454 - added: csrf token (featureLevel 5.8)
|
|
|
|
|
# 2017-12-27 - 15708 - added: create empty layout file on define if nonexistent
|
2015-02-14 12:16:52 +00:00
|
|
|
|
#
|
2018-05-28 09:19:51 +00:00
|
|
|
|
# 2018-05-06 - 16695 - changed: check plotName exists
|
2023-05-12 14:08:48 +00:00
|
|
|
|
# 2018-05-28 - 16791 - changed: remove misleading link in commandref
|
|
|
|
|
#
|
|
|
|
|
# 2019-05-30 - 19497 - added: meta tag to prevent translation popup in google
|
2018-05-06 11:44:25 +00:00
|
|
|
|
#
|
2023-05-12 14:08:48 +00:00
|
|
|
|
# 2023-02-20 - 27257 - added: show alias in overview
|
|
|
|
|
# 2023-05-12 - 27557 - added: support for named parameters in define
|
|
|
|
|
# for new define syntax
|
2023-07-04 17:45:32 +00:00
|
|
|
|
# 2023-06-10 - 27670 - changed: commandref updated to id syntax
|
|
|
|
|
#
|
|
|
|
|
# 2023-07-04 - 27724 - changed: minor bugfix for perl 5.36
|
2023-05-12 13:56:45 +00:00
|
|
|
|
#
|
2024-04-05 10:57:56 +00:00
|
|
|
|
# 2024-04-05 - 28756 - changed: remove smartmatch issues
|
2024-04-05 10:57:20 +00:00
|
|
|
|
#
|
2015-02-14 12:16:52 +00:00
|
|
|
|
##############################################
|
2017-02-07 16:10:16 +00:00
|
|
|
|
=cut
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2021-02-04 20:02:42 +00:00
|
|
|
|
package main;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
use strict;
|
|
|
|
|
use warnings;
|
|
|
|
|
|
2021-02-04 19:41:41 +00:00
|
|
|
|
#use Data::Dumper;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2024-04-05 10:57:20 +00:00
|
|
|
|
#use feature qw/switch/;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
use vars qw(%data);
|
2021-02-04 20:02:42 +00:00
|
|
|
|
use HttpUtils;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
my @valid_valign = qw(auto baseline middle center hanging);
|
|
|
|
|
my @valid_halign = qw(start middle end);
|
2021-02-04 20:02:42 +00:00
|
|
|
|
|
2015-02-08 20:34:48 +00:00
|
|
|
|
my $useImgTools = 1;
|
|
|
|
|
|
2024-04-05 10:57:20 +00:00
|
|
|
|
#no if $] >= 5.017011, warnings => 'experimental';
|
2021-02-04 20:02:42 +00:00
|
|
|
|
|
|
|
|
|
sub btIP_Define;
|
|
|
|
|
sub btIP_Undef;
|
|
|
|
|
sub btIP_Set;
|
|
|
|
|
sub btIP_Get;
|
|
|
|
|
sub btIP_Notify;
|
|
|
|
|
sub btIP_readLayout;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
sub btIP_itemArea;
|
2015-01-29 18:06:51 +00:00
|
|
|
|
sub btIP_itemButton;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_itemCircle;
|
2015-02-11 01:04:52 +00:00
|
|
|
|
sub btIP_itemCounter;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_itemDate;
|
|
|
|
|
sub btIP_itemEllipse;
|
2015-01-29 19:59:02 +00:00
|
|
|
|
sub btIP_itemGroup;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_itemImg;
|
|
|
|
|
sub _btIP_imgData;
|
|
|
|
|
sub _btIP_imgRescale;
|
|
|
|
|
sub btIP_itemLine;
|
2015-02-24 23:16:01 +00:00
|
|
|
|
sub btIP_itemLongpoll;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_itemPlot;
|
|
|
|
|
sub btIP_itemRect;
|
|
|
|
|
sub btIP_itemSeconds;
|
|
|
|
|
sub btIP_itemText;
|
|
|
|
|
sub btIP_itemTextBox;
|
2015-02-14 17:38:55 +00:00
|
|
|
|
sub btIP_itemTicker;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_itemTime;
|
2015-02-10 11:09:21 +00:00
|
|
|
|
|
2015-02-12 21:59:58 +00:00
|
|
|
|
sub btIP_changeColor;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_color;
|
2015-02-12 21:59:58 +00:00
|
|
|
|
sub btIP_FileRead;
|
2015-02-10 11:09:21 +00:00
|
|
|
|
sub btIP_findTarget;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_xy;
|
|
|
|
|
|
2015-02-11 01:04:52 +00:00
|
|
|
|
sub btIP_ReturnSVG;
|
|
|
|
|
sub btIP_evalLayout;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2015-02-11 01:04:52 +00:00
|
|
|
|
sub btIP_addExtension;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_CGI;
|
2015-02-11 01:04:52 +00:00
|
|
|
|
sub btIP_splitRequest;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2015-02-11 01:04:52 +00:00
|
|
|
|
sub btIP_returnHTML;
|
|
|
|
|
sub btIP_HTMLHead;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_getScript;
|
|
|
|
|
sub btIP_HTMLTail;
|
|
|
|
|
sub btIP_Overview;
|
2015-01-31 10:45:37 +00:00
|
|
|
|
sub btIP_getURL;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2021-02-04 20:02:42 +00:00
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
######################################
|
|
|
|
|
|
2021-02-04 20:02:42 +00:00
|
|
|
|
sub InfoPanel_Initialize {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my ($hash) = @_;
|
2015-02-08 20:34:48 +00:00
|
|
|
|
|
2020-03-31 12:20:27 +00:00
|
|
|
|
## no critic
|
|
|
|
|
eval "use MIME::Base64" ;
|
2015-02-08 20:34:48 +00:00
|
|
|
|
$useImgTools = 0 if($@);
|
|
|
|
|
Log3(undef,4,"InfoPanel: MIME::Base64 missing.") unless $useImgTools;
|
|
|
|
|
eval "use Image::Info qw(image_info dim)";
|
|
|
|
|
$useImgTools = 0 if($@);
|
|
|
|
|
Log3(undef,4,"InfoPanel: Image::Info missing.") unless $useImgTools;
|
2020-03-31 12:20:27 +00:00
|
|
|
|
## use critic
|
2015-02-08 20:34:48 +00:00
|
|
|
|
|
2021-02-04 20:02:42 +00:00
|
|
|
|
$hash->{DefFn} = "btIP_Define";
|
|
|
|
|
$hash->{UndefFn} = "btIP_Undef";
|
|
|
|
|
$hash->{SetFn} = "btIP_Set";
|
|
|
|
|
$hash->{GetFn} = "btIP_Get";
|
|
|
|
|
$hash->{NotifyFn} = "btIP_Notify";
|
2015-09-28 19:48:40 +00:00
|
|
|
|
$hash->{AttrList} = "autoreread:1,0 useViewPort:1,0 bgcolor refresh size ";
|
2017-01-09 13:00:24 +00:00
|
|
|
|
$hash->{AttrList} .= "mobileApp:none,apple,other ";
|
2015-09-28 19:48:40 +00:00
|
|
|
|
$hash->{AttrList} .= "title noscript showTime:1,0 ";
|
2015-02-08 20:34:48 +00:00
|
|
|
|
$hash->{AttrList} .= " bgcenter:1,0 bgdir bgopacity tmin" if $useImgTools;
|
|
|
|
|
|
2020-03-31 18:53:47 +00:00
|
|
|
|
return;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-04 20:02:42 +00:00
|
|
|
|
sub btIP_Define {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my ($hash, $def) = @_;
|
2023-05-12 13:56:45 +00:00
|
|
|
|
my $name = $hash->{NAME};
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$hash->{NOTIFYDEV} = 'global';
|
2015-01-28 12:34:47 +00:00
|
|
|
|
$hash->{fhem}{div} = '';
|
2023-05-12 13:56:45 +00:00
|
|
|
|
|
|
|
|
|
my ($unnamedParams,$namedParams) = parseParams($def);
|
|
|
|
|
|
|
|
|
|
if ($unnamedParams->[2]) {
|
|
|
|
|
$hash->{LAYOUTFILE} = $unnamedParams->[2];
|
|
|
|
|
} elsif ($namedParams->{layout}) {
|
|
|
|
|
$hash->{LAYOUTFILE} = $namedParams->{layout};
|
|
|
|
|
} else {
|
|
|
|
|
return "Usage: define <name> InfoPanel layout=layoutFileName";
|
|
|
|
|
}
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2021-02-04 20:02:42 +00:00
|
|
|
|
btIP_addExtension("btIP_CGI","btip","InfoPanel");
|
|
|
|
|
btIP_readLayout($hash);
|
2015-02-13 23:31:26 +00:00
|
|
|
|
|
2015-02-11 01:04:52 +00:00
|
|
|
|
readingsSingleUpdate($hash,'state','defined',1);
|
2020-03-31 18:53:47 +00:00
|
|
|
|
return;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-04 20:02:42 +00:00
|
|
|
|
sub btIP_Undef {
|
2015-01-31 12:50:35 +00:00
|
|
|
|
my ($hash, $arg) = @_;
|
|
|
|
|
# check if last device
|
|
|
|
|
my $url = '/btip';
|
2015-02-04 21:56:44 +00:00
|
|
|
|
delete $data{FWEXT}{$url} if int(devspec2array('TYPE=InfoPanel')) == 1;
|
2020-03-31 18:53:47 +00:00
|
|
|
|
return;
|
2015-01-31 12:50:35 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-04 20:02:42 +00:00
|
|
|
|
sub btIP_Set {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
my ($hash, @a) = @_;
|
|
|
|
|
my $name = $a[0];
|
|
|
|
|
|
2015-02-15 13:11:13 +00:00
|
|
|
|
my $usage= "Unknown argument, choose one of reread:noArg ovClear ovEnable ovDisable";
|
|
|
|
|
my $ret = undef;
|
2024-04-05 10:57:20 +00:00
|
|
|
|
my $cmd = $a[1];
|
2015-02-15 13:11:13 +00:00
|
|
|
|
|
2024-04-05 10:57:20 +00:00
|
|
|
|
if ($cmd eq "ovClear") {
|
|
|
|
|
if ($a[2] eq "all") {
|
|
|
|
|
delete $defs{$name}{fhem}{override};
|
|
|
|
|
} else {
|
|
|
|
|
delete $defs{$name}{fhem}{override}{$a[2]};
|
|
|
|
|
}
|
|
|
|
|
} elsif ($cmd eq "ovDisable") {
|
|
|
|
|
$defs{$name}{fhem}{override}{$a[2]} = 0;
|
|
|
|
|
} elsif ($cmd eq "ovEnable") {
|
|
|
|
|
$defs{$name}{fhem}{override}{$a[2]} = 1;
|
|
|
|
|
} elsif ($cmd eq "reread") {
|
|
|
|
|
btIP_readLayout($hash);
|
|
|
|
|
} else {
|
|
|
|
|
$ret = $usage;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
2015-02-15 13:11:13 +00:00
|
|
|
|
return $ret;
|
|
|
|
|
}
|
|
|
|
|
|
2021-02-04 20:02:42 +00:00
|
|
|
|
sub btIP_Get {
|
2015-02-15 13:11:13 +00:00
|
|
|
|
|
|
|
|
|
my ($hash, @a) = @_;
|
|
|
|
|
my $name = $a[0];
|
|
|
|
|
|
|
|
|
|
my $usage= "Unknown argument, choose one of reread:noArg counter:noArg layout:noArg overrides:noArg";
|
|
|
|
|
my $ret = undef;
|
2024-04-05 10:57:20 +00:00
|
|
|
|
my $cmd = $a[1];
|
|
|
|
|
|
|
|
|
|
if ($cmd eq "counter") {
|
|
|
|
|
$ret = $defs{$name}{fhem}{counter};
|
|
|
|
|
} elsif ($cmd eq "layout") {
|
|
|
|
|
$ret = $defs{$name}{fhem}{layout};
|
|
|
|
|
} elsif ($cmd eq "overrides") {
|
|
|
|
|
last if(!defined($defs{$name}{fhem}{override}));
|
|
|
|
|
foreach my $key ( keys %{$defs{$name}{fhem}{override}} ) {
|
|
|
|
|
$ret .= "$key => $defs{$name}{fhem}{override}{$key} \n";
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$ret = $usage;
|
|
|
|
|
}
|
2015-02-15 13:11:13 +00:00
|
|
|
|
return $ret;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-04 20:02:42 +00:00
|
|
|
|
sub btIP_Notify {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my ($hash,$dev) = @_;
|
|
|
|
|
|
|
|
|
|
return unless AttrVal($hash->{NAME},'autoreload',1);
|
|
|
|
|
return if($dev->{NAME} ne "global");
|
|
|
|
|
return if(!grep(m/^FILEWRITE $hash->{LAYOUTFILE}$/, @{$dev->{CHANGED}}));
|
|
|
|
|
|
|
|
|
|
Log3(undef, 4, "InfoPanel: $hash->{NAME} reread layout after edit.");
|
2023-07-04 17:20:27 +00:00
|
|
|
|
btIP_readLayout($hash);
|
2020-03-31 18:53:47 +00:00
|
|
|
|
return;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-04 20:02:42 +00:00
|
|
|
|
sub btIP_readLayout {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my ($hash)= @_;
|
2015-01-31 10:45:37 +00:00
|
|
|
|
my $filename= $hash->{LAYOUTFILE};
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my $name= $hash->{NAME};
|
2015-02-15 17:07:26 +00:00
|
|
|
|
my $level = 0;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
my ($err, @layoutfile) = FileRead($filename);
|
|
|
|
|
if($err) {
|
2017-12-27 15:01:42 +00:00
|
|
|
|
# Log 1, "InfoPanel $name: $err";
|
|
|
|
|
# $hash->{fhem}{layout} = "text ERROR 50 50 \"Error on reading layout!\"";
|
2021-02-04 20:02:42 +00:00
|
|
|
|
Log 1, "InfoPanel $name: $err";
|
2015-02-10 11:09:21 +00:00
|
|
|
|
$hash->{fhem}{layout} = "text ERROR 50 50 \"Error on reading layout!\"";
|
2017-12-27 15:01:42 +00:00
|
|
|
|
my ($e,@layout) = FileRead('./FHEM/template.layout');
|
|
|
|
|
unless ($e){
|
|
|
|
|
FileWrite($filename,@layout);
|
|
|
|
|
$hash->{fhem}{layout} = "text ERROR 50 50 \"Please edit layoutfile now.\"";
|
|
|
|
|
}
|
2015-01-26 15:13:11 +00:00
|
|
|
|
} else {
|
2015-01-28 12:34:47 +00:00
|
|
|
|
$hash->{fhem}{layout} = join("\n", @layoutfile);
|
2015-02-15 17:07:26 +00:00
|
|
|
|
while($hash->{fhem}{layout} =~ m/\@include/ && $level < 1000) {
|
|
|
|
|
$level++;
|
2015-01-28 12:34:47 +00:00
|
|
|
|
my (@layout2,@include);
|
|
|
|
|
foreach my $ll (@layoutfile) {
|
|
|
|
|
if($ll !~ m/^\@include/) {
|
|
|
|
|
push(@layout2,$ll);
|
2015-02-13 19:13:29 +00:00
|
|
|
|
} elsif ($ll =~ m/^\@include/) {
|
|
|
|
|
my ($cmd, $def) = split("[ \t]+", $ll, 2);
|
2015-01-28 12:34:47 +00:00
|
|
|
|
($err,@include) = FileRead($def) if($def);
|
|
|
|
|
splice(@layout2,-1,0,@include) unless $err;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@layoutfile = @layout2;
|
|
|
|
|
@layout2 = undef;
|
|
|
|
|
$hash->{fhem}{layout} = join("\n",@layoutfile);
|
|
|
|
|
}
|
2015-02-15 17:07:26 +00:00
|
|
|
|
while($hash->{fhem}{layout} =~ m/\@finclude/ && $level < 1000) {
|
|
|
|
|
$level++;
|
2015-02-13 19:13:29 +00:00
|
|
|
|
my (@layout2,@include);
|
|
|
|
|
foreach my $ll (@layoutfile) {
|
|
|
|
|
if($ll !~ m/^\@finclude/) {
|
|
|
|
|
push(@layout2,$ll);
|
|
|
|
|
} else {
|
|
|
|
|
my ($cmd, $def) = split("[ \t]+", $ll, 2);
|
|
|
|
|
@include = split("\n",AnalyzePerlCommand(undef,$def));
|
|
|
|
|
splice(@layout2,-1,0,@include);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
@layoutfile = @layout2;
|
|
|
|
|
@layout2 = undef;
|
|
|
|
|
$hash->{fhem}{layout} = join("\n",@layoutfile);
|
|
|
|
|
}
|
2015-02-15 17:07:26 +00:00
|
|
|
|
$hash->{fhem}{layout} = "text ERROR 50 50 \"Loop detected in includes!\"" if ($level >= 1000);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$hash->{fhem}{layout} =~ s/\n\n/\n/g;
|
|
|
|
|
}
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
##################
|
|
|
|
|
#
|
|
|
|
|
# Layout evaluation
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
##### Items
|
|
|
|
|
|
|
|
|
|
sub btIP_itemArea {
|
2015-02-25 10:33:21 +00:00
|
|
|
|
my ($id,$x1,$y1,$x2,$y2,$link,$target,%params)= @_;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
2015-02-10 11:09:21 +00:00
|
|
|
|
|
|
|
|
|
my $oldrgb = $params{rgb};
|
|
|
|
|
$params{rgb} = '00000000';
|
2015-02-25 10:33:21 +00:00
|
|
|
|
my $output = btIP_itemRect($id,$x1,$y1,$x2,$y2,0,0,1,0,$link,$target,%params);
|
2015-02-10 11:09:21 +00:00
|
|
|
|
$params{rgb} = $oldrgb;
|
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
return $output;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-29 18:06:51 +00:00
|
|
|
|
sub btIP_itemButton {
|
|
|
|
|
my ($id,$x1,$y1,$x2,$y2,$rx,$ry,$link,$text,%params)= @_;
|
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
|
|
|
|
my $width = $x2 - $x1;
|
|
|
|
|
my $height = $y2 - $y1;
|
2015-02-11 01:04:47 +00:00
|
|
|
|
|
|
|
|
|
my $oldrgb = $params{rgb};
|
|
|
|
|
$params{rgb} = $params{boxcolor};
|
2015-02-25 10:33:21 +00:00
|
|
|
|
my $output = btIP_itemRect($id,$x1,$y1,$x2,$y2,$rx,$ry,1,0,$link,undef,%params);
|
2015-02-11 01:04:47 +00:00
|
|
|
|
$params{rgb} = $oldrgb;
|
2015-01-29 18:06:51 +00:00
|
|
|
|
|
2015-02-12 10:03:17 +00:00
|
|
|
|
my ($oldhalign,$oldvalign) = ($params{thalign},$params{tvalign});
|
|
|
|
|
($params{thalign},$params{tvalign}) = ("middle","middle");
|
2015-02-11 01:04:47 +00:00
|
|
|
|
my $textoutput .= btIP_itemText("${id}_text",($x1+$x2)/2,($y1+$y2)/2,$text,%params);
|
2015-02-12 10:03:17 +00:00
|
|
|
|
($params{thalign},$params{tvalign}) = ($oldhalign,$oldvalign);
|
2015-01-29 18:06:51 +00:00
|
|
|
|
|
2015-02-11 01:04:47 +00:00
|
|
|
|
$output =~ s/<\/a>/$textoutput<\/a>/;
|
2015-01-29 18:06:51 +00:00
|
|
|
|
return $output;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_itemCircle {
|
2015-02-10 11:09:21 +00:00
|
|
|
|
my ($id,$x,$y,$r,$filled,$stroked,$link,%params)= @_;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
2015-02-10 11:09:21 +00:00
|
|
|
|
my $target;
|
|
|
|
|
($link,$target) = btIP_findTarget($link);
|
|
|
|
|
my $output = "";
|
|
|
|
|
$output .= "<a xlink:href=\"$link\" target=\"$target\">\n" if($link && length($link));
|
|
|
|
|
$output .= "<circle id=\”$id\” cx=\"$x\" cy=\"$y\" r=\"$r\" ";
|
2015-02-08 21:05:23 +00:00
|
|
|
|
if($filled > 0 || $stroked > 0) {
|
|
|
|
|
$output .= "style=\"";
|
|
|
|
|
if($filled > 0) {
|
|
|
|
|
my ($r,$g,$b,$a) = btIP_color($params{rgb});
|
|
|
|
|
$output .= "fill:rgb($r,$g,$b); fill-opacity:$a; ";
|
|
|
|
|
}
|
|
|
|
|
if($stroked > 0) {
|
|
|
|
|
my ($r,$g,$b,$a) = btIP_color($params{rgb});
|
|
|
|
|
$output .= "stroke:rgb($r,$g,$b); stroke-width:$stroked; ";
|
|
|
|
|
$output .= "fill:none; " if ($filled == 0);
|
|
|
|
|
}
|
|
|
|
|
$output .= "\" ";
|
2015-02-08 21:26:42 +00:00
|
|
|
|
} else {
|
|
|
|
|
$output .= "style=\"fill:none; stroke-width:0; \" ";
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
$output .= "/>\n";
|
2015-02-10 11:09:21 +00:00
|
|
|
|
$output .= "</a>\n" if($link && length($link));
|
2015-01-26 15:13:11 +00:00
|
|
|
|
return $output;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-11 01:04:47 +00:00
|
|
|
|
sub btIP_itemCounter {
|
|
|
|
|
my ($id,$x,$y,%params)= @_;
|
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
2015-02-12 10:03:17 +00:00
|
|
|
|
return btIP_itemText($id,$x,$y,$params{counter},%params);
|
2015-02-11 01:04:47 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_itemDate {
|
|
|
|
|
my ($id,$x,$y,%params)= @_;
|
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
|
|
|
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
|
|
|
|
|
return btIP_itemText($id,$x,$y,sprintf("%02d.%02d.%04d", $mday, $mon+1, $year+1900),%params);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub btIP_itemEllipse {
|
2015-02-10 11:09:21 +00:00
|
|
|
|
my ($id,$x,$y,$rx,$ry,$filled,$stroked,$link,%params)= @_;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
2015-02-10 11:09:21 +00:00
|
|
|
|
my $target;
|
|
|
|
|
($link,$target) = btIP_findTarget($link);
|
|
|
|
|
my $output = "";
|
|
|
|
|
$output .= "<a xlink:href=\"$link\" target=\"$target\">\n" if($link && length($link));
|
|
|
|
|
$output .= "<ellipse $id=\"$id\" cx=\"$x\" cy=\"$y\" rx=\"$rx\" ry=\"$ry\" ";
|
2015-02-08 21:05:23 +00:00
|
|
|
|
if($filled > 0 || $stroked > 0) {
|
|
|
|
|
$output .= "style=\"";
|
|
|
|
|
if($filled > 0) {
|
|
|
|
|
my ($r,$g,$b,$a) = btIP_color($params{rgb});
|
|
|
|
|
$output .= "fill:rgb($r,$g,$b); fill-opacity:$a; ";
|
|
|
|
|
}
|
|
|
|
|
if($stroked > 0) {
|
|
|
|
|
my ($r,$g,$b,$a) = btIP_color($params{rgb});
|
|
|
|
|
$output .= "stroke:rgb($r,$g,$b); stroke-width:$stroked; ";
|
|
|
|
|
$output .= "fill:none; " if ($filled == 0);
|
|
|
|
|
}
|
|
|
|
|
$output .= "\" ";
|
2015-02-08 21:26:42 +00:00
|
|
|
|
} else {
|
|
|
|
|
$output .= "style=\"fill:none; stroke-width:0; \" ";
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
$output .= "/>\n";
|
2015-02-10 11:09:21 +00:00
|
|
|
|
$output .= "</a>\n" if($link && length($link));
|
2015-01-26 15:13:11 +00:00
|
|
|
|
return $output;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-14 22:07:48 +00:00
|
|
|
|
sub btIP_itemEmbed {
|
|
|
|
|
my ($id,$x,$y,$width,$height,$arg,%params) = @_;
|
|
|
|
|
|
|
|
|
|
my $embed = "<div id=\"${id}_embedded\" style=\"position:absolute; top:${y}px; left:${x}px; ".
|
|
|
|
|
"width:${width}px; height:${height}px; z-index:2; \" >\n".
|
|
|
|
|
"$arg\n".
|
|
|
|
|
"</div>\n";
|
|
|
|
|
return $embed;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_itemGroup {
|
2015-02-25 10:33:21 +00:00
|
|
|
|
my($id,$type,$x,$y,%params) = @_;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
return "</g>\n" if $type eq 'close';
|
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
2015-02-11 01:04:56 +00:00
|
|
|
|
return "<g id=\"$id\" transform=\"translate($x,$y)\" >\n" if $type eq 'open';
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub btIP_itemImg {
|
2015-02-08 20:34:48 +00:00
|
|
|
|
return unless $useImgTools;
|
2015-02-14 11:12:15 +00:00
|
|
|
|
my ($id,$x,$y,$scale,$link,$srctype,$arg,%params)= @_;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
|
|
|
|
return unless(defined($arg));
|
|
|
|
|
return if($arg eq "");
|
2015-02-01 13:36:06 +00:00
|
|
|
|
my ($counter,$data,$info,$width,$height,$mimetype,$output);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
if($srctype eq 'file') {
|
2015-02-06 11:50:35 +00:00
|
|
|
|
($counter,$data) = btIP_FileRead($arg);
|
|
|
|
|
return unless $counter;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
} elsif ($srctype eq "url" || $srctype eq "urlq") {
|
|
|
|
|
if($srctype eq "url") {
|
|
|
|
|
$data= GetFileFromURL($arg,3,undef,1);
|
|
|
|
|
} else {
|
|
|
|
|
$data= GetFileFromURLQuiet($arg,3,undef,1);
|
|
|
|
|
}
|
|
|
|
|
} elsif ($srctype eq 'data') {
|
|
|
|
|
$data = $arg;
|
|
|
|
|
} else {
|
2015-02-06 11:50:35 +00:00
|
|
|
|
Log3(undef,4,"InfoPanel: unknown sourcetype $srctype for image tag");
|
2015-01-26 15:13:11 +00:00
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-02 19:10:32 +00:00
|
|
|
|
($width,$height,$mimetype,undef) = _btIP_imgData($data,1);
|
|
|
|
|
if($mimetype eq 'image/svg+xml') {
|
|
|
|
|
if($data !~ m/viewBox/) {
|
|
|
|
|
$data =~ s/width=/viewBox="0 0 $width $height"\n\twidth=/;
|
|
|
|
|
}
|
|
|
|
|
($width,$height) = _btIP_imgRescale($width,$height,$scale);
|
|
|
|
|
$data =~ s/width=".*"/width="$width"/;
|
|
|
|
|
$data =~ s/height=".*"/height="$height"/;
|
|
|
|
|
$scale = 1;
|
|
|
|
|
(undef,undef,undef,$data) = _btIP_imgData($data,$scale);
|
|
|
|
|
} else {
|
|
|
|
|
($width,$height,$mimetype,$data) = _btIP_imgData($data,$scale);
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-11 01:04:56 +00:00
|
|
|
|
my $target;
|
|
|
|
|
($link,$target) = btIP_findTarget($link);
|
|
|
|
|
|
2015-02-02 17:22:06 +00:00
|
|
|
|
$output = "<!-- s: $scale w: $width h: $height t: $mimetype -->\n";
|
2015-02-11 01:04:56 +00:00
|
|
|
|
$output .= "<a xlink:href=\"$link\" target=\"$target\">\n" if($link && length($link));
|
2015-02-02 19:10:32 +00:00
|
|
|
|
$output .= "<image id=\"$id\" x=\"$x\" y=\"$y\" width=\"${width}px\" height=\"${height}px\" \nxlink:href=\"$data\" />\n";
|
2015-02-11 01:04:56 +00:00
|
|
|
|
$output .= "</a>\n" if($link && length($link));
|
|
|
|
|
|
2015-02-12 10:03:17 +00:00
|
|
|
|
return ($output,$width,$height);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub _btIP_imgData {
|
|
|
|
|
my ($arg,$scale) = @_;
|
|
|
|
|
my $info = image_info(\$arg);
|
|
|
|
|
my $width = $info->{width};
|
|
|
|
|
my $height = $info->{height};
|
2015-03-02 20:05:52 +00:00
|
|
|
|
$width =~ s/px//;
|
|
|
|
|
$height =~ s/px//;
|
2017-04-25 10:19:12 +00:00
|
|
|
|
$width =~ s/pt//;
|
|
|
|
|
$height =~ s/pt//;
|
2015-02-02 10:49:21 +00:00
|
|
|
|
($width,$height)= _btIP_imgRescale($width,$height,$scale);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my $mimetype = $info->{file_media_type};
|
2015-02-02 13:23:49 +00:00
|
|
|
|
|
|
|
|
|
if($FW_userAgent =~ m/Trident/ && $mimetype =~ m/svg/) {
|
|
|
|
|
$arg =~ s/width=".*"//g;
|
|
|
|
|
$arg =~ s/height=".*"//g;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my $data = "data:$mimetype;base64,".encode_base64($arg);
|
2015-02-01 13:36:06 +00:00
|
|
|
|
return ($width,$height,$mimetype,$data);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub _btIP_imgRescale {
|
|
|
|
|
my ($width,$height,$scale) = @_;
|
|
|
|
|
if ($scale =~ s/([whWH])([\d]*)/$2/) {
|
|
|
|
|
$scale = (uc($1) eq "W") ? $scale/$width : $scale/$height;
|
|
|
|
|
}
|
|
|
|
|
$width = int($scale*$width);
|
|
|
|
|
$height = int($scale*$height);
|
|
|
|
|
return ($width,$height);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub btIP_itemLine {
|
|
|
|
|
my ($id,$x1,$y1,$x2,$y2,$th,%params)= @_;
|
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
2015-02-14 17:38:55 +00:00
|
|
|
|
$th //= 1;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my ($r,$g,$b,$a) = btIP_color($params{rgb});
|
|
|
|
|
return "<line id=\"$id\" x1=\"$x1\" y1=\"$y1\" x2=\"$x2\" y2=\"$y2\" style=\"stroke:rgb($r,$g,$b); stroke-width:$th; stroke-opacity:$a; \" />\n";
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-24 23:16:01 +00:00
|
|
|
|
sub btIP_itemLongpoll {
|
|
|
|
|
my ($id,$x,$y,$text,%params)= @_;
|
2015-02-24 23:38:08 +00:00
|
|
|
|
my ($iconName,undef,undef) = FW_dev2image($id);
|
2020-03-31 12:20:27 +00:00
|
|
|
|
my $iconURL;
|
|
|
|
|
$iconURL = FW_IconURL($iconName) if defined($iconName);
|
2015-02-24 23:38:08 +00:00
|
|
|
|
my $color = substr($params{rgb},0,6);
|
2015-02-27 14:43:02 +00:00
|
|
|
|
my $opacity = hex(substr($params{rgb},6,2))/255;
|
2015-02-24 23:16:01 +00:00
|
|
|
|
my $output = "<div informId=\"$id\" style=\"position:absolute; top:${y}px; left:${x}px; ";
|
2015-02-27 14:43:02 +00:00
|
|
|
|
$output .= "font-family:$params{font}; font-size:$params{pt}; color:#$color; opacity:$opacity; " if defined($text);
|
2015-02-24 23:16:01 +00:00
|
|
|
|
$output .= "margin-top:0px; z-index:3; \" >\n";
|
2015-02-24 23:38:08 +00:00
|
|
|
|
$output .= "$text\n" if defined($text);
|
2015-02-24 23:16:01 +00:00
|
|
|
|
$output .= "<img src=\"$iconURL\">\n" unless defined($text);
|
|
|
|
|
$output .= "</div>\n";
|
|
|
|
|
|
|
|
|
|
$defs{$params{name}}{fhem}{div} .= $output;
|
|
|
|
|
return "";
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_itemPlot {
|
|
|
|
|
my ($id,$x,$y,$scale,$inline,$arg) = @_;
|
|
|
|
|
my (@plotName) = split(";",$arg);
|
2018-05-06 11:44:25 +00:00
|
|
|
|
return ("<!-- undefined plotDevice -->\n",undef,undef) unless defined($defs{$plotName[0]});
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
2015-02-02 17:22:06 +00:00
|
|
|
|
my (@webs,$width,$height,$newWidth,$newHeight,$output,$mimetype,$svgdata);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
@webs=devspec2array("TYPE=FHEMWEB");
|
|
|
|
|
foreach(@webs) {
|
|
|
|
|
if(!InternalVal($_,'TEMPORARY',undef)) {
|
|
|
|
|
$FW_wname=InternalVal($_,'NAME','');
|
|
|
|
|
last;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-08 20:34:48 +00:00
|
|
|
|
if(!$useImgTools) {
|
|
|
|
|
$scale = 1;
|
|
|
|
|
$inline = 0;
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-03 19:41:35 +00:00
|
|
|
|
($width,$height) = split(",", AttrVal($plotName[0],"plotsize","800,160"));
|
|
|
|
|
($newWidth,$newHeight) = _btIP_imgRescale($width,$height,$scale);
|
2015-02-02 17:22:06 +00:00
|
|
|
|
|
2015-02-04 19:50:40 +00:00
|
|
|
|
if($inline == 1) {
|
2015-02-05 09:26:42 +00:00
|
|
|
|
# embed base64 data
|
2015-02-02 17:22:06 +00:00
|
|
|
|
|
2015-02-04 19:50:40 +00:00
|
|
|
|
$FW_RET = undef;
|
|
|
|
|
$FW_webArgs{dev} = $plotName[0];
|
|
|
|
|
$FW_webArgs{logdev} = InternalVal($plotName[0], "LOGDEVICE", "");
|
|
|
|
|
$FW_webArgs{gplotfile} = InternalVal($plotName[0], "GPLOTFILE", "");
|
|
|
|
|
$FW_webArgs{logfile} = InternalVal($plotName[0], "LOGFILE", "CURRENT");
|
2015-02-05 09:26:42 +00:00
|
|
|
|
$FW_pos{zoom} = $plotName[1] if(length($plotName[1]));
|
|
|
|
|
$FW_pos{off} = $plotName[2] if(length($plotName[2]));
|
2015-02-04 19:50:40 +00:00
|
|
|
|
$FW_plotsize = "$newWidth,$newHeight";
|
2015-02-02 17:22:06 +00:00
|
|
|
|
|
2015-02-04 19:50:40 +00:00
|
|
|
|
($mimetype, $svgdata) = SVG_showLog("unused");
|
|
|
|
|
$svgdata =~ s/<\/svg>/<polyline opacity="0" points="0,0 $newWidth,$newHeight"\/><\/svg>/;
|
|
|
|
|
(undef,undef,undef,$svgdata) = _btIP_imgData($svgdata,1);
|
|
|
|
|
|
2015-02-11 01:04:47 +00:00
|
|
|
|
$output = "<!-- s: $scale ow: $width oh: $height nw: $newWidth nh: $newHeight t: $mimetype -->\n";
|
2015-02-04 19:50:40 +00:00
|
|
|
|
$output .= "<image id=\"$id\" x=\"$x\" y=\"$y\" width=\"${newWidth}px\" height=\"${newHeight}px\" \n";
|
|
|
|
|
$output .= "xlink:href=\"$svgdata\" />\n";
|
|
|
|
|
} else {
|
2015-02-05 09:26:42 +00:00
|
|
|
|
# embed link to plot
|
|
|
|
|
|
2015-02-04 19:50:40 +00:00
|
|
|
|
my $url;
|
|
|
|
|
$url = "$FW_ME/SVG_showLog?dev=". $plotName[0].
|
|
|
|
|
"&logdev=". InternalVal($plotName[0], "LOGDEVICE", "").
|
|
|
|
|
"&gplotfile=". InternalVal($plotName[0], "GPLOTFILE", "").
|
|
|
|
|
"&logfile=". InternalVal($plotName[0], "LOGFILE", "CURRENT").
|
|
|
|
|
"&plotsize=". "$newWidth,$newHeight";
|
2015-02-05 09:26:42 +00:00
|
|
|
|
$url .= "&pos=";
|
|
|
|
|
$url .= "zoom=". "$plotName[1];" if(length($plotName[1]));
|
|
|
|
|
$url .= "off=". $plotName[2] if(length($plotName[2]));
|
|
|
|
|
|
|
|
|
|
$output = "<!-- $url -->\n";
|
|
|
|
|
$output .= "<image id=\"$id\" x=\"$x\" y=\"$y\" width=\"${newWidth}px\" height=\"${newHeight}px\" \nxlink:href=\"$url\" />\n";
|
2015-02-04 19:50:40 +00:00
|
|
|
|
}
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2015-02-12 10:03:17 +00:00
|
|
|
|
return ($output,$newWidth,$newHeight);
|
2015-02-04 19:50:40 +00:00
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub btIP_itemRect {
|
2015-02-25 10:33:21 +00:00
|
|
|
|
my ($id,$x1,$y1,$x2,$y2,$rx,$ry,$filled,$stroked,$link,$target,%params)= @_;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
2015-02-25 10:33:21 +00:00
|
|
|
|
$target //= "";
|
|
|
|
|
($link,$target) = btIP_findTarget($link) unless ($target ne "");
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my $width = $x2 - $x1;
|
|
|
|
|
my $height = $y2 - $y1;
|
2015-02-12 21:59:58 +00:00
|
|
|
|
$filled //= 0;
|
|
|
|
|
$stroked //= 0;
|
2015-02-10 11:09:21 +00:00
|
|
|
|
my $output = "";
|
2015-02-11 01:04:47 +00:00
|
|
|
|
$output .= "<a id=\”${id}_link\” xlink:href=\"$link\" target=\"$target\">\n" if($link && length($link));
|
|
|
|
|
$output .= "<rect id=\”${id}_rect\” x=\"$x1\" y=\"$y1\" width=\"$width\" height=\"$height\" rx=\"$rx\" ry=\"$ry\" ";
|
2015-02-08 20:34:48 +00:00
|
|
|
|
if($filled > 0 || $stroked > 0) {
|
|
|
|
|
$output .= "style=\"";
|
|
|
|
|
if($filled > 0) {
|
|
|
|
|
my ($r,$g,$b,$a) = btIP_color($params{rgb});
|
|
|
|
|
$output .= "fill:rgb($r,$g,$b); fill-opacity:$a; ";
|
|
|
|
|
}
|
|
|
|
|
if($stroked > 0) {
|
|
|
|
|
my ($r,$g,$b,$a) = btIP_color($params{rgb});
|
|
|
|
|
$output .= "stroke:rgb($r,$g,$b); stroke-width:$stroked; ";
|
|
|
|
|
$output .= "fill:none; " if ($filled == 0);
|
|
|
|
|
}
|
|
|
|
|
$output .= "\" ";
|
2015-02-08 21:26:42 +00:00
|
|
|
|
} else {
|
|
|
|
|
$output .= "style=\"fill:none; stroke-width:0; \" ";
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
$output .= "/>\n";
|
2015-02-10 11:09:21 +00:00
|
|
|
|
$output .= "</a>\n" if($link && length($link));
|
2015-01-26 15:13:11 +00:00
|
|
|
|
return $output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub btIP_itemSeconds {
|
|
|
|
|
my ($id,$x,$y,$format,%params)= @_;
|
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
|
|
|
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
|
|
|
|
|
if ($format eq "colon")
|
|
|
|
|
{ return btIP_itemText($id,$x,$y,sprintf(":%02d", $sec),%params); }
|
|
|
|
|
else
|
|
|
|
|
{ return btIP_itemText($id,$x,$y,sprintf("%02d", $sec),%params); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub btIP_itemText {
|
|
|
|
|
my ($id,$x,$y,$text,%params)= @_;
|
|
|
|
|
return unless(defined($text));
|
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
|
|
|
|
my ($r,$g,$b,$a) = btIP_color($params{rgb});
|
|
|
|
|
|
2015-02-09 14:56:56 +00:00
|
|
|
|
my $output = "<text id=\”$id\” x=\"$x\" y=\"$y\" ".
|
|
|
|
|
"fill=\"rgb($r,$g,$b)\" fill-opacity=\"$a\" ".
|
|
|
|
|
"font-family=\"$params{font}\" ".
|
|
|
|
|
"font-style=\"$params{fontstyle}\" ".
|
|
|
|
|
"font-size=\"$params{pt}px\" ".
|
|
|
|
|
"font-weight=\"$params{fontweight}\" ".
|
|
|
|
|
"text-anchor=\"$params{thalign}\" ".
|
|
|
|
|
"text-decoration=\"$params{textdecoration}\" ".
|
|
|
|
|
"alignment-baseline=\"$params{tvalign}\" >\n".
|
|
|
|
|
"$text\n".
|
|
|
|
|
"</text>\n";
|
2015-01-26 15:13:11 +00:00
|
|
|
|
return $output;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub btIP_itemTextBox {
|
2015-02-06 18:45:02 +00:00
|
|
|
|
my ($id,$x,$y,$boxwidth,$boxheight,$text,$link,%params)= @_;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
return unless(defined($text));
|
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
2015-01-27 22:42:11 +00:00
|
|
|
|
my $color = substr($params{rgb},0,6);
|
2015-02-06 18:45:02 +00:00
|
|
|
|
$link =~ s/"//g;
|
2015-02-08 21:05:23 +00:00
|
|
|
|
my $target;
|
|
|
|
|
($link,$target) = btIP_findTarget($link);
|
2015-02-08 20:34:48 +00:00
|
|
|
|
|
2015-01-27 22:42:11 +00:00
|
|
|
|
my ($d,$output);
|
|
|
|
|
|
|
|
|
|
if(defined($params{boxcolor})) {
|
|
|
|
|
my $orgcolor = $params{rgb};
|
|
|
|
|
$params{rgb} = $params{boxcolor};
|
|
|
|
|
my $bx1 = $x - $params{padding};
|
|
|
|
|
my $by1 = $y - $params{padding};
|
|
|
|
|
my $bx2 = $x + $boxwidth + $params{padding};
|
|
|
|
|
my $by2 = $y + $boxheight + $params{padding};
|
2015-02-25 10:33:21 +00:00
|
|
|
|
$output .= btIP_itemRect("box_$id",$bx1,$by1,$bx2,$by2,1,1,1,0,undef,undef,%params);
|
2015-01-27 22:42:11 +00:00
|
|
|
|
$params{rgb} = $orgcolor;
|
2015-01-31 10:45:37 +00:00
|
|
|
|
} else {
|
|
|
|
|
$output = "";
|
2015-01-27 22:42:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-02-06 18:45:02 +00:00
|
|
|
|
$d = "<div id=\"text_$id\" style=\"position:absolute; top:".$y."px; left:".$x."px; ".
|
|
|
|
|
"width:".$boxwidth."px; height:".$boxheight."px; text-overflow:ellipsis; z-index:2\" >\n".
|
|
|
|
|
"<style type=\"text/css\">a {text-decoration: none;}</style>\n";
|
2015-02-07 18:29:59 +00:00
|
|
|
|
$d .= "<a href=\"$link\" target=\"$target\">\n" if($link && length($link));
|
2015-02-06 18:45:02 +00:00
|
|
|
|
$d .= "<p style=\"font-family:$params{font}; font-size:$params{pt}; color:#$color; ".
|
|
|
|
|
"width:".$boxwidth."px; height:".$boxheight."px; ".
|
|
|
|
|
"margin-top:0px; text-align:$params{tbalign}; text-overflow:ellipsis; ".
|
|
|
|
|
"\">\n$text\n</p>\n";
|
|
|
|
|
$d .= "</a>" if($link && length($link));
|
|
|
|
|
$d .= "</div>\n";
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2015-01-27 22:42:11 +00:00
|
|
|
|
$defs{$params{name}}{fhem}{div} .= $d;
|
|
|
|
|
|
|
|
|
|
return $output;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 23:08:22 +00:00
|
|
|
|
sub btIP_itemTicker {
|
2015-02-13 23:52:14 +00:00
|
|
|
|
my ($id,$x,$y,$width,$items,$speed,$arg,%params) = @_;
|
2015-02-13 23:08:22 +00:00
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
|
|
|
|
my $pause = 2 * $speed;
|
|
|
|
|
my $color = substr($params{rgb},0,6);
|
2015-09-25 12:25:49 +00:00
|
|
|
|
$arg =~ s/\\n/\n/g; # support ReadingsVal() with \n in text
|
2015-02-13 23:08:22 +00:00
|
|
|
|
my @a = split("\n",$arg);
|
|
|
|
|
my $liTemplate = '<li>%s</li>'."\n";
|
|
|
|
|
|
|
|
|
|
my $ticker = "<div id=\"${id}_tickercontent\" >\n".
|
|
|
|
|
"<script>\$(function() {\$('#${id}_ticker').vTicker('init', ".
|
|
|
|
|
"{speed: $speed, pause: $pause, mousePause:true, showItems: $items, padding:$params{padding}});});</script>\n".
|
|
|
|
|
"<div id=\"${id}_ticker\" style=\"position:relative; top:${y}px; left:${x}px; z-index:1; ".
|
2015-02-16 12:28:29 +00:00
|
|
|
|
"width:${width}px; text-align:$params{tbalign}; ".
|
2015-02-13 23:08:22 +00:00
|
|
|
|
"font-family:$params{font}; font-size:$params{pt}; color:#$color; \" >\n<ul>\n";
|
|
|
|
|
foreach (@a) {$ticker .= sprintf($liTemplate,$_)};
|
|
|
|
|
$ticker .= "</ul>\n</div>\n</div>\n";
|
2015-02-13 23:52:14 +00:00
|
|
|
|
|
2015-02-13 23:08:22 +00:00
|
|
|
|
return $ticker;
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
sub btIP_itemTime {
|
|
|
|
|
my ($id,$x,$y,%params)= @_;
|
|
|
|
|
$id = ($id eq '-') ? createUniqueId() : $id;
|
|
|
|
|
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time);
|
|
|
|
|
return btIP_itemText($id,$x,$y,sprintf("%02d:%02d", $hour, $min),%params);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
##### Helper
|
|
|
|
|
|
2015-02-03 14:56:17 +00:00
|
|
|
|
sub btIP_changeColor {
|
|
|
|
|
my($file,$oldcolor,$newcolor) = @_;
|
2015-02-06 11:50:35 +00:00
|
|
|
|
Log3(undef,4,"InfoPanel: read file $file for changeColor");
|
|
|
|
|
my ($counter,$data) = btIP_FileRead($file);
|
|
|
|
|
return unless $counter;
|
2015-02-04 22:08:59 +00:00
|
|
|
|
if($newcolor =~ /[[:xdigit:]]{6}/) {
|
2015-02-06 11:50:35 +00:00
|
|
|
|
Log3(undef,4,"InfoPanel: changing color from $oldcolor to $newcolor");
|
2015-02-04 22:08:59 +00:00
|
|
|
|
$data =~ s/fill="#$oldcolor"/fill="#$newcolor"/g;
|
2015-02-04 22:38:59 +00:00
|
|
|
|
$data =~ s/fill:#$oldcolor/fill:#$newcolor/g;
|
2015-02-04 22:08:59 +00:00
|
|
|
|
} else {
|
2015-02-06 11:50:35 +00:00
|
|
|
|
Log3(undef,4,"InfoPanel: invalid rgb value for changeColor!");
|
2015-02-04 22:08:59 +00:00
|
|
|
|
}
|
2015-02-03 14:56:17 +00:00
|
|
|
|
return $data;
|
|
|
|
|
}
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2015-02-12 21:59:58 +00:00
|
|
|
|
sub btIP_color {
|
|
|
|
|
my ($rgb)= @_;
|
|
|
|
|
my $alpha = 1;
|
|
|
|
|
my @d= split("", $rgb);
|
|
|
|
|
if(length($rgb) == 8) {
|
|
|
|
|
$alpha = hex("$d[6]$d[7]");
|
|
|
|
|
$alpha = $alpha/255;
|
|
|
|
|
}
|
|
|
|
|
return (hex("$d[0]$d[1]"),hex("$d[2]$d[3]"),hex("$d[4]$d[5]"),$alpha);
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-06 11:50:35 +00:00
|
|
|
|
sub btIP_FileRead {
|
|
|
|
|
my ($file) = @_;
|
|
|
|
|
my ($data,$counter);
|
|
|
|
|
|
|
|
|
|
Log3(undef,4,"InfoPanel: looking for img $file");
|
|
|
|
|
|
|
|
|
|
if(configDBUsed()){
|
|
|
|
|
Log3(undef,4,"InfoPanel: reading from configDB");
|
|
|
|
|
($data,$counter) = _cfgDB_Fileexport($file,1);
|
|
|
|
|
Log3(undef,4,"InfoPanel: file not found in database") unless $counter;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if(!$counter) {
|
|
|
|
|
Log3(undef,4,"InfoPanel: reading from filesystem");
|
|
|
|
|
my $length = -s "$file";
|
2020-03-31 12:20:27 +00:00
|
|
|
|
open(my $GRAFIK, "<", $file) or die("File not found $!");
|
|
|
|
|
binmode($GRAFIK);
|
|
|
|
|
$counter = read($GRAFIK, $data, $length);
|
|
|
|
|
close($GRAFIK);
|
2015-02-06 11:50:35 +00:00
|
|
|
|
Log3(undef,4,"InfoPanel: file not found in filesystem") unless $counter;
|
|
|
|
|
}
|
|
|
|
|
return "" unless $counter;
|
|
|
|
|
Log3(undef,4,"InfoPanel: file found.");
|
|
|
|
|
return ($counter,$data);
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-12 21:59:58 +00:00
|
|
|
|
sub btIP_findTarget {
|
|
|
|
|
my ($link) = shift;
|
2015-03-02 20:05:52 +00:00
|
|
|
|
return unless length($link);
|
2015-02-12 21:59:58 +00:00
|
|
|
|
my $target = 'secret';
|
|
|
|
|
$target = '_top' if $link =~ s/^-//;
|
|
|
|
|
$target = '_blank' if $link =~ s/^\+//;
|
2015-03-24 12:41:28 +00:00
|
|
|
|
$link = $FW_httpheader{Referer} if $link eq 'BACK';
|
2015-02-12 21:59:58 +00:00
|
|
|
|
return ($link,$target);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub btIP_xy {
|
|
|
|
|
my ($x,$y,%params)= @_;
|
2015-02-14 11:12:15 +00:00
|
|
|
|
$x = $params{width} if ($x eq 'max');
|
|
|
|
|
$y = $params{height} if ($y eq 'max');
|
|
|
|
|
$x = $params{xx} if ($x eq 'x');
|
|
|
|
|
$y = $params{yy} if ($y eq 'y');
|
2015-02-12 21:59:58 +00:00
|
|
|
|
if((-1 < $x) && ($x < 1)) { $x *= $params{width}; }
|
|
|
|
|
if((-1 < $y) && ($y < 1)) { $y *= $params{height}; }
|
|
|
|
|
return($x,$y);
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-15 17:07:26 +00:00
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
##################
|
|
|
|
|
#
|
|
|
|
|
# create SVG content
|
|
|
|
|
#
|
|
|
|
|
|
2015-02-11 01:04:52 +00:00
|
|
|
|
sub btIP_returnSVG {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my ($name)= @_;
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# increase counter
|
|
|
|
|
#
|
|
|
|
|
if(defined($defs{$name}{fhem}) && defined($defs{$name}{fhem}{counter})) {
|
|
|
|
|
$defs{$name}{fhem}{counter}++;
|
|
|
|
|
} else {
|
|
|
|
|
$defs{$name}{fhem}{counter}= 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
my ($width,$height)= split(/x/, AttrVal($name,"size","800x600"));
|
2015-02-07 17:34:49 +00:00
|
|
|
|
my $bgcolor = AnalyzePerlCommand(undef,AttrVal($name,'bgcolor','"000000"'));
|
2015-02-13 19:13:29 +00:00
|
|
|
|
$bgcolor = substr($bgcolor,0,6);
|
2015-02-06 11:50:35 +00:00
|
|
|
|
my $output = "";
|
2015-02-01 13:36:06 +00:00
|
|
|
|
our $svg = "";
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
eval {
|
|
|
|
|
|
2015-02-06 18:45:02 +00:00
|
|
|
|
$svg = "\n<svg \n".
|
|
|
|
|
"xmlns=\"http://www.w3.org/2000/svg\"\nxmlns:xlink=\"http://www.w3.org/1999/xlink\"\n".
|
|
|
|
|
"width=\"".$width."px\" height=\"".$height."px\" \n".
|
|
|
|
|
"viewPort=\"0 0 $width $height\"\n".
|
|
|
|
|
"style=\"stroke-width: 0px; ";
|
|
|
|
|
$svg .= "background-color:$bgcolor; " unless $bgcolor eq 'none';
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
# set the background
|
|
|
|
|
# check if background directory is set
|
|
|
|
|
my $reason= "?"; # remember reason for undefined image
|
2015-03-02 20:05:52 +00:00
|
|
|
|
my $bgdir= AnalyzePerlCommand(undef,AttrVal($name,"bgdir",""));
|
2015-01-26 15:13:11 +00:00
|
|
|
|
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++;
|
|
|
|
|
}
|
2015-02-06 11:50:35 +00:00
|
|
|
|
|
|
|
|
|
if(opendir(BGDIR, $bgdir)){
|
|
|
|
|
my @bgfiles= grep {$_ !~ /^\./} readdir(BGDIR);
|
|
|
|
|
closedir(BGDIR);
|
|
|
|
|
if($#bgfiles>=0) {
|
|
|
|
|
if($bgnr > $#bgfiles) { $bgnr= 0; }
|
|
|
|
|
$defs{$name}{fhem}{bgnr}= $bgnr;
|
|
|
|
|
my $bgfile = $bgdir . "/" . $bgfiles[$bgnr];
|
|
|
|
|
my $info = image_info($bgfile);
|
|
|
|
|
my $bgwidth = $info->{width};
|
|
|
|
|
my $bgheight = $info->{height};
|
2015-03-07 19:38:33 +00:00
|
|
|
|
my ($u,$v) = ($bgwidth/$width, $bgheight/$height);
|
|
|
|
|
my ($w,$h);
|
|
|
|
|
if($u>$v) {
|
|
|
|
|
$w= $width;
|
|
|
|
|
$h= $bgheight/$u;
|
|
|
|
|
} else {
|
|
|
|
|
$h= $height;
|
|
|
|
|
$w= $bgwidth/$v;
|
|
|
|
|
}
|
|
|
|
|
my $scale = ($u>$v) ? 1/$u : 1/$v;
|
|
|
|
|
my ($bgx,$bgy) = (0,0);
|
|
|
|
|
$bgx = ($width - $w)/2 if AttrVal($name,'bgcenter',1);
|
|
|
|
|
$bgy = ($height - $h)/2 if AttrVal($name,'bgcenter',1);
|
|
|
|
|
($output,undef,undef) = btIP_itemImg('bgImage',$bgx,$bgy,$scale,undef,'file',$bgfile,undef);
|
2015-02-06 18:45:02 +00:00
|
|
|
|
my $opacity = AttrVal($name,'bgopacity',1);
|
|
|
|
|
$output =~ s/<image\ /<image\ opacity="$opacity" /;
|
2015-02-06 11:50:35 +00:00
|
|
|
|
}
|
|
|
|
|
} # end opendir()
|
2015-01-26 15:13:11 +00:00
|
|
|
|
} # end defined()
|
|
|
|
|
|
2015-02-06 11:50:35 +00:00
|
|
|
|
$svg .= "\" >\n";
|
|
|
|
|
$svg .= "$output\n";
|
2015-02-01 13:36:06 +00:00
|
|
|
|
$svg = btIP_evalLayout($svg, $name, $defs{$name}{fhem}{layout});
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2015-03-22 16:40:46 +00:00
|
|
|
|
readingsSingleUpdate($defs{$name},'state',localtime(),1) if(AttrVal($name,'showTime',1));
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
}; #warn $@ if $@;
|
|
|
|
|
if($@) {
|
|
|
|
|
my $msg= $@;
|
|
|
|
|
chomp $msg;
|
2015-02-06 11:50:35 +00:00
|
|
|
|
Log3($name, 2, $msg);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-02-13 23:08:22 +00:00
|
|
|
|
$svg .= "\nSorry, your browser does not support inline SVG.\n</svg>\n";
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
return $svg;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-11 01:04:52 +00:00
|
|
|
|
sub btIP_evalLayout {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my ($svg,$name,$layout)= @_;
|
|
|
|
|
my ($width,$height)= split(/x/, AttrVal($name,"size","800x600"));
|
|
|
|
|
my @layout= split("\n", $layout);
|
|
|
|
|
|
2015-02-11 15:28:31 +00:00
|
|
|
|
my $pstackcount = 0;
|
2015-02-12 21:59:58 +00:00
|
|
|
|
my %pstack;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my %params;
|
2015-02-11 19:36:11 +00:00
|
|
|
|
|
|
|
|
|
$params{name} = $name;
|
2015-02-12 10:03:17 +00:00
|
|
|
|
$params{counter} = $defs{$name}{fhem}{counter};
|
2015-02-11 19:36:11 +00:00
|
|
|
|
$params{xx} = 0;
|
|
|
|
|
$params{yy} = 0;
|
2015-02-25 10:33:21 +00:00
|
|
|
|
$params{groupx} = 0;
|
|
|
|
|
$params{groupy} = 0;
|
2015-02-11 19:36:11 +00:00
|
|
|
|
$params{width} = $width;
|
|
|
|
|
$params{height} = $height;
|
|
|
|
|
$params{rgb} = 'FFFFFF';
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$params{condition} = 1;
|
2015-02-11 19:36:11 +00:00
|
|
|
|
|
|
|
|
|
$params{boxcolor} = undef;
|
|
|
|
|
$params{tbalign} = 'left';
|
|
|
|
|
$params{padding} = 0;
|
|
|
|
|
|
|
|
|
|
$params{font} = 'Arial';
|
|
|
|
|
$params{pt} = 12;
|
|
|
|
|
$params{fontstyle} = 'initial';
|
|
|
|
|
$params{fontweight} = 'normal';
|
|
|
|
|
$params{textdecoration} = 'none';
|
|
|
|
|
$params{thalign} = 'start';
|
|
|
|
|
$params{tvalign} = 'auto';
|
2015-01-27 22:42:11 +00:00
|
|
|
|
|
2015-02-12 10:03:17 +00:00
|
|
|
|
$defs{$name}{fhem}{div} = undef;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2015-02-12 10:03:17 +00:00
|
|
|
|
my ($id,$x,$y,$x1,$y1,$x2,$y2,$radius,$rx,$ry);
|
2015-01-27 22:42:11 +00:00
|
|
|
|
my ($scale,$inline,$boxwidth,$boxheight,$boxcolor);
|
2015-02-13 23:08:22 +00:00
|
|
|
|
my ($speed,$bgcolor,$fgcolor);
|
2015-02-25 10:33:21 +00:00
|
|
|
|
my ($text,$link,$target,$imgtype,$srctype,$arg,$format,$filled,$stroked);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
my $cont= "";
|
|
|
|
|
foreach my $line (@layout) {
|
2015-02-12 10:03:17 +00:00
|
|
|
|
# kill trailing newline
|
2015-01-26 15:13:11 +00:00
|
|
|
|
chomp $line;
|
|
|
|
|
# kill comments and blank lines
|
|
|
|
|
$line=~ s/\#.*$//;
|
2015-01-28 12:34:47 +00:00
|
|
|
|
$line=~ s/\@.*$//;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$line=~ s/\s+$//;
|
|
|
|
|
$line= $cont . $line;
|
|
|
|
|
if($line=~ s/\\$//) { $cont= $line; undef $line; }
|
|
|
|
|
next unless($line);
|
|
|
|
|
$cont= "";
|
2015-02-12 10:03:17 +00:00
|
|
|
|
# Debug "$name: evaluating >$line<";
|
2015-01-26 15:13:11 +00:00
|
|
|
|
# split line into command and definition
|
|
|
|
|
my ($cmd, $def)= split("[ \t]+", $line, 2);
|
|
|
|
|
|
|
|
|
|
# Debug "CMD= \"$cmd\", DEF= \"$def\"";
|
|
|
|
|
|
|
|
|
|
# separate condition handling
|
2015-02-15 13:11:13 +00:00
|
|
|
|
if($cmd =~ m/condition/) {
|
|
|
|
|
if($cmd =~ m/^xcond/) {
|
|
|
|
|
($id,$arg) = split("[ \t]+", $def, 2);
|
|
|
|
|
$params{condition} = AnalyzePerlCommand(undef,$arg);
|
|
|
|
|
my $override = $defs{$name}{fhem}{override}{$id};
|
|
|
|
|
$override //= $params{condition};
|
|
|
|
|
if($params{condition}) {
|
|
|
|
|
$params{condition} = AnalyzePerlCommand(undef,$arg) && $override;
|
|
|
|
|
} else {
|
|
|
|
|
$params{condition} = AnalyzePerlCommand(undef,$arg) || $override;
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
$params{condition} = AnalyzePerlCommand(undef,$def);
|
|
|
|
|
}
|
2015-01-26 15:13:11 +00:00
|
|
|
|
next;
|
|
|
|
|
}
|
|
|
|
|
next unless($params{condition});
|
2015-01-31 10:45:37 +00:00
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
# Debug "before command $line: x= " . $params{xx} . ", y= " . $params{yy};
|
|
|
|
|
|
|
|
|
|
eval {
|
2024-04-05 10:57:20 +00:00
|
|
|
|
if ($cmd eq "area") {
|
2015-02-25 10:33:21 +00:00
|
|
|
|
($id,$x1,$y1,$x2,$y2,$link,$target)= split("[ \t]+", $def, 7);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$target //= "";
|
2015-01-26 15:13:11 +00:00
|
|
|
|
($x1,$y1)= btIP_xy($x1,$y1,%params);
|
|
|
|
|
($x2,$y2)= btIP_xy($x2,$y2,%params);
|
2015-02-11 01:04:56 +00:00
|
|
|
|
$link = AnalyzePerlCommand(undef,$link);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$params{xx} = $x1;
|
|
|
|
|
$params{yy} = $y2;
|
2015-02-25 10:33:21 +00:00
|
|
|
|
$svg .= btIP_itemArea($id,$x1,$y1,$x2,$y2,$link,$target,%params);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "boxcolor") {
|
2015-01-27 22:42:11 +00:00
|
|
|
|
$def = "\"$def\"" if(length($def) == 6 && $def =~ /[[:xdigit:]]{6}/);
|
|
|
|
|
$params{boxcolor} = AnalyzePerlCommand(undef, $def);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "button") {
|
2015-02-12 10:03:17 +00:00
|
|
|
|
($id,$x1,$y1,$x2,$y2,$rx,$ry,$link,$text)= split("[ \t]+", $def, 9);
|
2015-01-29 18:06:51 +00:00
|
|
|
|
($x1,$y1)= btIP_xy($x1,$y1,%params);
|
|
|
|
|
($x2,$y2)= btIP_xy($x2,$y2,%params);
|
2015-02-12 10:03:17 +00:00
|
|
|
|
($rx,$ry)= btIP_xy($rx,$ry,%params);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$params{xx} = $x1;
|
|
|
|
|
$params{yy} = $y2;
|
|
|
|
|
$link = AnalyzePerlCommand(undef,$link);
|
|
|
|
|
$link = (length($link)) ? $link : "-$params{name}.html";
|
|
|
|
|
$text = AnalyzePerlCommand(undef,$text);
|
2015-02-12 10:03:17 +00:00
|
|
|
|
$svg .= btIP_itemButton($id,$x1,$y1,$x2,$y2,$rx,$ry,$link,$text,%params);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "buttonpanel") {
|
|
|
|
|
$defs{$params{name}}{fhem}{div} .= "<div id=\"hiddenDiv\" ".
|
|
|
|
|
"style=\"display:none\" >".
|
|
|
|
|
"<iframe id=\"secretFrame\" name=\"secret\" src=\"\"></iframe></div>\n";
|
|
|
|
|
} elsif ($cmd eq "circle") {
|
2015-02-12 10:03:17 +00:00
|
|
|
|
($id,$x1,$y1,$radius,$filled,$stroked,$link)= split("[ \t]+", $def, 7);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
($x1,$y1)= btIP_xy($x1,$y1,%params);
|
2015-02-12 10:03:17 +00:00
|
|
|
|
$params{xx} = $x1;
|
|
|
|
|
$params{yy} = $y1+$radius;
|
2015-02-08 21:05:23 +00:00
|
|
|
|
$filled //= 0;
|
|
|
|
|
$stroked //= 0;
|
2015-12-06 10:23:12 +00:00
|
|
|
|
$link //= "";
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$link = AnalyzePerlCommand(undef,$link);
|
2015-02-12 10:03:17 +00:00
|
|
|
|
$svg .= btIP_itemCircle($id,$x1,$y1,$radius,$filled,$stroked,$link,%params);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "counter") {
|
2015-02-11 01:04:47 +00:00
|
|
|
|
($id,$x,$y)= split("[ \t]+", $def, 3);
|
|
|
|
|
($x,$y)= btIP_xy($x,$y,%params);
|
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y;
|
|
|
|
|
$svg .= btIP_itemCounter($id,$x,$y,%params);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "date") {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
($id,$x,$y)= split("[ \t]+", $def, 3);
|
|
|
|
|
($x,$y)= btIP_xy($x,$y,%params);
|
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y;
|
|
|
|
|
$svg .= btIP_itemDate($id,$x,$y,%params);
|
2024-04-05 12:07:59 +00:00
|
|
|
|
} elsif ($cmd eq "ellipse") {
|
2015-02-12 10:03:17 +00:00
|
|
|
|
($id,$x1,$y1,$rx,$ry,$filled,$stroked,$link)= split("[ \t]+", $def, 8);
|
|
|
|
|
($x1,$y1) = btIP_xy($x1,$y1,%params);
|
|
|
|
|
($rx,$ry) = btIP_xy($rx,$ry,%params);
|
|
|
|
|
$params{xx} = $x1;
|
|
|
|
|
$params{yy} = $y1+$ry;
|
2015-02-08 21:05:23 +00:00
|
|
|
|
$filled //= 0;
|
|
|
|
|
$stroked //= 0;
|
2015-12-06 10:23:12 +00:00
|
|
|
|
$link //= "";
|
2015-02-11 01:04:56 +00:00
|
|
|
|
$link = AnalyzePerlCommand(undef,$link);
|
2015-02-12 10:03:17 +00:00
|
|
|
|
$svg .= btIP_itemEllipse($id,$x1,$y1,$rx,$ry,$filled,$stroked,$link,%params);
|
2024-04-05 12:07:59 +00:00
|
|
|
|
} elsif ($cmd eq "embed") {
|
2015-02-14 22:07:48 +00:00
|
|
|
|
($id,$x,$y,$width,$height,$arg)= split("[ \t]+", $def, 6);
|
|
|
|
|
($x,$y)= btIP_xy($x,$y,%params);
|
|
|
|
|
($width,$height)= btIP_xy($width,$height,%params);
|
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y;
|
|
|
|
|
$arg = AnalyzePerlCommand(undef,$arg);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$defs{$name}{fhem}{div} .= btIP_itemEmbed($id,$x,$y,$width,$height,$arg,%params);
|
|
|
|
|
} elsif ($cmd eq "font") {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$params{font} = $def;
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "group") {
|
2015-01-29 19:59:02 +00:00
|
|
|
|
($id,$text,$x,$y) = split("[ \t]+", $def, 4);
|
2015-02-15 17:07:26 +00:00
|
|
|
|
$x //= $params{xx};
|
|
|
|
|
$y //= $params{yy};
|
2015-01-31 10:45:37 +00:00
|
|
|
|
($x,$y)= btIP_xy($x,$y,%params);
|
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y;
|
2024-04-05 10:57:20 +00:00
|
|
|
|
if($text eq 'open') {
|
|
|
|
|
$params{groupx} = $x;
|
|
|
|
|
$params{groupy} = $y;
|
|
|
|
|
} else {
|
|
|
|
|
$params{groupx} = 0;
|
|
|
|
|
$params{groupy} = 0;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$svg .= btIP_itemGroup($id,$text,$x,$y,%params);
|
|
|
|
|
} elsif ($cmd eq "img") {
|
2015-02-14 11:12:15 +00:00
|
|
|
|
($id,$x,$y,$scale,$link,$srctype,$arg) = split("[ \t]+", $def,7);
|
2015-02-12 10:03:17 +00:00
|
|
|
|
($x,$y) = btIP_xy($x,$y,%params);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y;
|
2015-02-14 11:12:15 +00:00
|
|
|
|
$arg = AnalyzePerlCommand(undef,$arg);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$link = AnalyzePerlCommand(undef,$link);
|
|
|
|
|
my($output,$width,$height)= btIP_itemImg($id,$x,$y,$scale,$link,$srctype,$arg,%params);
|
|
|
|
|
$svg .= $output;
|
2015-02-12 10:03:17 +00:00
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y+$height;
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "line") {
|
2015-02-12 10:03:17 +00:00
|
|
|
|
($id,$x1,$y1,$x2,$y2,$format) = split("[ \t]+", $def, 6);
|
|
|
|
|
($x1,$y1) = btIP_xy($x1,$y1,%params);
|
|
|
|
|
($x2,$y2) = btIP_xy($x2,$y2,%params);
|
|
|
|
|
$format //= 1;
|
|
|
|
|
$svg .= btIP_itemLine($id,$x1,$y1,$x2,$y2,$format,%params);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "longpoll") {
|
|
|
|
|
($id,$x,$y,$text)= split("[ \t]+", $def, 4);
|
|
|
|
|
$text //= undef;
|
|
|
|
|
$text = AnalyzePerlCommand(undef,$text) if defined($text);
|
2015-02-25 10:33:21 +00:00
|
|
|
|
($x,$y)= btIP_xy($x,$y,%params);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$x += $params{groupx};
|
|
|
|
|
$y += $params{groupy};
|
2015-02-25 10:33:21 +00:00
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y;
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$svg .= btIP_itemLongpoll($id,$x,$y,$text,%params);
|
|
|
|
|
} elsif ($cmd eq "movecalculated") {
|
|
|
|
|
my ($tox,$toy)= split('[ \t]+', $def, 2);
|
|
|
|
|
$params{xx} = AnalyzePerlCommand(undef,$tox);
|
|
|
|
|
$params{yy} = AnalyzePerlCommand(undef,$toy);
|
|
|
|
|
} elsif ($cmd eq "moveby") {
|
|
|
|
|
my ($byx,$byy) = split('[ \t]+', $def, 2);
|
|
|
|
|
my ($x,$y)= btIP_xy($byx,$byy,%params);
|
|
|
|
|
$params{xx} += $x;
|
|
|
|
|
$params{yy} += $y;
|
|
|
|
|
} elsif ($cmd eq "moveto") {
|
|
|
|
|
my ($tox,$toy)= split('[ \t]+', $def, 2);
|
|
|
|
|
my ($x,$y)= btIP_xy($tox,$toy,%params);
|
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y;
|
|
|
|
|
} elsif ($cmd eq "padding") {
|
|
|
|
|
$params{padding}= AnalyzePerlCommand(undef,$def);
|
|
|
|
|
} elsif ($cmd eq "plain") {
|
|
|
|
|
$svg .= AnalyzePerlCommand(undef,$def);
|
|
|
|
|
} elsif ($cmd eq "plot") {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
($id,$x,$y,$scale,$inline,$arg)= split("[ \t]+", $def,6);
|
|
|
|
|
($x,$y)= btIP_xy($x,$y,%params);
|
2015-02-12 10:03:17 +00:00
|
|
|
|
$arg = AnalyzePerlCommand(undef, $arg);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
my($output,$width,$height)= btIP_itemPlot($id,$x,$y,$scale,$inline,$arg,%params);
|
|
|
|
|
$svg .= $output;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$params{xx} = $x;
|
2015-02-12 10:03:17 +00:00
|
|
|
|
$params{yy} = $y+$height;
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "pop") {
|
|
|
|
|
return unless $pstackcount;
|
|
|
|
|
foreach my $key ( keys %{$pstack{$pstackcount}} ) {
|
|
|
|
|
# Debug "pop key: $key, value: $pstack{$pstackcount}{$key}";
|
|
|
|
|
$params{$key} = $pstack{$pstackcount}{$key};
|
2015-02-11 19:36:11 +00:00
|
|
|
|
}
|
2024-04-05 10:57:20 +00:00
|
|
|
|
delete $pstack{$pstackcount};
|
|
|
|
|
$pstackcount--;
|
|
|
|
|
} elsif ($cmd eq "pt") {
|
|
|
|
|
$def = AnalyzePerlCommand(undef, $def);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
if($def =~ m/^[+-]/) {
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$params{pt} += $def;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
} else {
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$params{pt} = $def;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$params{pt} = 6 if($params{pt} < 0);
|
|
|
|
|
} elsif ($cmd eq "push") {
|
|
|
|
|
$pstackcount++;
|
|
|
|
|
foreach my $key ( keys %params ) {
|
|
|
|
|
# Debug "push key: $key, value: $params{$key}";
|
|
|
|
|
$pstack{$pstackcount}{$key} = $params{$key};
|
2015-02-11 19:36:11 +00:00
|
|
|
|
}
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "rect") {
|
2015-02-12 10:03:17 +00:00
|
|
|
|
($id,$x1,$y1,$x2,$y2,$rx,$ry,$filled,$stroked,$link)= split("[ \t]+", $def, 10);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
($x1,$y1)= btIP_xy($x1,$y1,%params);
|
|
|
|
|
($x2,$y2)= btIP_xy($x2,$y2,%params);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
($rx,$ry) = btIP_xy($rx,$ry,%params);
|
|
|
|
|
$params{xx} = $x1;
|
|
|
|
|
$params{yy} = $y2;
|
2015-02-08 20:34:48 +00:00
|
|
|
|
$filled //= 0; # set 0 as default (not filled)
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$stroked //= 0; # set 0 as default (not stroked)
|
|
|
|
|
$link //= "";
|
|
|
|
|
$link = AnalyzePerlCommand(undef,$link);
|
2015-02-25 10:33:21 +00:00
|
|
|
|
$svg .= btIP_itemRect($id,$x1,$y1,$x2,$y2,$rx,$ry,$filled,$stroked,$link,undef,%params);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "rgb") {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$def = "\"$def\"" if(length($def) == 6 && $def =~ /[[:xdigit:]]{6}/);
|
|
|
|
|
$params{rgb} = AnalyzePerlCommand(undef, $def);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "seconds") {
|
|
|
|
|
($id,$x,$y,$format) = split("[ \+]", $def,4);
|
|
|
|
|
($x,$y)= btIP_xy($x,$y,%params);
|
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y;
|
|
|
|
|
$svg .= btIP_itemSeconds($id,$x,$y,$format,%params);
|
|
|
|
|
} elsif ($cmd eq "text") {
|
|
|
|
|
($id,$x,$y,$text)= split("[ \t]+", $def, 4);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
($x,$y)= btIP_xy($x,$y,%params);
|
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y;
|
2015-02-11 19:36:11 +00:00
|
|
|
|
$text= AnalyzePerlCommand(undef, $text);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$svg .= btIP_itemText($id,$x,$y,$text,%params);
|
|
|
|
|
} elsif ($cmd eq "textbox") {
|
|
|
|
|
($id,$x,$y,$boxwidth,$boxheight,$link,$text)= split("[ \t]+", $def, 7);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
($x,$y)= btIP_xy($x,$y,%params);
|
2015-02-07 17:34:49 +00:00
|
|
|
|
$text = AnalyzePerlCommand(undef, $text);
|
|
|
|
|
$text =~ s/\n/<br\/>/g;
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$link = AnalyzePerlCommand(undef, $link);
|
2015-02-07 17:34:49 +00:00
|
|
|
|
$svg .= btIP_itemTextBox($id,$x,$y,$boxwidth,$boxheight,$text,$link,%params);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y + $boxheight;
|
|
|
|
|
} elsif ($cmd eq "textboxalign") {
|
|
|
|
|
$params{tbalign} = $def;
|
|
|
|
|
} elsif ($cmd eq "textdesign") {
|
|
|
|
|
my @args = split(/,/,$def);
|
|
|
|
|
my @deco = qw(underline overline line-through); #text-decoration
|
|
|
|
|
my @style = qw(italic oblique); #font-style
|
|
|
|
|
my @weight = qw(bold); #font-weight
|
|
|
|
|
$params{fontstyle} = "initial";
|
|
|
|
|
$params{fontweight} = "initial";
|
|
|
|
|
$params{textdecoration} = "none";
|
|
|
|
|
foreach my $s (@args) {
|
|
|
|
|
if($s ne 'clear') {
|
2024-04-05 11:59:24 +00:00
|
|
|
|
$params{fontstyle} = "$s " if (grep($s,@style));
|
|
|
|
|
$params{fontweight} = "$s " if (grep($s,@weight));
|
|
|
|
|
$params{textdecoration} = "$s " if (grep($s,@deco));
|
2015-02-01 15:46:46 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "ticker") {
|
2015-02-13 23:52:14 +00:00
|
|
|
|
($id,$x,$y,$width,$format,$speed,$arg)= split("[ \t]+", $def, 7);
|
2015-02-13 23:08:22 +00:00
|
|
|
|
($x,$y)= btIP_xy($x,$y,%params);
|
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y;
|
|
|
|
|
$arg = AnalyzePerlCommand(undef,$arg);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$defs{$name}{fhem}{div} .= btIP_itemTicker($id,$x,$y,$width,$format,$speed,$arg,%params);
|
|
|
|
|
} elsif ($cmd eq "time") {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
($id,$x,$y)= split("[ \t]+", $def, 3);
|
|
|
|
|
($x,$y)= btIP_xy($x,$y,%params);
|
|
|
|
|
$params{xx} = $x;
|
|
|
|
|
$params{yy} = $y;
|
|
|
|
|
$svg .= btIP_itemTime($id,$x,$y,%params);
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "thalign"){
|
|
|
|
|
my $d = AnalyzePerlCommand(undef, $def);
|
2024-04-05 11:59:24 +00:00
|
|
|
|
if (grep($d,@valid_halign)) {
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$params{thalign}= $d;
|
|
|
|
|
} else {
|
|
|
|
|
Log3($name, 2, "InfoPanel $name: Illegal horizontal alignment $d");
|
2015-02-15 17:07:26 +00:00
|
|
|
|
}
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} elsif ($cmd eq "tvalign"){
|
|
|
|
|
my $d = AnalyzePerlCommand(undef, $def);
|
2024-04-05 11:59:24 +00:00
|
|
|
|
if(grep($d,@valid_valign)) {
|
2024-04-05 10:57:20 +00:00
|
|
|
|
$params{tvalign}= $d;
|
|
|
|
|
} else {
|
|
|
|
|
Log3($name, 2, "InfoPanel $name: Illegal vertical alignment $d");
|
2015-02-15 17:07:26 +00:00
|
|
|
|
}
|
2024-04-05 10:57:20 +00:00
|
|
|
|
} else {
|
|
|
|
|
Log3($name, 2, "InfoPanel $name: Illegal command $cmd in layout definition.");
|
|
|
|
|
}
|
2015-02-12 10:03:17 +00:00
|
|
|
|
} # eval
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2015-02-15 17:07:26 +00:00
|
|
|
|
#Debug "after command $line: x= " . $params{xx} . ", y= " . $params{yy};
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
} # foreach
|
|
|
|
|
return $svg;
|
|
|
|
|
}
|
2015-02-15 17:07:26 +00:00
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
##################
|
|
|
|
|
#
|
2015-03-29 18:53:39 +00:00
|
|
|
|
# here we answer any request to http://host:port/fhem/btip
|
2015-01-26 15:13:11 +00:00
|
|
|
|
#
|
|
|
|
|
|
2015-02-11 01:04:52 +00:00
|
|
|
|
sub btIP_addExtension {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my ($func,$link,$friendlyname)= @_;
|
|
|
|
|
my $url = "/" . $link;
|
2015-02-14 20:34:10 +00:00
|
|
|
|
$data{FWEXT}{$url}{FUNC} = $func;
|
|
|
|
|
$data{FWEXT}{$url}{LINK} = "+$link";
|
|
|
|
|
$data{FWEXT}{$url}{NAME} = $friendlyname;
|
|
|
|
|
$data{FWEXT}{$url}{FORKABLE} = 0;
|
2015-02-14 13:29:02 +00:00
|
|
|
|
$data{FWEXT}{jquery}{SCRIPT} = "/pgm2/jquery.min.js" unless $data{FWEXT}{jquery}{SCRIPT};
|
2015-02-14 20:34:10 +00:00
|
|
|
|
$data{FWEXT}{jqueryvticker}{SCRIPT} = "/pgm2/jquery.vticker.min.js" unless $data{FWEXT}{jqueryvticker}{SCRIPT};
|
2015-01-26 15:13:11 +00:00
|
|
|
|
}
|
|
|
|
|
|
2021-02-04 20:02:42 +00:00
|
|
|
|
sub btIP_CGI{
|
|
|
|
|
|
|
|
|
|
my ($request) = @_;
|
|
|
|
|
|
|
|
|
|
my ($name,$ext)= btIP_splitRequest($request);
|
|
|
|
|
|
|
|
|
|
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 InfoPanel device: $name");
|
|
|
|
|
}
|
|
|
|
|
if($ext eq "png") {
|
|
|
|
|
return btIP_returnPNG($name);
|
|
|
|
|
}
|
|
|
|
|
if($ext eq "info" || $ext eq "html") {
|
|
|
|
|
return btIP_returnHTML($name);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
|
return btIP_Overview();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-11 01:04:52 +00:00
|
|
|
|
sub btIP_splitRequest {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
my ($request) = @_;
|
|
|
|
|
|
|
|
|
|
if($request =~ /^.*\/btip$/) {
|
|
|
|
|
# http://localhost:8083/fhem/btip
|
|
|
|
|
return (undef,undef); # name, ext
|
|
|
|
|
} else {
|
|
|
|
|
my $call= $request;
|
|
|
|
|
$call =~ s/^.*\/btip\/([^\/]*)$/$1/;
|
|
|
|
|
my $name= $call;
|
2015-02-06 11:50:35 +00:00
|
|
|
|
$name =~ s/^(.*)\.(png|svg|info|html)$/$1/;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my $ext= $call;
|
|
|
|
|
$ext =~ s/^$name\.(.*)$/$1/;
|
|
|
|
|
return ($name,$ext);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-15 17:07:26 +00:00
|
|
|
|
|
2015-02-06 11:50:35 +00:00
|
|
|
|
####################
|
|
|
|
|
#
|
|
|
|
|
# HTML Stuff
|
|
|
|
|
#
|
|
|
|
|
|
2015-02-11 01:04:52 +00:00
|
|
|
|
sub btIP_returnHTML {
|
2015-01-26 15:13:11 +00:00
|
|
|
|
my ($name) = @_;
|
|
|
|
|
|
2015-01-27 22:42:11 +00:00
|
|
|
|
my $refresh = AttrVal($name, 'refresh', 60);
|
2015-03-24 12:41:28 +00:00
|
|
|
|
$refresh = ($refresh && $refresh < 59) ? 60 : $refresh;
|
2015-01-27 22:42:11 +00:00
|
|
|
|
my $title = AttrVal($name, 'title', $name);
|
2017-01-09 13:00:24 +00:00
|
|
|
|
my $viewport= "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0\"/>";
|
2015-09-28 19:48:40 +00:00
|
|
|
|
$viewport = AttrVal($name,"useViewPort",1) ? $viewport : "";
|
2017-01-09 13:00:24 +00:00
|
|
|
|
my $webApp = "";
|
|
|
|
|
$webApp = "<meta name=\"apple-mobile-web-app-capable\" content=\"yes\"/>" if (AttrVal($name,'mobileApp','none') eq 'apple');
|
|
|
|
|
$webApp = "<meta name=\"mobile-web-app-capable\" content=\"yes\"/>" if (AttrVal($name,'mobileApp','none') eq 'other');
|
2015-02-23 21:20:56 +00:00
|
|
|
|
my $gen = 'generated="'.(time()-1).'"';
|
2017-01-09 13:00:24 +00:00
|
|
|
|
my $code = btIP_HTMLHead($name,$title,$viewport,$webApp,$refresh);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
2017-02-19 17:41:32 +00:00
|
|
|
|
my $csrf= ($FW_CSRF ? "fwcsrf='$defs{$FW_wname}{CSRFTOKEN}'" : "");
|
|
|
|
|
$code .= "<body $csrf topmargin=\"0\" leftmargin=\"0\" margin=\"0\" padding=\"0\" ".
|
2015-02-23 21:20:56 +00:00
|
|
|
|
"$gen longpoll=\"1\" longpollfilter=\"room=all\" >\n".
|
|
|
|
|
|
2015-02-13 23:08:22 +00:00
|
|
|
|
"<div id=\"svg_content\" style=\"position:absolute; top:0px; left:0px; z-index:1\" >\n".
|
2015-01-28 12:34:47 +00:00
|
|
|
|
btIP_returnSVG($name)."\n</div>\n";
|
|
|
|
|
$code .= $defs{$name}{fhem}{div} if($defs{$name}{fhem}{div});
|
|
|
|
|
$code .= "</body>\n".btIP_HTMLTail();
|
2015-01-26 15:13:11 +00:00
|
|
|
|
return ("text/html; charset=utf-8", $code);
|
|
|
|
|
}
|
|
|
|
|
|
2015-02-11 01:04:52 +00:00
|
|
|
|
sub btIP_HTMLHead {
|
2017-01-09 13:00:24 +00:00
|
|
|
|
my ($name,$title,$viewport,$webApp,$refresh) = @_;
|
2015-02-12 10:03:17 +00:00
|
|
|
|
my $doctype = '<?xml version="1.0" encoding="utf-8" standalone="no"?> '."\n".
|
|
|
|
|
'<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" '.
|
|
|
|
|
'"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd\">'."\n";
|
|
|
|
|
my $xmlns = "";
|
|
|
|
|
|
2015-09-28 19:18:01 +00:00
|
|
|
|
my $r = (defined($refresh) && $refresh) ? "<meta http-equiv=\"refresh\" content=\"$refresh\"/>" : "";
|
2015-02-15 17:07:26 +00:00
|
|
|
|
my $scripts = btIP_getScript($name);
|
2019-05-30 15:28:41 +00:00
|
|
|
|
my $meta = "<meta charset=\"UTF-8\">"."\n";
|
|
|
|
|
$meta .= "<meta name=\"google\" content=\"notranslate\">";
|
2017-01-09 13:00:24 +00:00
|
|
|
|
my $code = "$doctype\n<html $xmlns>\n<head>\n<title>$title</title>\n$meta\n$r\n$viewport\n$webApp\n$scripts</head>\n";
|
2015-01-26 15:13:11 +00:00
|
|
|
|
return $code;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub btIP_getScript {
|
2015-02-15 17:07:26 +00:00
|
|
|
|
my ($name) = shift;
|
|
|
|
|
return "" if AttrVal($name,'noscript',0);
|
2015-01-26 15:13:11 +00:00
|
|
|
|
|
|
|
|
|
my $scripts= "";
|
2015-02-14 13:29:02 +00:00
|
|
|
|
my $jsTemplate = '<script type="text/javascript" src="%s"></script>';
|
|
|
|
|
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};
|
2015-02-14 17:38:55 +00:00
|
|
|
|
$script = ($script =~ m,^/,) ? "$FW_ME$script" : "$FW_ME/pgm2/$script" unless ($script =~ m,^http,);
|
2015-02-14 13:29:02 +00:00
|
|
|
|
$scripts .= sprintf($jsTemplate, $script);
|
|
|
|
|
}
|
|
|
|
|
}
|
2015-02-14 17:38:55 +00:00
|
|
|
|
# $scripts .= sprintf($jsTemplate,"/fhem/pgm2/cordova-2.3.0.js");
|
|
|
|
|
# $scripts .= sprintf($jsTemplate,"/fhem/pgm2/webviewcontrol.js");
|
2015-02-23 21:20:56 +00:00
|
|
|
|
$scripts .= sprintf($jsTemplate,"/fhem/pgm2/fhemweb.js");
|
2015-02-14 13:29:02 +00:00
|
|
|
|
$scripts =~ s/script>/script>\n/g;
|
2015-01-26 15:13:11 +00:00
|
|
|
|
return $scripts;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub btIP_HTMLTail {
|
|
|
|
|
return "</html>";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
sub btIP_Overview {
|
|
|
|
|
my ($name, $url);
|
2015-10-05 17:29:07 +00:00
|
|
|
|
my $html= btIP_HTMLHead(undef, "InfoPanel Overview", undef, undef) . "<body>\n";
|
2015-01-26 15:13:11 +00:00
|
|
|
|
foreach my $def (sort keys %defs) {
|
|
|
|
|
if($defs{$def}{TYPE} eq "InfoPanel") {
|
|
|
|
|
$name= $defs{$def}{NAME};
|
2023-02-20 19:21:25 +00:00
|
|
|
|
my $alias = ' ('.AttrVal($name,'alias','').')';
|
|
|
|
|
$alias = '' if $alias eq ' ()';
|
2015-01-31 10:45:37 +00:00
|
|
|
|
$url= btIP_getURL();
|
2023-02-20 19:21:25 +00:00
|
|
|
|
$html.= "$name$alias<br>\n<ul>";
|
2015-02-06 11:50:35 +00:00
|
|
|
|
$html.= "<a href='$url/btip/$name.html' target='_blank'>HTML</a><br>\n";
|
2015-01-26 15:13:11 +00:00
|
|
|
|
$html.= "</ul>\n<p>\n";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
$html.="</body>\n" . btIP_HTMLTail();
|
|
|
|
|
|
|
|
|
|
return ("text/html; charset=utf-8", $html);
|
|
|
|
|
}
|
|
|
|
|
|
2015-01-31 10:45:37 +00:00
|
|
|
|
sub btIP_getURL {
|
|
|
|
|
my $proto = (AttrVal($FW_wname, 'HTTPS', 0) == 1) ? 'https' : 'http';
|
2015-01-31 11:06:58 +00:00
|
|
|
|
return $proto."://$FW_httpheader{Host}$FW_ME";
|
2015-01-31 10:45:37 +00:00
|
|
|
|
}
|
|
|
|
|
|
2015-01-26 15:13:11 +00:00
|
|
|
|
1;
|
|
|
|
|
|
|
|
|
|
#
|
2015-02-06 11:50:35 +00:00
|
|
|
|
|
|
|
|
|
=pod
|
2016-01-17 14:17:58 +00:00
|
|
|
|
=item helper
|
2016-08-19 18:18:00 +00:00
|
|
|
|
=item summary create a simple status display
|
|
|
|
|
=item summary_DE erzeugt ein einfaches Statusdisplay
|
2015-02-06 11:50:35 +00:00
|
|
|
|
=begin html
|
|
|
|
|
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<a id="InfoPanel"></a>
|
2015-02-06 11:50:35 +00:00
|
|
|
|
<h3>InfoPanel</h3>
|
|
|
|
|
|
|
|
|
|
<ul>
|
|
|
|
|
InfoPanel is an extension to <a href="#FHEMWEB">FHEMWEB</a>. You must install FHEMWEB to use InfoPanel.<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<br/>
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<b>Prerequesits</b><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>InfoPanel is an extension to <a href="#FHEMWEB">FHEMWEB</a>. You must install FHEMWEB to use InfoPanel.</li>
|
|
|
|
|
<br/>
|
|
|
|
|
<li>Module uses following additional Perl modules:<br/><br/>
|
|
|
|
|
<ul><code>MIME::Base64 Image::Info</code></ul><br/>
|
|
|
|
|
If not already installed in your environment, please install them using appropriate commands from your environment.<br/><br/>
|
|
|
|
|
Package installation in debian environments: <code>apt-get install libmime-base64-perl libimage-info-perl</code></li>
|
|
|
|
|
<br/>
|
|
|
|
|
<li>You can use this module without the two additional perl modules, but in this case, you have to accept some limitations:<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>layout tag img can not be used</li>
|
|
|
|
|
<li>layout tag plot can only handle scale = 1 and inline = 0</li>
|
|
|
|
|
</ul>
|
|
|
|
|
</li>
|
|
|
|
|
</ul>
|
|
|
|
|
<br/><br/>
|
|
|
|
|
|
|
|
|
|
<a id="InfoPanel-define"></a>
|
|
|
|
|
<b>Define</b><br/><br/>
|
2015-02-06 11:50:35 +00:00
|
|
|
|
<ul>
|
2023-05-12 13:56:45 +00:00
|
|
|
|
<code>define <name> InfoPanel layout=layoutFileName</code><br/>
|
2015-02-06 11:50:35 +00:00
|
|
|
|
<br/>
|
|
|
|
|
Example:<br/><br>
|
2023-05-12 13:56:45 +00:00
|
|
|
|
<ul><code>define myInfoPanel InfoPanel layout=./FHEM/panel.layout</code><br/></ul>
|
2015-02-06 11:50:35 +00:00
|
|
|
|
</ul>
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<br/><br/>
|
2015-02-06 11:50:35 +00:00
|
|
|
|
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<a id="InfoPanel-set"></a>
|
|
|
|
|
<b>Set-Commands</b><br/><br/>
|
2015-02-06 11:50:35 +00:00
|
|
|
|
<ul>
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<a id="InfoPanel-set-reread"></a>
|
2015-02-15 13:11:13 +00:00
|
|
|
|
<li><code>set <name> reread</code>
|
2015-02-06 11:50:35 +00:00
|
|
|
|
<ul><br/>
|
|
|
|
|
Rereads the <a href="#InfoPanellayout">layout definition</a> from the file.<br/><br/>
|
|
|
|
|
<b>Important:</b><br/>
|
|
|
|
|
<ul>
|
|
|
|
|
Layout will be reread automatically if edited via fhem's "Edit files" function.<br/>
|
|
|
|
|
Autoread can be disabled via <a href="#InfoPanelattr">attribute</a>.
|
|
|
|
|
</ul>
|
2015-02-15 13:11:13 +00:00
|
|
|
|
</ul></li><br/>
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<a id="InfoPanel-set-ovEnable"></a>
|
2015-02-15 13:11:13 +00:00
|
|
|
|
<li><code>set <name> ovEnable <xconditionName></code>
|
|
|
|
|
<ul><br/>
|
|
|
|
|
set an override "1" to named xcondition
|
|
|
|
|
</ul>
|
|
|
|
|
</li><br/>
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<a id="InfoPanel-set-ovDisable"></a>
|
2015-02-15 13:11:13 +00:00
|
|
|
|
<li><code>set <name> ovDisable <xconditionName></code>
|
|
|
|
|
<ul><br/>
|
|
|
|
|
set an override "0" to named xcondition
|
|
|
|
|
</ul>
|
|
|
|
|
</li><br/>
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<a id="InfoPanel-set-ovClear"></a>
|
2015-02-15 13:11:13 +00:00
|
|
|
|
<li><code>set <name> ovClear <xconditionName>|all;</code>
|
|
|
|
|
<ul><br/>
|
|
|
|
|
delete an existing overrides to named xcondition. "all" will clear all overrides.<br/>
|
|
|
|
|
</ul>
|
|
|
|
|
</li>
|
2015-02-06 11:50:35 +00:00
|
|
|
|
</ul>
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<br/><br/>
|
2015-02-06 11:50:35 +00:00
|
|
|
|
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<a id="InfoPanel-get"></a>
|
|
|
|
|
<b>Get-Commands</b><br/><br/>
|
|
|
|
|
<ul>
|
|
|
|
|
<a id="InfoPanel-get-counter"></a>
|
2015-02-15 13:11:13 +00:00
|
|
|
|
<li><code>get <name> counter</code>
|
|
|
|
|
<ul><br/>
|
|
|
|
|
return value from internal counter<br/>
|
|
|
|
|
</ul></li><br/>
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<a id="InfoPanel-get-layout"></a>
|
2015-02-15 13:11:13 +00:00
|
|
|
|
<li><code>get <name> layout</code>
|
|
|
|
|
<ul><br/>
|
|
|
|
|
return complete layout definition<br/>
|
|
|
|
|
</ul></li><br/>
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<a id="InfoPanel-get-overrides"></a>
|
2015-02-15 13:11:13 +00:00
|
|
|
|
<li><code>get <name> overrides</code>
|
|
|
|
|
<ul><br/>
|
|
|
|
|
return list of defined overrides<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2023-06-10 16:05:18 +00:00
|
|
|
|
</ul>
|
|
|
|
|
<br/><br/>
|
|
|
|
|
|
|
|
|
|
<a id="InfoPanel-attr"></a>
|
|
|
|
|
<b>Attributes</b><br/><br/>
|
|
|
|
|
<ul>
|
|
|
|
|
<a id="InfoPanel-attr-autoread"></a>
|
|
|
|
|
<li><b>autoreread</b> - disables automatic layout reread after edit if set to 1</li>
|
|
|
|
|
<a id="InfoPanel-attr-refresh"></a>
|
|
|
|
|
<li><b>refresh</b> - time (in seconds) after which the HTML page will be reloaded automatically.<br/>
|
|
|
|
|
Any values below 60 seconds will not become valid.</li>
|
|
|
|
|
<a id="InfoPanel-attr-showTime"></a>
|
|
|
|
|
<li><b>showTime</b> - disables generation timestamp in state if set to 0</li>
|
|
|
|
|
<a id="InfoPanel-attr-size"></a>
|
|
|
|
|
<li><b>size</b> - The dimensions of the picture in the format
|
|
|
|
|
<code><width>x<height></code></li>
|
|
|
|
|
<a id="InfoPanel-attr-useViewPort"></a>
|
|
|
|
|
<li><b>useViewPort</b> - add viewport meta tag to fit mobile displays</li>
|
|
|
|
|
<a id="InfoPanel-attr-mobileApp"></a>
|
|
|
|
|
<li><b>mobileApp</b> - add support for mobile fullscreen experience</li>
|
|
|
|
|
<a id="InfoPanel-attr-title"></a>
|
|
|
|
|
<li><b>title</b> - webpage title to be shown in Browser</li>
|
|
|
|
|
<br/>
|
|
|
|
|
<a id="InfoPanel-attr-bgcenter"></a>
|
|
|
|
|
<li><b>bgcenter</b> - background images will not be centered if attribute set to 0. Default: show centered</li>
|
|
|
|
|
<a id="InfoPanel-attr-bgcolor"></a>
|
|
|
|
|
<li><b>bgcolor</b> - defines the background color, use html-hexcodes to specify color, eg 00FF00 for green background. Default color is black. You can use bgcolor=none to disable use of any background color</li>
|
|
|
|
|
<a id="InfoPanel-attr-bgdir"></a>
|
|
|
|
|
<li><b>bgdir</b> - directory containing background images</li>
|
|
|
|
|
<a id="InfoPanel-attr-bgopacity"></a>
|
|
|
|
|
<li><b>bgopacity</b> - set opacity for background image, values 0...1.0</li>
|
|
|
|
|
<a id="InfoPanel-attr-tmin"></a>
|
|
|
|
|
<li><b>tmin</b> - background picture will be shown at least <code>tmin</code> seconds,
|
|
|
|
|
no matter how frequently the feed consumer accesses the page.</li>
|
|
|
|
|
<br/>
|
|
|
|
|
<b>Important:</b> bgcolor and bgdir will be evaluated by <code>{ <a href="#perl"><perl special></a> }</code> use quotes for absolute values!<br/>
|
|
|
|
|
</ul>
|
|
|
|
|
<br/><br/>
|
2015-02-06 11:50:35 +00:00
|
|
|
|
|
|
|
|
|
<a name="InfoPanelreadings"></a>
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<b>Generated Readings/Events:</b><br/><br/>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>state - show time and date of last layout evaluation</li>
|
|
|
|
|
</ul>
|
|
|
|
|
<br/><br/>
|
|
|
|
|
|
|
|
|
|
<a id="InfoPanel-layout"></a>
|
|
|
|
|
<b>Layout definition</b><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>
|
2015-02-07 10:22:29 +00:00
|
|
|
|
All parameters in curly brackets can be evaluated by <code>{ <a href="#perl"><perl special></a> }</code></br>
|
|
|
|
|
<br/>
|
2015-02-06 18:45:02 +00:00
|
|
|
|
<li><code>area <id> <x1> <y1> <x2> <y2> <{link}></code><br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<br/>
|
|
|
|
|
<ul>create a responsive area which will call a link when clicked.<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x1,y1 = upper left corner<br/>
|
|
|
|
|
x2,y2 = lower right corner<br/>
|
|
|
|
|
link = url to be called<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br>
|
2015-02-06 18:45:02 +00:00
|
|
|
|
<li><code>boxcolor <{rgba}></code><br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<br/>
|
|
|
|
|
<ul>define an rgb color code to be used for filling button and textbox<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br>
|
|
|
|
|
<li><code>button <id> <x1> <y1> <x2> <y2> <r1> <r2> <link> <text></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>create a responsive colored button which will call a link when clicked.<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x1,y1 = upper left corner<br/>
|
|
|
|
|
x2,y2 = lower right corner<br/>
|
|
|
|
|
r1,r2 = radius for rounded corners<br/>
|
|
|
|
|
link = url to be called<br/>
|
|
|
|
|
text = text that will be written onto the button<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
button will be filled with color defined by "boxcolor"<br/>
|
|
|
|
|
text color will be read from "rgb" value<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<li><code>buttonpanel</code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>needed once in your layout file if you intend to use buttons in the same layout.<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-10 11:09:21 +00:00
|
|
|
|
<li><code>circle <id> <x> <y> <r> [<fill>] [<stroke-width>] [<link>]</code><br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<br/>
|
|
|
|
|
<ul>create a circle<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x,y = center coordinates of circle<br/>
|
|
|
|
|
r = radius<br/>
|
2015-02-08 21:05:23 +00:00
|
|
|
|
fill = circle will be filled with "rgb" color if set to 1. Default = 0<br/>
|
|
|
|
|
stroke-width = defines stroke width to draw around the circle. Default = 0<br/>
|
2015-02-10 11:09:21 +00:00
|
|
|
|
link = URL to be linked to item<br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-11 01:04:47 +00:00
|
|
|
|
<li><code>counter <id> <x> <y></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>print internal counter<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x,y = position<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<li><code>date <id> <x> <y></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>print date<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x,y = position<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-14 22:28:21 +00:00
|
|
|
|
<li><code>embed <id> <x> <y> <width> <height> <{object}></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>embed any object<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x,y = position<br/>
|
|
|
|
|
width,height = containers's dimension<br/>
|
|
|
|
|
object = object to embed<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-10 11:09:21 +00:00
|
|
|
|
<li><code>ellipse <id> <x> <y> <r1> <r2> [<fill>] [<stroke-width>] [<link>]</code><br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<br/>
|
|
|
|
|
<ul>create an ellipse<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
2015-02-14 22:28:21 +00:00
|
|
|
|
x,y = center coordinates of ellipse<br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
r1,r2 = radius<br/>
|
2015-02-08 21:05:23 +00:00
|
|
|
|
fill = ellipse will be filled with "rgb" color if set to 1. Default = 0<br/>
|
|
|
|
|
stroke-width = defines stroke width to draw around the ellipse. Default = 0<br/>
|
2015-02-10 11:09:21 +00:00
|
|
|
|
link = URL to be linked to item<br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<li><code>font <font-family></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>define font family used for text elements (text, date, time, seconds ...)<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
Example: <code>font arial</code><br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<li><code>group <id> open <x> <y><br/>
|
|
|
|
|
group - close</code> (id will not be evaluated, just give any value)<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>group items<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
open|close = define start and end of group<br/>
|
|
|
|
|
x,y = upper left corner as reference for all grouped items, will be inherited to all elements.<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
Examples:<br/>
|
|
|
|
|
<code>
|
|
|
|
|
group - open 150 150<br/>
|
|
|
|
|
rect ...<br/>
|
|
|
|
|
img ...<br/>
|
|
|
|
|
group - close<br/>
|
|
|
|
|
</code>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-14 17:38:55 +00:00
|
|
|
|
<li><code>img <id> <x> <y> <scale> <link> <sourceType> <{dataSource}>s</code><br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<br/>
|
|
|
|
|
<ul>embed an image into InfoPanel<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x,y = upper left corner<br/>
|
|
|
|
|
scale = scale to be used for resizing; may be factor or defined by width or height<br/>
|
2015-02-14 12:16:52 +00:00
|
|
|
|
link = URL to be linked to item, use "" if not needed<br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
sourceType = file | url | data<br/>
|
|
|
|
|
dataSource = where to read data from, depends on sourceType<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<li><code>line <id> <x1> <y1> <x2> <y2> [<stroke>]</code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>draw a line<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x1,y1 = coordinates (start)<br/>
|
|
|
|
|
x2,y2 = coordinates (end)<br/>
|
|
|
|
|
stroke = stroke width for line; if omitted, default = 0<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<li><code>moveby <x> <y></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>move most recently x- and y-coordinates by given steps<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2016-09-04 11:29:27 +00:00
|
|
|
|
<li><code>movecalculated <{perlSpecial x}> <{perlSpecial y}></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>calculate x- and y-coordinates by perlSpecials<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<li><code>moveto <x> <y></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>move x- and y-coordinates to the given positon<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-07 17:34:49 +00:00
|
|
|
|
<li><code>padding <width></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>border width (in pixel) to be used in textboxes<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-06 18:45:02 +00:00
|
|
|
|
<li><code>plot <id> <x> <y> <scale> <inline> <{plotName}></code><br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<br/>
|
|
|
|
|
<ul>embed an SVG plot into InfoPanel<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x,y = upper left corner<br/>
|
|
|
|
|
scale = scale to be used for resizing; may be factor or defined by width or height<br/>
|
|
|
|
|
inline = embed plot as data (inline=1) or as link (inline=0)<br/>
|
|
|
|
|
plotName = name of desired SVG device from your fhem installation<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-11 19:36:11 +00:00
|
|
|
|
<li><code>pop</code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>fetch last parameter set from stack and set it actice<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<li><code>pt <[+-]font-size></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>define font size used for text elements (text, date, time, seconds ...)<br/>
|
|
|
|
|
can be given as absolute or relative value.<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
Examples:<br/>
|
|
|
|
|
<code>pt 12</code><br/>
|
|
|
|
|
<code>pt +3</code><br/>
|
|
|
|
|
<code>pt -2</code><br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-11 19:36:11 +00:00
|
|
|
|
<li><code>push</code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>push active parameter set onto stack<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-10 11:09:21 +00:00
|
|
|
|
<li><code>rect <id> <x1> <y1> <x2> <y2> <r1> <r2> [<fill>] [<stroke-width>] [<link>]</code><br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<br/>
|
|
|
|
|
<ul>create a rectangle<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x1,y1 = upper left corner<br/>
|
|
|
|
|
x2,y2 = lower right corner<br/>
|
|
|
|
|
r1,r2 = radius for rounded corners<br/>
|
2015-02-08 20:34:48 +00:00
|
|
|
|
fill = rectangle will be filled with "rgb" color if set to 1. Default = 0<br/>
|
|
|
|
|
stroke-width = defines stroke width to draw around the rectangle. Default = 0<br/>
|
2015-02-10 11:09:21 +00:00
|
|
|
|
link = URL to be linked to item<br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-06 18:45:02 +00:00
|
|
|
|
<li><code>rgb <{rgb[a]}></code><br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<br/>
|
|
|
|
|
<ul>define rgba value (hex digits!) used for text, lines, circles, ellipses<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<code>r = red value</code><br/>
|
|
|
|
|
<code>g = green value</code><br/>
|
|
|
|
|
<code>b = blue value</code><br/>
|
|
|
|
|
<code>a = alpha value used for opacity; optional</code><br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<li><code>seconds <id> <x> <y> [<format>]</code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>print seconds<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x,y = position<br/>
|
|
|
|
|
format = seconds will be preceeded by ':' if set to 'colon'; optional<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-06 18:45:02 +00:00
|
|
|
|
<li><code>text <id> <x> <y> <{text}></code><br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<br/>
|
|
|
|
|
<ul>print text<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x,y = position<br/>
|
|
|
|
|
text = text content to be printed<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-07 17:34:49 +00:00
|
|
|
|
<li><code>textbox <id> <x> <y> <boxWidth> <boxHeight> <{link}> <{text}> </code><br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<br/>
|
|
|
|
|
<ul>create a textbox to print text with auto wrapping<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x,y = upper left corner<br/>
|
|
|
|
|
boxWidth,boxHeight = dimensions of textbox<br/>
|
2015-02-07 17:34:49 +00:00
|
|
|
|
link = url to be used when clicked; use "" if not needed<br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
text = text to be printed in textbox<br/>
|
|
|
|
|
<br/>
|
2015-02-06 18:48:53 +00:00
|
|
|
|
<b>Important:</b> textboxes are not responsive via area tag. Use optional link parameter in textbox tag<br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<li><code>textboxalign <align></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>define horizontal alignment for text inside textboxes<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
valid values: left center right justify<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<li><code>textdesign <align></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>define comma-separated list for text design and decoration<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
valid values: underline overline line-through bold italic oblique clear<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
Examples:<br/>
|
|
|
|
|
<code>
|
|
|
|
|
textdesign underline<br/>
|
|
|
|
|
textdesign bold,italic,underline
|
|
|
|
|
</code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<b>Important:</b> "clear" resets all to default values!<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<li><code>thalign <align></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>define horizontal alignment for text output<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
valid values: start middle end<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-14 22:28:21 +00:00
|
|
|
|
<li><code>ticker <id> <x> <y> <width> <items> <speed> <{data}></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>create a vertical ticker<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x,y = position<br/>
|
|
|
|
|
width = width<br/>
|
|
|
|
|
items = number of items to be displayed simultanously<br/>
|
|
|
|
|
speed = scroll speed<br/>
|
|
|
|
|
data = list of text items, separated by <code>\n</code><br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
<li><code>time <id> <x> <y></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>print time<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
id = element id<br/>
|
|
|
|
|
x,y = position<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<li><code>tvalign <align></code><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>define vertical alignment for text output<br/>
|
|
|
|
|
<br/>
|
|
|
|
|
valid values: auto baseline middle center hanging<br/>
|
|
|
|
|
</ul></li><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
|
2023-06-10 16:05:18 +00:00
|
|
|
|
</ul>
|
|
|
|
|
<br/>
|
2015-02-06 14:52:44 +00:00
|
|
|
|
|
2023-06-10 16:05:18 +00:00
|
|
|
|
<b>Author's notes</b><br/>
|
|
|
|
|
<br/>
|
|
|
|
|
<ul>
|
|
|
|
|
<li>Have fun!</li><br/>
|
|
|
|
|
</ul>
|
2015-02-06 11:50:35 +00:00
|
|
|
|
</ul>
|
|
|
|
|
|
|
|
|
|
=end html
|
|
|
|
|
|
|
|
|
|
=cut
|