Structure changes by Tobias

git-svn-id: svn://svn.code.sf.net/p/fhem/code/trunk@1869 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
rudolfkoenig
2012-09-19 07:29:38 +00:00
parent 078687605b
commit a4e4d4cfea
2 changed files with 216 additions and 15 deletions

View File

@@ -4,6 +4,8 @@ package main;
use strict;
use warnings;
#use Data::Dumper;
#####################################
sub
@@ -13,9 +15,11 @@ structure_Initialize($)
$hash->{DefFn} = "structure_Define";
$hash->{UndefFn} = "structure_Undef";
$hash->{NotifyFn} = "structure_Notify";
$hash->{SetFn} = "structure_Set";
$hash->{AttrFn} = "structure_Attr";
$hash->{AttrList} = "clientstate_priority clientstate_behavior:relative,absolute";
addToAttrList("structexclude");
my %ahash = ( Fn=>"CommandAddStruct",
@@ -43,6 +47,7 @@ structure_Define($$)
my $stype = shift(@a);
addToAttrList($stype);
addToAttrList($stype . "_map");
$hash->{ATTR} = $stype;
my %list;
@@ -70,6 +75,171 @@ structure_Undef($$)
return undef;
}
#############################
# returns the unique keys of the given array
# @my_array = ("one","two","three","two","three");
# print join(" ", @my_array), "\n";
# print join(" ", uniq(@my_array)), "\n";
sub uniq {
return keys %{{ map { $_ => 1 } @_ }};
}
#############################
sub structure_Notify($$)
{
my ($hash, $dev) = @_;
#Log 1, Dumper($hash);
my $me = $hash->{NAME};
my $devmap = $hash->{ATTR}."_map";
# lade das Verhalten, Standard ist absolute
my $behavior = AttrVal($me,"clientstate_behavior", "absolute");
my @clientstate;
return "" if($attr{$me} && $attr{$me}{disable});
#pruefen ob Devices welches das notify ausgeloest hat Mitglied dieser
# Struktur ist
return "" if (!$hash->{CONTENT}->{$dev->{NAME}});
# hier nur den Struktur-Status anpassen wenn
# a) behavior=absolute oder
# b) behavior=relative UND das Attr clientstate_priority gefaellt ist
my @structPrio = split(" ", $attr{$me}{clientstate_priority})
if($attr{$me}{clientstate_priority});
return "" if (!@structPrio && $behavior eq "relative");
# assoziatives Array aus Prioritaetsliste aufbauen
# Bsp: Original: "On|An Off|Aus"
# wobei der erste Wert der "Oder"-Liste als Status der Struktur uebernommen
# wird hier also On oder Off
# priority[On]=0
# priority[An]=0
# priority[Off]=1
# priority[Aus]=1
my %priority;
my (@priority, @foo);
for (my $i=0; $i<@structPrio; $i++) {
@foo = split(/\|/, $structPrio[$i]);
for (my $j=0; $j<@foo;$j++) {
$priority{$foo[$j]} = $i+1;
$priority[$i+1]=$foo[0];
}
}
undef @foo;
undef @structPrio;
#Log 1, Dumper(%priority) . "\n";
$hash->{INSET} = 1;
my $minprio = 99999;
my $devstate;
#ueber jedes Device das zu dieser Struktur gehoert
foreach my $d (sort keys %{ $hash->{CONTENT} }) {
next if(!$defs{$d});
if($defs{$d}{INSET}) {
Log 1, "ERROR: endless loop detected for $d in " . $hash->{NAME};
next;
}
# wenn zum Device das "structexclude" gesetzt ist, wird dieses nicht
# beruecksichtigt
if($attr{$d} && $attr{$d}{structexclude}) {
my $se = $attr{$d}{structexclude};
next if($hash->{NAME} =~ m/$se/);
}
# Status des Devices gemaess den Regeln des gesetztes StrukturAttr
# umformatieren
if ($attr{$d}{$devmap}) {
my @gruppe = split(" ", $attr{$d}{$devmap});
my @value;
for (my $i=0; $i<@gruppe; $i++) {
@value = split(":", $gruppe[$i]);
if(@value == 1) {
# nur das zu lesende Reading ist angegeben, zb. bei 1wire Modul
# OWSWITCH
#Bsp: A --> nur Reading A gehuert zur Struktur
#Bsp: A B --> Reading A und B gehuert zur Struktur
$devstate = ReadingsVal($d, $value[0], undef);
push(@clientstate, $devstate);
} elsif(@value == 2) {
# zustand wenn der Status auf dem in der Struktur definierten
# umdefiniert werden muss
# bsp: on:An
if($devstate eq $value[0]){
$devstate = $value[1];
push(@clientstate, $devstate);
$i=99999;
}
} elsif(@value == 3) {
# Das zu lesende Reading wurde mit angegeben:
# Reading:OriginalStatus:NeuerStatus wenn zb. ein Device mehrere
# Readings abbildet, zb. 1wire DS2406, DS2450 Bsp: A:Zu.:Geschlossen
$devstate = ReadingsVal($d, $value[0], undef);
if($devstate eq $value[1]){
$devstate = $value[2];
push(@clientstate, $devstate);
# $i=99999; entfernt, wenn Device mehrere Ports/Readings abbildet
# wird beim ersten Auftreten sonst nicht weiter geprueft
}
}
# Log 1, "Dev: ".$d." Anzahl: ".@value." Value:".$value[0]." devstate:
# ".$devstate;
$minprio = $priority{$devstate}
if($devstate &&
$priority{$devstate} &&
$priority{$devstate} < $minprio);
}
} else {
# falls kein mapping im Device angegeben wurde
$devstate = ReadingsVal($d, "state", undef);
$minprio = $priority{$devstate}
if($devstate &&
$priority{$devstate} &&
$priority{$devstate} < $minprio);
push(@clientstate, $devstate);
}
#besser als 1 kann minprio nicht werden
last if($minprio == 1);
} #foreach
@clientstate = uniq(@clientstate);# eleminiere alle Dubletten
#ermittle Endstatus
my $newState;
if($behavior eq "absolute"){
# wenn absolute, dann gebe undefinierten Status aus falls die Clients
# unterschiedliche Status' haben
if(@clientstate > 1) { $newState = "undefined";}
else { $newState = $clientstate[0];}
} elsif($behavior eq "relative" && $minprio < 99999) {
$newState = $priority[$minprio];
} else {
$newState = "undefined";
}
#eigenen Status jetzt setzen, nur wenn abweichend
if($hash->{STATE} ne $newState) {
Log 3, "Update structure '" .$me . "' to " . $newState .
" because device '" .$dev->{NAME}. "' has changed";
$hash->{STATE} = $newState;
readingsBeginUpdate($hash);
readingsUpdate($hash, "state", $newState);
readingsEndUpdate($hash, 1);
}
#Log 1, "devstate: ".$devstate." - minprio final: " . $minprio . "\n";
#Log 1, Dumper(%priority);
delete($hash->{INSET});
undef;
}
#####################################
sub