# $Id$ ######################################################################################## # # 95_Dashboard.pm # ######################################################################################## # Released : 20.12.2013 Sascha Hermann # Version : # 1.00: Released to testers # 1.02: Don't show link on Groups with WebLinks. Hide GroupToogle Button (new Attribut dashboard_showtooglebuttons). # Set the Columnheight (new Attribur dashboard_colheight). # 1.03: Dashboard Entry over the Room-List, set the Room "Dashboard" to hiddenroom. Build weblink independently. # Dashboard Row on Top and Bottom (no separately columns). Detail Button # to jump into define Detailview. Don't show link on Groups with SVG and readingsGroup. # 1.04: Sort the Groupentrys (@gemx). Hide Room Dashboard. # 1.05: Fix dashboard_row center # 1.10: Released Version 1.10. Rename Module from 95_FWViews to 95_Dashboard. Rename view_* Attributes to # dashboard_*. Rename fhemweb_FWViews.js to dashboard.js. Cleanup CSS. Reduce single png-Images to one File only. # Fix duplicated run of JS Script. Dashboard STAT show "Missing File" Information if installation is wrong. # 1.11: use jquery.min and jquery-ui.min. add dashboard_debug attribute. Check dashboard_sorting value plausibility. # Change default Values. First Release to FHEM SVN. # 1.12: Add Germyn command_ref Text. Add Default Values to command_ref (@cotecmania). Fix identification of an existing # Dashboard-Weblink (Message *_weblink already defined, delete it first on rereadcfg). Remove white space from # both ends of a group in dashboard_groups. Fix dashboard_sorting check. Wrong added hiddenroom to FHEMWEB # Browsersession fixed. Buttonbar can now placed on top or bottom of the Dashboard (@cotecmania). # Dashboard is always edited out the Room Dashboard (@justme1968) # Fix Dashboard Entry over the Room-List after 01_FHEMWEB.pm changes # 2.00: First Changes vor Dashboard Tabs. Change while saving positioning. Alterd max/min Group positioning. # Many changes in Dasboard.js. Replaced the attributes dashboard_groups, dashboard_colheight and dashboard_sorting # Many new Attributes vor Tabs, Dashboard sizing. Set of mimimal attributes (helpful for beginners). # Provisionally the columns widths are dependent on the total width of the Dashboard. # 2.01: attibute dashboard_colwidth replace with dashboard_rowcentercolwidth. rowcentercolwidth can now be defined per # column. Delete Groups Attribut with Value 1. Dashboard can hide FHEMWEB Roomliste and Header => Fullscreenmode # 2.02: Tabs can set on top, bottom or hidden. Fix "variable $tabgroups masks earlier" Errorlog. # 2.03: dashboard_showfullsize only in DashboardRoom. Tabs can show Icons (new Attributes). Fix showhelper Bug on lock/unlock. # The error that after a trigger action the curren tab is changed to the "old" activetab tab has been fixed. dashboard_activetab # is stored after tab change # 2.04: change view of readingroups. Attribute dashboard_groups removed. New Attribute dashboard_webfrontendfilter to define # separate Dashboards per FHEMWEB Instance. # 2.05: bugfix, changes in dashboard.js, groups can show Icons (group:icon@color,group:icon@color ...). "Back"-Button in Fullsize-Mode. # Dashboard near top in Fullsize-Mode. dashboard_activetab store the active Tab, not the last active tab. # 2.06: Attribute dashboard_colheight removed. Change Groupcontent sorting in compliance by alias and sortby. # Custom CSS over new Attribute dashboard_customcss. Fix Bug that affect new groups. # 2.07: Fix GroupWidget-Error with readingGroups in hiddenroom # 2.08: Fix dashboard_webfrontendfilter Error-Message. Internal changes. Attribute dashboard_colwidth and dashboard_sorting removed. # 2.09: dashboard_showfullsize not applied in room "all" resp. "Everything". First small implementation over Dashboard_DetailFN. # 2.10: Internal Changes. Lock/Unlock now only in Detail view. Attribut dashboard_lockstate are obsolet. # 2.11: Attribute dashboard_showhelper ist obolet. Erase tabs-at-the-top-buttonbar-hidden and tabs-on-the-bottom-buttonbar-hidden values # from Attribute dashboard_showtabs. Change Buttonbar Style. Clear CSS and Dashboard.js. # 2.12: Update Docu. CSS Class Changes. Insert Configdialog for Tabs. Change handling of parameters in both directions. # 2.13: Changed View of readingsHistory. Fix Linebrake in unlock state. Bugfix Display Group with similar group names. # # Known Bugs/Todos: # BUG: Nicht alle Inhalte aller Tabs laden, bei Plots dauert die bedienung des Dashboards zu lange. -> elemente hidden? -> widgets aus js über XHR nachladen und dann anzeigen (jquery xml nachladen...) # BUG: Variabler abstand wird nicht gesichert # BUG: dashboard_webfrontendfilter doesn't Work Antwort #469 # BUG: Überlappen Gruppen andere? ->Zindex oberer reihe > als darunter liegenden # # Log 1, "[DASHBOARD simple debug] '".$g."' "; ######################################################################################## # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program. If not, see . # ######################################################################################## # Helpfull Links: # http://jquery.10927.n7.nabble.com/saving-portlet-state-td125831.html # http://jsfiddle.net/w7ZvQ/ # http://jsfiddle.net/adamboduch/e6zdX/1/ # http://www.innovativephp.com/jquery-resizable-practical-examples-and-demos/ # http://jsfiddle.net/raulfernandez/mAuxn/ # http://jsfiddle.net/zeTP8/ package main; use strict; use warnings; use vars qw(%FW_icons); # List of icons use vars qw($FW_dir); # base directory for web server use vars qw($FW_icondir); # icon base directory use vars qw($FW_room); # currently selected room use vars qw(%defs); # FHEM device/button definitions #use vars qw(%FW_groups); # List of Groups use vars qw($FW_wname); # Web instance use vars qw(%FW_hiddenroom);# hash of hidden rooms, used by weblink use vars qw(%FW_types); # device types use vars qw($FW_ss); # is smallscreen, needed by 97_GROUP/95_VIEW ######################### # Forward declaration sub Dashboard_GetGroupList(); ######################### # Global variables my %group; my $dashboard_groupListfhem; my $fwjquery = "jquery.min.js"; my $fwjqueryui = "jquery-ui.min.js"; my $dashboardname = "Dashboard"; # Link Text my $dashboardhiddenroom = "DashboardRoom"; # Hiddenroom my $dashboardversion = "2.13"; ############################################################################################# sub Dashboard_Initialize ($) { my ($hash) = @_; $hash->{DefFn} = "Dashboard_define"; $hash->{SetFn} = "Dashboard_Set"; $hash->{GetFn} = "Dashboard_Get"; $hash->{UndefFn} = "Dashboard_undef"; $hash->{FW_detailFn} = "Dashboard_DetailFN"; $hash->{AttrFn} = "Dashboard_attr"; $hash->{AttrList} = "disable:0,1 ". "dashboard_colcount:1,2,3,4,5 ". "dashboard_debug:0,1 ". "dashboard_lockstate:dont-use-this-attribut ". #obolet since 04.2014 "dashboard_rowtopheight ". "dashboard_rowbottomheight ". "dashboard_row:top,center,bottom,top-center,center-bottom,top-center-bottom ". "dashboard_showhelper:dont-use-this-attribut ". #obolet since 04.2014 "dashboard_showtooglebuttons:0,1 ". #new attribute vers. 2.00 "dashboard_tabcount:1,2,3,4,5,6,7 ". "dashboard_activetab:1,2,3,4,5,6,7 ". "dashboard_tab1name ". "dashboard_tab2name ". "dashboard_tab3name ". "dashboard_tab4name ". "dashboard_tab5name ". "dashboard_tab1groups ". "dashboard_tab2groups ". "dashboard_tab3groups ". "dashboard_tab4groups ". "dashboard_tab5groups ". "dashboard_tab1sorting ". "dashboard_tab2sorting ". "dashboard_tab3sorting ". "dashboard_tab4sorting ". "dashboard_tab5sorting ". "dashboard_width ". "dashboard_rowcenterheight ". #new attribute vers. 2.01 "dashboard_rowcentercolwidth ". "dashboard_showfullsize:0,1 ". #new attribute vers. 2.02 #"dashboard_showtabs:tabs-and-buttonbar-at-the-top,tabs-at-the-top-buttonbar-hidden,tabs-and-buttonbar-on-the-bottom,tabs-on-the-bottom-buttonbar-hidden,tabs-and-buttonbar-hidden ". "dashboard_showtabs:tabs-and-buttonbar-at-the-top,tabs-and-buttonbar-on-the-bottom,tabs-and-buttonbar-hidden ". #new attribute vers. 2.03 "dashboard_tab1icon ". "dashboard_tab2icon ". "dashboard_tab3icon ". "dashboard_tab4icon ". "dashboard_tab5icon ". #new attribute vers. 2.04 "dashboard_webfrontendfilter ". #new attribute vers. 2.06 "dashboard_customcss ". "dashboard_tab6name ". "dashboard_tab7name ". "dashboard_tab6groups ". "dashboard_tab7groups ". "dashboard_tab6sorting ". "dashboard_tab7sorting ". "dashboard_tab6icon ". "dashboard_tab7icon"; $data{FWEXT}{jquery}{SCRIPT} = "/pgm2/".$fwjquery if (!$data{FWEXT}{jquery}{SCRIPT}); $data{FWEXT}{jqueryui}{SCRIPT} = "/pgm2/".$fwjqueryui if (!$data{FWEXT}{jqueryui}{SCRIPT}); $data{FWEXT}{z_dashboard}{SCRIPT} = "/pgm2/dashboard.js" if (!$data{FWEXT}{z_dashboard}); $data{FWEXT}{Dashboardx}{LINK} = "?room=".$dashboardhiddenroom; $data{FWEXT}{Dashboardx}{NAME} = $dashboardname; return undef; } sub Dashboard_DetailFN() { my ($name, $d, $room, $pageHash) = @_; my $hash = $defs{$name}; my $ret = ""; $ret .= "\n"; $ret .= "\n"; $ret .= "
Helper:\n
\n"; $ret .= " \n"; $ret .= " \n"; $ret .= " \n"; $ret .= "
\n"; $ret .= "
\n"; return $ret; } sub Dashboard_Set($@) { my ( $hash, $name, $cmd, @args ) = @_; if ( $cmd eq "lock" ) { readingsSingleUpdate( $hash, "lockstate", "lock", 0 ); return; } elsif ( $cmd eq "unlock" ) { readingsSingleUpdate( $hash, "lockstate", "unlock", 0 ); return; }else { return "Unknown argument " . $cmd . ", choose one of lock:noArg unlock:noArg"; } } sub Dashboard_Escape($) { my $a = shift; return "null" if(!defined($a)); my %esc = ("\n" => '\n', "\r" => '\r', "\t" => '\t', "\f" => '\f', "\b" => '\b', "\"" => '\"', "\\" => '\\\\', "\'" => '\\\'', ); $a =~ s/([\x22\x5c\n\r\t\f\b])/$esc{$1}/eg; return $a; } sub Dashboard_Get($@) { my ($hash, @a) = @_; my $res = ""; my $arg = (defined($a[1]) ? $a[1] : ""); if ($arg eq "config") { my $name = $hash->{NAME}; my $attrdata = $attr{$name}; if ($attrdata) { my $x = keys %$attrdata; my $i = 0; my @splitattr; $res .= "{\n"; $res .= " \"CONFIG\": {\n"; $res .= " \"name\": \"$name\",\n"; $res .= " \"lockstate\": \"".ReadingsVal($name,"lockstate","unlock")."\",\n"; my @iconFolders = split(":", AttrVal($FW_wname, "iconPath", "$FW_sp:default:fhemSVG:openautomation")); my $iconDirs = ""; foreach my $idir (@iconFolders) {$iconDirs .= "$attr{global}{modpath}/www/images/".$idir.",";} $res .= " \"icondirs\": \"$iconDirs\""; $res .= ($i != $x) ? ",\n" : "\n"; foreach my $attr (sort keys %$attrdata) { $i++; @splitattr = split("@", $attrdata->{$attr}); if (@splitattr == 2) { $res .= " \"".Dashboard_Escape($attr)."\": \"".$splitattr[0]."\",\n"; $res .= " \"".Dashboard_Escape($attr)."color\": \"".$splitattr[1]."\""; } else { $res .= " \"".Dashboard_Escape($attr)."\": \"".$attrdata->{$attr}."\"";} $res .= ($i != $x) ? ",\n" : "\n"; } $res .= " }\n"; $res .= "}\n"; return $res; } } elsif ($arg eq "groupWidget") { #### Comming Soon ###### # For dynamic load of GroupWidgets from JavaScript my $dbgroup = ""; #for (my $p=2;$p<@a;$p++){$dbgroup .= @a[$p]." ";} #For Groupnames with Space for (my $p=2;$p<@a;$p++){$dbgroup .= $a[$p]." ";} #For Groupnames with Space $dashboard_groupListfhem = Dashboard_GetGroupList; %group = BuildGroupList($dashboard_groupListfhem); $res .= BuildGroupWidgets(1,1,1212,trim($dbgroup),"t1c1,".trim($dbgroup).",true,0,0:"); return $res; } else { return "Unknown argument $arg choose one of config:noArg groupWidget"; } } sub Dashboard_define ($$) { my ($hash, $def) = @_; my $now = time(); my $name = $hash->{NAME}; $hash->{VERSION} = $dashboardversion; readingsSingleUpdate( $hash, "state", "Initialized", 0 ); RemoveInternalTimer($hash); InternalTimer ($now + 5, 'CreateDashboardEntry', $hash, 0); InternalTimer ($now + 5, 'CheckDashboardAttributUssage', $hash, 0); my $dashboard_groupListfhem = Dashboard_GetGroupList; return; } sub Dashboard_undef ($$) { my ($hash,$arg) = @_; RemoveInternalTimer($hash); return undef; } sub Dashboard_attr($$$) { my ($cmd, $name, $attrName, $attrVal) = @_; return; } ############################################################################################# ############################################################################################# sub DashboardAsHtml($) { my ($d) = @_; Dashboard_SummaryFN($FW_wname,$d,$FW_room,undef); } sub Dashboard_SummaryFN($$$$) { my ($FW_wname, $d, $room, $pageHash) = @_; my $ret = ""; my $showbuttonbar = "hidden"; my $debugfield = "hidden"; my $h = $defs{$d}; my $name = $defs{$d}{NAME}; my $id = $defs{$d}{NR}; ######################### Read Dashboard Attributes and set Default-Values #################################### my $lockstate = ($defs{$d}->{READINGS}{lockstate}{VAL}) ? $defs{$d}->{READINGS}{lockstate}{VAL} : "unlock"; my $showhelper = ($lockstate eq "unlock") ? 1 : 0; my $disable = AttrVal($defs{$d}{NAME}, "disable", 0); my $colcount = AttrVal($defs{$d}{NAME}, "dashboard_colcount", 1); my $colwidth = AttrVal($defs{$d}{NAME}, "dashboard_rowcentercolwidth", 100); my $colheight = AttrVal($defs{$d}{NAME}, "dashboard_rowcenterheight", 400); my $rowtopheight = AttrVal($defs{$d}{NAME}, "dashboard_rowtopheight", 250); my $rowbottomheight = AttrVal($defs{$d}{NAME}, "dashboard_rowbottomheight", 250); my $showtabs = AttrVal($defs{$d}{NAME}, "dashboard_showtabs", "tabs-and-buttonbar-at-the-top"); my $showtooglebuttons = AttrVal($defs{$d}{NAME}, "dashboard_showtooglebuttons", 1); my $showfullsize = AttrVal($defs{$d}{NAME}, "dashboard_showfullsize", 0); my $webfrontendfilter = AttrVal($defs{$d}{NAME}, "dashboard_webfrontendfilter", "*"); my $customcss = AttrVal($defs{$d}{NAME}, "dashboard_customcss", "none"); my $row = AttrVal($defs{$d}{NAME}, "dashboard_row", "center"); my $debug = AttrVal($defs{$d}{NAME}, "dashboard_debug", "0"); my $activetab = AttrVal($defs{$d}{NAME}, "dashboard_activetab", 1); my $tabcount = AttrVal($defs{$d}{NAME}, "dashboard_tabcount", 1); my $dbwidth = AttrVal($defs{$d}{NAME}, "dashboard_width", "100%"); my @tabnames = (AttrVal($defs{$d}{NAME}, "dashboard_tab1name", "Dashboard-Tab 1"), AttrVal($defs{$d}{NAME}, "dashboard_tab2name", "Dashboard-Tab 2"), AttrVal($defs{$d}{NAME}, "dashboard_tab3name", "Dashboard-Tab 3"), AttrVal($defs{$d}{NAME}, "dashboard_tab4name", "Dashboard-Tab 4"), AttrVal($defs{$d}{NAME}, "dashboard_tab5name", "Dashboard-Tab 5"), AttrVal($defs{$d}{NAME}, "dashboard_tab6name", "Dashboard-Tab 6"), AttrVal($defs{$d}{NAME}, "dashboard_tab7name", "Dashboard-Tab 7")); my @tabgroups = (AttrVal($defs{$d}{NAME}, "dashboard_tab1groups", ""), AttrVal($defs{$d}{NAME}, "dashboard_tab2groups", ""), AttrVal($defs{$d}{NAME}, "dashboard_tab3groups", ""), AttrVal($defs{$d}{NAME}, "dashboard_tab4groups", ""), AttrVal($defs{$d}{NAME}, "dashboard_tab5groups", ""), AttrVal($defs{$d}{NAME}, "dashboard_tab6groups", ""), AttrVal($defs{$d}{NAME}, "dashboard_tab7groups", "")); my @tabsortings = (AttrVal($defs{$d}{NAME}, "dashboard_tab1sorting", ""), AttrVal($defs{$d}{NAME}, "dashboard_tab2sorting", ""), AttrVal($defs{$d}{NAME}, "dashboard_tab3sorting", ""), AttrVal($defs{$d}{NAME}, "dashboard_tab4sorting", ""), AttrVal($defs{$d}{NAME}, "dashboard_tab5sorting", ""), AttrVal($defs{$d}{NAME}, "dashboard_tab6sorting", ""), AttrVal($defs{$d}{NAME}, "dashboard_tab7sorting", "")); ############################################################################################# if ($disable == 1) { readingsSingleUpdate( $defs{$d}, "state", "Disabled", 0 ); return ""; } unless (@tabgroups) { readingsSingleUpdate( $defs{$d}, "state", "No Groups set", 0 ); return ""; } ############# Filter Dashboard display depending on $FW_wname ################################### if ($webfrontendfilter ne "*") { my $filterhit = 0; my @webfilter = split(",", $webfrontendfilter); for (my $i=0;$i<@webfilter;$i++){ if (trim($FW_wname) eq trim($webfilter[$i]) ) { $filterhit = 1; } } if ($filterhit == 0) { # construction site # $ret .= "No Dashboard configured for ".$FW_wname."
"; # $ret .= "Set Attribute dashboard_webfrontendfilter, see Details"; return $ret; } } ################################################################################## if ($debug == 1) { $debugfield = "edit" }; if ($showtabs eq "tabs-and-buttonbar-at-the-top") { $showbuttonbar = "top"; } if ($showtabs eq "tabs-and-buttonbar-on-the-bottom") { $showbuttonbar = "bottom"; } if ($showbuttonbar eq "hidden") { $lockstate = "lock" }; if ($activetab > $tabcount) { $activetab = $tabcount; } $colwidth =~ tr/,/:/; if (not ($colheight =~ /^\d+$/)) { $colheight = 400 }; if (not ($rowtopheight =~ /^\d+$/)) { $rowtopheight = 50 }; if (not ($rowbottomheight =~ /^\d+$/)) { $rowbottomheight = 50 }; #------------------- Check dashboard_sorting on false content ------------------------------------ for (my $i=0;$i<@tabsortings;$i++){ if (($tabsortings[$i-1] !~ /[0-9]/ || $tabsortings[$i-1] !~ /:/ || $tabsortings[$i-1] !~ /,/ ) && ($tabsortings[$i-1] ne "," && $tabsortings[$i-1] ne "")){ Log3 $d, 3, "[".$name." V".$dashboardversion."] Value of attribut dashboard_tab".$i."sorting is wrong. Saved sorting can not be set. Fix Value or delete the Attribute. [".$tabsortings[$i-1]."]"; } else { Log3 $d, 5, "[".$name." V".$dashboardversion."] Sorting OK or Empty: dashboard_tab".$i."sorting "; } } #------------------------------------------------------------------------------------------------- if ($room ne "all") { ################################ $dashboard_groupListfhem = Dashboard_GetGroupList; ################################ $ret .= "
\n"; $ret .= "
\n"; $ret .= " \n"; $ret .= "
\n"; $ret .= " \n"; $ret .= " \n"; $ret .= " "; $ret .= " "; $ret .= " "; $ret .= " "; $ret .= "
Tabtitle:
Tabicon:
Groups:
\n"; $ret .= "
\n"; $ret .= "
\n"; $ret .= "Comming soon"; $ret .= "
\n"; $ret .= "
\n"; $ret .= "
\n"; $ret .= "
$d
\n"; $ret .= "\n"; $ret .= "\n"; $ret .= "\n"; $ret .= "
\n"; $ret .= "\n"; $ret .= "\n"; $ret .= "
\n"; ########################### Dashboard Tab-Liste ############################################## $ret .= " \n"; ######################################################################################## for (my $t=0;$t<$tabcount;$t++){ my @tabgroup = split(",", $tabgroups[$t]); #Set temp. position for groups without an stored position for (my $i=0;$i<@tabgroup;$i++){ my @stabgroup = split(":", trim($tabgroup[$i])); if (index($tabsortings[$t],','.trim($stabgroup[0]).',') < 0) {$tabsortings[$t] = $tabsortings[$t]."t".$t."c".GetMaxColumnId($row,$colcount).",".trim($stabgroup[0]).",true,0,0:";} } %group = BuildGroupList($tabgroups[$t]); $ret .= "
\n"; $ret .= "
    \n"; $ret .= " \n"; ##################### Top Row (only one Column) ############################################# if ($row eq "top-center-bottom" || $row eq "top-center" || $row eq "top"){ $ret .= BuildDashboardTopRow($t,$id,$tabgroups[$t],$tabsortings[$t]); } ##################### Center Row (max. 5 Column) ############################################ if ($row eq "top-center-bottom" || $row eq "top-center" || $row eq "center-bottom" || $row eq "center"){ $ret .= BuildDashboardCenterRow($t,$id,$tabgroups[$t],$tabsortings[$t],$colcount);} ############################# Bottom Row (only one Column) ############################################ if ($row eq "top-center-bottom" || $row eq "center-bottom" || $row eq "bottom"){ $ret .= BuildDashboardBottomRow($t,$id,$tabgroups[$t],$tabsortings[$t]); } ############################################################################################# $ret .= "
    \n"; $ret .= "
\n"; $ret .= "
\n"; } $ret .= "
\n"; } else { $ret .= ""; $ret .= ""; $ret .= ""; $ret .= "
".$defs{$d}{TYPE}."
"; $ret .= ""; $ret .= ""; $ret .= ""; $ret .= ""; $ret .= "
".$defs{$d}{STATE}."
"; } return $ret; } sub BuildDashboardTopRow($$$$){ my ($t,$id, $dbgroups, $dbsorting) = @_; my $ret; $ret .= "\n"; $ret .= "
\n"; $ret .= "
\n"; $ret .= BuildGroupWidgets($t,"100",$id,$dbgroups,$dbsorting); $ret .= "
\n"; $ret .= "
\n"; $ret .= "\n"; return $ret; } sub BuildDashboardCenterRow($$$$$){ my ($t,$id, $dbgroups, $dbsorting, $colcount) = @_; my $ret; $ret .= "\n"; $ret .= "
\n"; for (my $i=0;$i<$colcount;$i++){ $ret .= "
\n"; $ret .= BuildGroupWidgets($t,$i,$id,$dbgroups,$dbsorting); $ret .= "
\n"; } $ret .= "
\n"; $ret .= "\n"; return $ret; } sub BuildDashboardBottomRow($$$$){ my ($t,$id, $dbgroups, $dbsorting) = @_; my $ret; $ret .= "\n"; $ret .= "
\n"; $ret .= "
\n"; $ret .= BuildGroupWidgets($t,"200",$id,$dbgroups,$dbsorting); $ret .= "
\n"; $ret .= "
\n"; $ret .= "\n"; return $ret; } sub BuildGroupWidgets($$$$$) { my ($tab,$column,$id,$dbgroups, $dbsorting) = @_; my $ret = ""; my $counter = 0; my @storedsorting = split(":", $dbsorting); my @dbgroup = split(",", $dbgroups); my $widgetheader = ""; foreach my $singlesorting (@storedsorting) { my @groupdata = split(",", $singlesorting); if (scalar(@groupdata) > 1) { if (index($dbsorting, "t".$tab."c".$column.",".$groupdata[1]) >= 0 && index($dbgroups, $groupdata[1]) >= 0 && $groupdata[1] ne "" ) { #group is set to tab $widgetheader = $groupdata[1]; foreach my $strdbgroup (@dbgroup) { my @groupicon = split(":", trim($strdbgroup)); if ($groupicon[0] eq $groupdata[1]) { if ($#groupicon > 0) { $widgetheader = FW_makeImage($groupicon[1],$groupicon[1],"dashboard_tabicon") . " ".$groupdata[1]; } } } $ret .= "
\n"; $ret .= "
\n"; $ret .= "
".$widgetheader."
\n"; $ret .= "
\n"; $ret .= BuildGroup($groupdata[1]); $ret .= "
\n"; $ret .= "
\n"; $ret .= "
\n"; $counter++; } } } return $ret; } sub BuildGroupList($) { my @dashboardgroups = split(",", $_[0]); #array for all groups to build an widget my %group = (); foreach my $d (sort keys %defs) { foreach my $grp (split(",", AttrVal($d, "group", ""))) { $grp = trim($grp); foreach my $g (@dashboardgroups){ my ($gtitle, $iconName) = split(":", trim($g)); $group{$grp}{$d} = 1 if($gtitle eq $grp); } } } return %group; } sub Dashboard_GetGroupList() { my %allGroups = (); foreach my $d (keys %defs ) { next if(IsIgnored($d)); foreach my $g (split(",", AttrVal($d, "group", ""))) { $allGroups{$g}{$d} = 1; } } my $ret = join(",", sort map { $_ =~ s/ /#/g ;$_} keys %allGroups); return $ret; } sub BuildGroup($) { my ($currentgroup) = @_; my $ret = ""; my $row = 1; my %extPage = (); my $rf = ($FW_room ? "&room=$FW_room" : ""); # stay in the room foreach my $g (keys %group) { next if ($g ne $currentgroup); $ret .= ""; foreach my $d (sort { lc(AttrVal($a,"sortby",AttrVal($a,"alias",$a))) cmp lc(AttrVal($b,"sortby",AttrVal($b,"alias",$b))) } keys %{$group{$g}}) { $ret .= sprintf("", ($row&1)?"odd":"even"); my $type = $defs{$d}{TYPE}; my $devName = AttrVal($d, "alias", $d); my $icon = AttrVal($d, "icon", ""); $icon = FW_makeImage($icon,$icon,"icon dashboard_groupicon") . " " if($icon); if ($type ne "weblink" && $type ne "SVG" && $type ne "readingsGroup" && $type ne "readingsHistory") { # Don't show Link by weblink, svg and readingsGroup $ret .= FW_pH "detail=$d", "$icon$devName", 1, "col1", 1; } $row++; my ($allSets, $cmdlist, $txt) = FW_devState($d, $rf, \%extPage); ############## Customize Result for Special Types ##################### my @txtarray = split(">", $txt); if (($type eq "readingsGroup" || $type eq "readingsHistory") && $txtarray[0] eq " -1) {$storeinfo = 0; } if ($storeinfo == 3) { $txtreturn .= $txtarray[$i].">"; } if ($storeinfo == 2 && index($txtarray[$i]," -1 ) { $storeinfo = $storeinfo+1;} if ($storeinfo == 1 && index($txtarray[$i]," -1 ) { $linkreturn = $txtarray[$i].">"; } if (index($txtarray[$i]," -1) {$storeinfo = $storeinfo+1; } } $ret .= ""; } else { $ret .= ""; } ########################################################### ###### Commands, slider, dropdown if(!$FW_ss && $cmdlist) { foreach my $cmd (split(":", $cmdlist)) { my $htmlTxt; my @c = split(' ', $cmd); if($allSets && $allSets =~ m/$c[0]:([^ ]*)/) { my $values = $1; foreach my $fn (sort keys %{$data{webCmdFn}}) { no strict "refs"; $htmlTxt = &{$data{webCmdFn}{$fn}}($FW_wname, $d, $FW_room, $cmd, $values); use strict "refs"; last if(defined($htmlTxt)); } } if($htmlTxt) { $ret .= $htmlTxt; } else { $ret .= FW_pH "cmd.$d=set $d $cmd$rf", $cmd, 1, "col3", 1; } } } $ret .= ""; } $ret .= "
$txtreturn$txt
"; } if ($ret eq "") { $ret .= ""; $ret .= ""; $ret .= ""; $ret .= ""; $ret .= "
Unknown Group: $currentgroup
Check if the group attribute is really set
Check if the groupname is correct written
"; } return $ret; } sub GetMaxColumnId($$) { my ($row, $colcount) = @_; my $maxcolid = "0"; if (index($row,"bottom") > 0) { $maxcolid = "200"; } elsif (index($row,"center") > 0) { $maxcolid = $colcount-1; } elsif (index($row,"top") > 0) { $maxcolid = "100"; } return $maxcolid; } sub CheckDashboardEntry($) { my ($hash) = @_; my $now = time(); my $timeToExec = $now + 5; RemoveInternalTimer($hash); InternalTimer ($timeToExec, 'CreateDashboardEntry', $hash, 0); InternalTimer ($timeToExec, 'CheckDashboardAttributUssage', $hash, 0); } sub CheckDashboardAttributUssage($) { # replaces old disused attributes and their values | set minimal attributes my ($hash) = @_; my $d = $hash->{NAME}; my $detailnote = ""; # --------- Set minimal Attributes in the hope to make it easier for beginners -------------------- my $tabcount = AttrVal($defs{$d}{NAME}, "dashboard_tabcount", "0"); if ($tabcount eq "0") { FW_fC("attr ".$d." dashboard_tabcount 1"); } my $tab1groups = AttrVal($defs{$d}{NAME}, "dashboard_tab1groups", ""); if ($tab1groups eq "") { FW_fC("attr ".$d." dashboard_tab1groups Set Your Groups - See Attribute dashboard_tab1groups-"); } # ------------------------------------------------------------------------------------------------- # ---------------- Delete empty Groups entries ---------------------------------------------------------- my $tabgroups = AttrVal($defs{$d}{NAME}, "dashboard_tab1groups", "999"); if ($tabgroups eq "1" ) { FW_fC("deleteattr ".$d." dashboard_tab1groups"); } $tabgroups = AttrVal($defs{$d}{NAME}, "dashboard_tab2groups", "999"); if ($tabgroups eq "1" ) { FW_fC("deleteattr ".$d." dashboard_tab2groups"); } $tabgroups = AttrVal($defs{$d}{NAME}, "dashboard_tab3groups", "999"); if ($tabgroups eq "1" ) { FW_fC("deleteattr ".$d." dashboard_tab3groups"); } $tabgroups = AttrVal($defs{$d}{NAME}, "dashboard_tab4groups", "999"); if ($tabgroups eq "1" ) { FW_fC("deleteattr ".$d." dashboard_tab4groups"); } $tabgroups = AttrVal($defs{$d}{NAME}, "dashboard_tab5groups", "999"); if ($tabgroups eq "1" ) { FW_fC("deleteattr ".$d." dashboard_tab5groups"); } # ------------------------------------------------------------------------------------------------- my $lockstate = AttrVal($defs{$d}{NAME}, "dashboard_lockstate", ""); # outdates 04.2014 if ($lockstate ne "") { { FW_fC("deleteattr ".$d." dashboard_lockstate"); } Log3 $hash, 3, "[".$hash->{NAME}. " V".$dashboardversion."]"." Using an outdated no longer used Attribute or Value. This has been corrected. Don't forget to save config. [dashboard_lockstate]"; } my $showhelper = AttrVal($defs{$d}{NAME}, "dashboard_showhelper", ""); # outdates 04.2014 if ($showhelper ne "") { { FW_fC("deleteattr ".$d." dashboard_showhelper"); } Log3 $hash, 3, "[".$hash->{NAME}. " V".$dashboardversion."]"." Using an outdated no longer used Attribute or Value. This has been corrected. Don't forget to save config. [dashboard_showhelper]"; } my $showtabs = AttrVal($defs{$d}{NAME}, "dashboard_showtabs", ""); # delete values 04.2014 if ($showtabs eq "tabs-at-the-top-buttonbar-hidden") { { FW_fC("set ".$d." dashboard_showtabs tabs-and-buttonbar-at-the-top"); } Log3 $hash, 3, "[".$hash->{NAME}. " V".$dashboardversion."]"." Using an outdated no longer used Attribute or Value. This has been corrected. Don't forget to save config. [tabs-at-the-top-buttonbar-hidden]"; } if ($showtabs eq "tabs-on-the-bottom-buttonbar-hidden") { { FW_fC("set ".$d." dashboard_showtabs tabs-and-buttonbar-on-the-bottom"); } Log3 $hash, 3, "[".$hash->{NAME}. " V".$dashboardversion."]"." Using an outdated no longer used Attribute or Value. This has been corrected. Don't forget to save config. [tabs-on-the-bottom-buttonbar-hidden]"; } } sub CreateDashboardEntry($) { my ($hash) = @_; my $h = $hash->{NAME}; if (!defined $defs{$h."_weblink"}) { FW_fC("define ".$h."_weblink weblink htmlCode {DashboardAsHtml(\"".$h."\")}"); Log3 $hash, 3, "[".$hash->{NAME}. " V".$dashboardversion."]"." Weblink dosen't exists. Created weblink ".$h."_weblink. Don't forget to save config."; } FW_fC("attr ".$h."_weblink room ".$dashboardhiddenroom); foreach my $dn (sort keys %defs) { if ($defs{$dn}{TYPE} eq "FHEMWEB" && $defs{$dn}{NAME} !~ /FHEMWEB:/) { my $hr = AttrVal($defs{$dn}{NAME}, "hiddenroom", ""); if (index($hr,$dashboardhiddenroom) == -1){ if ($hr eq "") {FW_fC("attr ".$defs{$dn}{NAME}." hiddenroom ".$dashboardhiddenroom);} else {FW_fC("attr ".$defs{$dn}{NAME}." hiddenroom ".$hr.",".$dashboardhiddenroom);} Log3 $hash, 3, "[".$hash->{NAME}. " V".$dashboardversion."]"." Added hiddenroom '".$dashboardhiddenroom."' to ".$defs{$dn}{NAME}.". Don't forget to save config."; } } } } 1; =pod =begin html

Dashboard

=end html =begin html_DE

Dashboard

=end html_DE =cut