mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-22 02:10:32 +00:00
LightScene: add html overview of all configured scenes in detail view.
allow usage of overview in a weblink. git-svn-id: https://svn.fhem.de/fhem/trunk@3404 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
cfe8635b7b
commit
0c7508fc3c
@ -1,5 +1,7 @@
|
|||||||
# Add changes at the top of the list. Keep it in ASCII
|
# Add changes at the top of the list. Keep it in ASCII
|
||||||
- SVN
|
- SVN
|
||||||
|
- feature: LightScene: add html overview of all configured scenes in
|
||||||
|
detail view. allow usage of overview in a weblink.
|
||||||
- feature: FLOORPLAN: enhanced detail-screen for floorplans in fhemweb,
|
- feature: FLOORPLAN: enhanced detail-screen for floorplans in fhemweb,
|
||||||
arrange-mode has delete-button, new command
|
arrange-mode has delete-button, new command
|
||||||
"get <floorplan-name> config"
|
"get <floorplan-name> config"
|
||||||
|
@ -6,6 +6,8 @@ use warnings;
|
|||||||
use POSIX;
|
use POSIX;
|
||||||
use JSON;
|
use JSON;
|
||||||
|
|
||||||
|
use vars qw(%FW_webArgs); # all arguments specified in the GET
|
||||||
|
|
||||||
sub LightScene_Initialize($)
|
sub LightScene_Initialize($)
|
||||||
{
|
{
|
||||||
my ($hash) = @_;
|
my ($hash) = @_;
|
||||||
@ -15,6 +17,8 @@ sub LightScene_Initialize($)
|
|||||||
$hash->{UndefFn} = "LightScene_Undefine";
|
$hash->{UndefFn} = "LightScene_Undefine";
|
||||||
$hash->{SetFn} = "LightScene_Set";
|
$hash->{SetFn} = "LightScene_Set";
|
||||||
$hash->{GetFn} = "LightScene_Get";
|
$hash->{GetFn} = "LightScene_Get";
|
||||||
|
|
||||||
|
$hash->{FW_detailFn} = "LightScene_detailFn";
|
||||||
}
|
}
|
||||||
|
|
||||||
sub LightScene_Define($$)
|
sub LightScene_Define($$)
|
||||||
@ -26,7 +30,7 @@ sub LightScene_Define($$)
|
|||||||
return "Usage: define <name> LightScene <device>+" if(@args < 3);
|
return "Usage: define <name> LightScene <device>+" if(@args < 3);
|
||||||
|
|
||||||
my $name = shift(@args);
|
my $name = shift(@args);
|
||||||
my $tyoe = shift(@args);
|
my $type = shift(@args);
|
||||||
|
|
||||||
my %list;
|
my %list;
|
||||||
foreach my $a (@args) {
|
foreach my $a (@args) {
|
||||||
@ -55,6 +59,102 @@ sub LightScene_Undefine($$)
|
|||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sub
|
||||||
|
LightScene_2html($)
|
||||||
|
{
|
||||||
|
my($hash) = @_;
|
||||||
|
$hash = $defs{$hash} if( ref($hash) ne 'HASH' );
|
||||||
|
|
||||||
|
return undef if( !$hash );
|
||||||
|
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
my $room = $FW_webArgs{room};
|
||||||
|
|
||||||
|
my $show_heading = 1;
|
||||||
|
|
||||||
|
my $row = 1;
|
||||||
|
my $ret = "";
|
||||||
|
$ret .= "<table>";
|
||||||
|
$ret .= "<tr><td><div class=\"devType\"><a href=\"$FW_ME$FW_subdir?detail=$name\">".AttrVal($name, "alias", $name)."</a></div></td></tr>" if( $show_heading );
|
||||||
|
$ret .= "<tr><td><table class=\"block wide\">";
|
||||||
|
|
||||||
|
$ret .= sprintf("<tr class=\"%s\">", ($row&1)?"odd":"even");
|
||||||
|
$row++;
|
||||||
|
$ret .= "<td><div></div></td>";
|
||||||
|
foreach my $d (sort keys %{ $hash->{CONTENT} }) {
|
||||||
|
$ret .= "<td><div class=\"col2\"><a href=\"$FW_ME$FW_subdir?detail=$d\">". AttrVal($d, "alias", $d) ."</a></div></td>";
|
||||||
|
}
|
||||||
|
|
||||||
|
if( defined($FW_webArgs{detail}) ) {
|
||||||
|
$room = "&detail=$FW_webArgs{detail}";
|
||||||
|
|
||||||
|
$ret .= sprintf("<tr class=\"%s\">", ($row&1)?"odd":"even");
|
||||||
|
$row++;
|
||||||
|
$ret .= "<td><div></div></td>";
|
||||||
|
foreach my $d (sort keys %{ $hash->{CONTENT} }) {
|
||||||
|
my %extPage = ();
|
||||||
|
my ($allSets, $cmdlist, $txt) = FW_devState($d, $room, \%extPage);
|
||||||
|
$ret .= "<td id=\"$d\">$txt</td>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach my $scene (sort keys %{ $hash->{SCENES} }) {
|
||||||
|
$ret .= sprintf("<tr class=\"%s\">", ($row&1)?"odd":"even");
|
||||||
|
$row++;
|
||||||
|
|
||||||
|
my $srf = $room ? "&room=$room" : "";
|
||||||
|
$srf = $room if( $room && $room =~ m/^&/ );
|
||||||
|
my $link = "cmd=set $name scene $scene";
|
||||||
|
my $txt = $scene;
|
||||||
|
if( AttrVal($FW_wname, "longpoll", 1)) {
|
||||||
|
$txt = "<a onClick=\"FW_cmd('$FW_ME$FW_subdir?XHR=1&$link')\">$txt</a>";
|
||||||
|
} else {
|
||||||
|
$txt = "<a href=\"$FW_ME$FW_subdir?$link$srf\">$txt</a>";
|
||||||
|
}
|
||||||
|
$ret .= "<td><div>$txt</div></td>";
|
||||||
|
|
||||||
|
foreach my $d (sort keys %{ $hash->{CONTENT} }) {
|
||||||
|
if( !defined($hash->{SCENES}{$scene}{$d} ) ) {
|
||||||
|
$ret .= "<td><div></div></td>";
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $icon;
|
||||||
|
my $state = $hash->{SCENES}{$scene}{$d};
|
||||||
|
$icon = $state->{icon} if( ref($state) eq 'HASH' );
|
||||||
|
$state = $state->{state} if( ref($state) eq 'HASH' );
|
||||||
|
|
||||||
|
my ($isHtml);
|
||||||
|
$isHtml = 0;
|
||||||
|
|
||||||
|
if( !$icon ) {
|
||||||
|
my ($link);
|
||||||
|
($icon, $link, $isHtml) = FW_dev2image($d, $state);
|
||||||
|
}
|
||||||
|
$icon = FW_iconName($state) if( !$icon );
|
||||||
|
|
||||||
|
if( $icon ) {
|
||||||
|
$ret .= "<td><div class=\"col2\">". ($isHtml ? $icon : FW_makeImage($icon, $state)) ."</div></td>";
|
||||||
|
} else {
|
||||||
|
$ret .= "<td><div>". $state ."</div></td>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret .= "</table></td></tr>";
|
||||||
|
$ret .= "</table>";
|
||||||
|
$ret .= "</br>";
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
|
sub
|
||||||
|
LightScene_detailFn()
|
||||||
|
{
|
||||||
|
my ($FW_wname, $d, $room, $pageHash) = @_; # pageHash is set for summaryFn.
|
||||||
|
|
||||||
|
return LightScene_2html($d);
|
||||||
|
}
|
||||||
|
|
||||||
sub
|
sub
|
||||||
LightScene_Notify($$)
|
LightScene_Notify($$)
|
||||||
{
|
{
|
||||||
@ -69,6 +169,43 @@ LightScene_Notify($$)
|
|||||||
LightScene_Save();
|
LightScene_Save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
my $max = int(@{$dev->{CHANGED}});
|
||||||
|
for (my $i = 0; $i < $max; $i++) {
|
||||||
|
my $s = $dev->{CHANGED}[$i];
|
||||||
|
$s = "" if(!defined($s));
|
||||||
|
|
||||||
|
if($s =~ m/^RENAMED ([^ ]*) ([^ ]*)$/) {
|
||||||
|
my ($old, $new) = ($1, $2);
|
||||||
|
if( defined($hash->{CONTENT}{$old}) ) {
|
||||||
|
|
||||||
|
$hash->{DEF} =~ s/(\s*)$old(\s*)/$1$new$2/;
|
||||||
|
|
||||||
|
foreach my $scene (keys %{ $hash->{SCENES} }) {
|
||||||
|
$hash->{SCENES}{$scene}{$new} = $hash->{SCENES}{$scene}{$old} if( defined($hash->{SCENES}{$scene}{$old}) );
|
||||||
|
delete( $hash->{SCENES}{$scene}{$old} );
|
||||||
|
}
|
||||||
|
|
||||||
|
delete( $hash->{CONTENT}{$old} );
|
||||||
|
$hash->{CONTENT}{$new} = 1;
|
||||||
|
}
|
||||||
|
} elsif($s =~ m/^DELETED ([^ ]*)$/) {
|
||||||
|
my ($name) = ($1);
|
||||||
|
|
||||||
|
if( defined($hash->{CONTENT}{$name}) ) {
|
||||||
|
|
||||||
|
$hash->{DEF} =~ s/(\s*)$name(\s*)/ /;
|
||||||
|
$hash->{DEF} =~ s/^ //;
|
||||||
|
$hash->{DEF} =~ s/ $//;
|
||||||
|
|
||||||
|
foreach my $scene (keys %{ $hash->{SCENES} }) {
|
||||||
|
delete( $hash->{SCENES}{$scene}{$name} );
|
||||||
|
}
|
||||||
|
|
||||||
|
delete( $hash->{CONTENT}{$name} );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -85,7 +222,7 @@ LightScene_Save()
|
|||||||
{
|
{
|
||||||
my $time_now = TimeNow();
|
my $time_now = TimeNow();
|
||||||
return if( $time_now eq $LightScene_LastSaveTime);
|
return if( $time_now eq $LightScene_LastSaveTime);
|
||||||
$LightScene_LastSaveTime = $time_now ;
|
$LightScene_LastSaveTime = $time_now;
|
||||||
|
|
||||||
return "No statefile specified" if(!$attr{global}{statefile});
|
return "No statefile specified" if(!$attr{global}{statefile});
|
||||||
my $statefile = myStatefileName();
|
my $statefile = myStatefileName();
|
||||||
@ -154,7 +291,7 @@ LightScene_Set($@)
|
|||||||
|
|
||||||
if( !defined($cmd) ){ return "$name: set needs at least one parameter" };
|
if( !defined($cmd) ){ return "$name: set needs at least one parameter" };
|
||||||
|
|
||||||
if( $cmd eq "?" ){ return "Unknown argument ?, choose one of remove save set scene:".join(",", sort keys %{$hash->{SCENES}}) };
|
if( $cmd eq "?" ){ return "Unknown argument ?, choose one of remove:".join(",", sort keys %{$hash->{SCENES}}) ." save set scene:".join(",", sort keys %{$hash->{SCENES}})};
|
||||||
|
|
||||||
if( $cmd eq "save" && !defined( $scene ) ) { return "Usage: set $name save <scene_name>" };
|
if( $cmd eq "save" && !defined( $scene ) ) { return "Usage: set $name save <scene_name>" };
|
||||||
if( $cmd eq "scene" && !defined( $scene ) ) { return "Usage: set $name scene <scene_name>" };
|
if( $cmd eq "scene" && !defined( $scene ) ) { return "Usage: set $name scene <scene_name>" };
|
||||||
@ -167,13 +304,11 @@ LightScene_Set($@)
|
|||||||
my ($d, @args) = @a;
|
my ($d, @args) = @a;
|
||||||
|
|
||||||
if( !defined( $scene ) || !defined( $d ) || !@args ) { return "Usage: set $name set <scene_name> <device> <cmd>" };
|
if( !defined( $scene ) || !defined( $d ) || !@args ) { return "Usage: set $name set <scene_name> <device> <cmd>" };
|
||||||
|
return "no stored scene >$scene<" if( !defined($hash->{SCENES}{$scene} ) );
|
||||||
|
return "device >$d< is not a member of scene >$scene<" if( !defined($hash->{CONTENT}{$d} ) );
|
||||||
|
|
||||||
if( defined($hash->{SCENES}{$scene})
|
$hash->{SCENES}{$scene}{$d} = join(" ", @args);
|
||||||
&& defined($hash->{SCENES}{$scene}{$d}) )
|
return undef;
|
||||||
{
|
|
||||||
$hash->{SCENES}{$scene}{$d} = join(" ", @args);
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -187,54 +322,74 @@ LightScene_Set($@)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if( $cmd eq "save" ) {
|
if( $cmd eq "save" ) {
|
||||||
my $status = "";
|
my $state = "";
|
||||||
if( $defs{$d}{TYPE} eq 'CUL_HM' ) {
|
my $type = $defs{$d}->{TYPE};
|
||||||
|
$type = "" if( !defined($type) );
|
||||||
|
|
||||||
|
if( $type eq 'CUL_HM' ) {
|
||||||
my $subtype = AttrVal($d,"subType","");
|
my $subtype = AttrVal($d,"subType","");
|
||||||
if( $subtype eq "switch" ) {
|
if( $subtype eq "switch" ) {
|
||||||
$status = Value($d);
|
$state = Value($d);
|
||||||
} elsif( $subtype eq "dimmer" ) {
|
} elsif( $subtype eq "dimmer" ) {
|
||||||
$status = Value($d);
|
$state = Value($d);
|
||||||
} else {
|
} else {
|
||||||
$status = Value($d);
|
$state = Value($d);
|
||||||
}
|
}
|
||||||
} elsif( $defs{$d}{TYPE} eq 'FS20' ) {
|
} elsif( $type eq 'FS20' ) {
|
||||||
$status = Value($d);
|
$state = Value($d);
|
||||||
} elsif( $defs{$d}{TYPE} eq 'HUEDevice' ) {
|
} elsif( $type eq 'SWAP_0000002200000003' ) {
|
||||||
|
$state = Value($d);
|
||||||
|
$state = "rgb ". $state if( $state ne "off" );
|
||||||
|
} elsif( $type eq 'HUEDevice' ) {
|
||||||
my $subtype = AttrVal($d,"subType","");
|
my $subtype = AttrVal($d,"subType","");
|
||||||
if( $subtype eq "switch" || Value($d) eq "off" ) {
|
if( $subtype eq "switch" || Value($d) eq "off" ) {
|
||||||
$status = Value($d);
|
$state = Value($d);
|
||||||
} elsif( $subtype eq "dimmer" ) {
|
} elsif( $subtype eq "dimmer" ) {
|
||||||
$status = "bri ". ReadingsVal($d,'bri',"0");
|
$state = "bri ". ReadingsVal($d,'bri',"0");
|
||||||
} elsif( $subtype eq "colordimmer" ) {
|
} elsif( $subtype eq "colordimmer" ) {
|
||||||
if( ReadingsVal($d,"colormode","") eq "ct" ) {
|
if( ReadingsVal($d,"colormode","") eq "ct" ) {
|
||||||
ReadingsVal($d,"ct","") =~ m/(\d+) .*/;
|
ReadingsVal($d,"ct","") =~ m/(\d+) .*/;
|
||||||
$status = "bri ". ReadingsVal($d,'bri',"0") ." : ct ". $1;
|
$state = "bri ". ReadingsVal($d,'bri',"0") ." : ct ". $1;
|
||||||
} else {
|
} else {
|
||||||
$status = "bri ". ReadingsVal($d,'bri',"0") ." : xy ". ReadingsVal($d,'xy',"");
|
$state = "bri ". ReadingsVal($d,'bri',"0") ." : xy ". ReadingsVal($d,'xy',"");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} elsif( $defs{$d}{TYPE} eq 'IT' ) {
|
} elsif( $type eq 'IT' ) {
|
||||||
my $subtype = AttrVal($d,"model","");
|
my $subtype = AttrVal($d,"model","");
|
||||||
if( $subtype eq "itswitch" ) {
|
if( $subtype eq "itswitch" ) {
|
||||||
$status = Value($d);
|
$state = Value($d);
|
||||||
} elsif( $subtype eq "itdimmer" ) {
|
} elsif( $subtype eq "itdimmer" ) {
|
||||||
$status = Value($d);
|
$state = Value($d);
|
||||||
} else {
|
} else {
|
||||||
$status = Value($d);
|
$state = Value($d);
|
||||||
}
|
}
|
||||||
} elsif( $defs{$d}{TYPE} eq 'TRX_LIGHT' ) {
|
} elsif( $type eq 'TRX_LIGHT' ) {
|
||||||
$status = Value($d);
|
$state = Value($d);
|
||||||
} else {
|
} else {
|
||||||
$status = Value($d);
|
$state = Value($d);
|
||||||
}
|
}
|
||||||
|
|
||||||
$hash->{SCENES}{$scene}{$d} = $status;
|
if( $type eq "SWAP_0000002200000003" || $type eq "HUEDevice" ) {
|
||||||
$ret .= $d .": ". $status ."\n";
|
my %desc;
|
||||||
|
$desc{state} = $state;
|
||||||
|
my ($icon, $link, $isHtml) = FW_dev2image($d);
|
||||||
|
$desc{icon} = $icon;
|
||||||
|
$hash->{SCENES}{$scene}{$d} = \%desc;
|
||||||
|
} else {
|
||||||
|
$hash->{SCENES}{$scene}{$d} = $state;
|
||||||
|
}
|
||||||
|
|
||||||
|
$ret .= $d .": ". $state ."\n" if( defined($FW_webArgs{room}) && $FW_webArgs{room} eq "all" ); #only if telnet
|
||||||
|
|
||||||
} elsif ( $cmd eq "scene" ) {
|
} elsif ( $cmd eq "scene" ) {
|
||||||
$hash->{STATE} = $scene;
|
$hash->{STATE} = $scene;
|
||||||
|
next if( !defined($hash->{SCENES}{$scene}{$d}));
|
||||||
|
|
||||||
|
my $state = $hash->{SCENES}{$scene}{$d};
|
||||||
|
$state = $state->{state} if( ref($state) eq 'HASH' );
|
||||||
|
|
||||||
$ret .= " " if( $ret );
|
$ret .= " " if( $ret );
|
||||||
$ret .= CommandSet(undef,"$d $hash->{SCENES}{$scene}{$d}");
|
$ret .= CommandSet(undef,"$d $state");
|
||||||
} else {
|
} else {
|
||||||
$ret = "Unknown argument $cmd, choose one of save scene";
|
$ret = "Unknown argument $cmd, choose one of save scene";
|
||||||
}
|
}
|
||||||
@ -260,7 +415,9 @@ LightScene_Get($@)
|
|||||||
if( $cmd eq "scene" && @a < 3 ) { return "Usage: get scene <scene_name>" };
|
if( $cmd eq "scene" && @a < 3 ) { return "Usage: get scene <scene_name>" };
|
||||||
|
|
||||||
my $ret = "";
|
my $ret = "";
|
||||||
if( $cmd eq "scenes" ) {
|
if( $cmd eq "html" ) {
|
||||||
|
return LightScene_2html($hash);
|
||||||
|
} elsif( $cmd eq "scenes" ) {
|
||||||
foreach my $scene (sort keys %{ $hash->{SCENES} }) {
|
foreach my $scene (sort keys %{ $hash->{SCENES} }) {
|
||||||
$ret .= $scene ."\n";
|
$ret .= $scene ."\n";
|
||||||
}
|
}
|
||||||
@ -270,7 +427,12 @@ LightScene_Get($@)
|
|||||||
my $scene = $a[2];
|
my $scene = $a[2];
|
||||||
if( defined($hash->{SCENES}{$scene}) ) {
|
if( defined($hash->{SCENES}{$scene}) ) {
|
||||||
foreach my $d (sort keys %{ $hash->{SCENES}{$scene} }) {
|
foreach my $d (sort keys %{ $hash->{SCENES}{$scene} }) {
|
||||||
$ret .= $d .": ". $hash->{SCENES}{$scene}{$d} ."\n";
|
next if( !defined($hash->{SCENES}{$scene}{$d}));
|
||||||
|
|
||||||
|
my $state = $hash->{SCENES}{$scene}{$d};
|
||||||
|
$state = $state->{state} if( ref($state) eq 'HASH' );
|
||||||
|
|
||||||
|
$ret .= $d .": ". $state ."\n";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$ret = "no scene <$scene> defined";
|
$ret = "no scene <$scene> defined";
|
||||||
@ -278,7 +440,7 @@ LightScene_Get($@)
|
|||||||
return $ret;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return "Unknown argument $cmd, choose one of scenes scene";
|
return "Unknown argument $cmd, choose one of html scenes scene";
|
||||||
}
|
}
|
||||||
|
|
||||||
1;
|
1;
|
||||||
@ -303,9 +465,20 @@ LightScene_Get($@)
|
|||||||
<ul>
|
<ul>
|
||||||
<code>define light_group LightScene Lampe1 Lampe2 Dimmer1</code><br>
|
<code>define light_group LightScene Lampe1 Lampe2 Dimmer1</code><br>
|
||||||
<code>define kino_group LightScene LampeDecke LampeFernseher Fernseher Verstaerker</code><br>
|
<code>define kino_group LightScene LampeDecke LampeFernseher Fernseher Verstaerker</code><br>
|
||||||
|
<code>define Wohnzimmer LightScene Leinwand Beamer TV Leselampe Deckenlampe</code><br>
|
||||||
</ul>
|
</ul>
|
||||||
</ul><br>
|
</ul><br>
|
||||||
|
|
||||||
|
The device detail view will show an html overview of the current state of all included devices and all
|
||||||
|
configured scenes with the device states for each. The column heading with the device names is clickable
|
||||||
|
to go to detail view of this device. The first row that displays the current device state is clickable
|
||||||
|
and should react like a click on the device icon in a room overview would. this can be used to interactively
|
||||||
|
configure a new scene and save it with the command menu of the detail view. The first column of the table with
|
||||||
|
the scene names ic clickable to activate the scene.<br><br>
|
||||||
|
|
||||||
|
A weblink with a scene overview that can be included in any room or a floorplan can be created with:
|
||||||
|
<ul><code>define wlScene weblink htmlCode {LightScene_2html("Scene")}</code></ul>
|
||||||
|
|
||||||
<a name="LightScene_Set"></a>
|
<a name="LightScene_Set"></a>
|
||||||
<b>Set</b>
|
<b>Set</b>
|
||||||
<ul>
|
<ul>
|
||||||
@ -326,7 +499,7 @@ LightScene_Get($@)
|
|||||||
<li>scene <scene_name></li>
|
<li>scene <scene_name></li>
|
||||||
</ul><br>
|
</ul><br>
|
||||||
|
|
||||||
</ul><br>
|
</ul>
|
||||||
|
|
||||||
=end html
|
=end html
|
||||||
=cut
|
=cut
|
||||||
|
Loading…
x
Reference in New Issue
Block a user