98_powerMap: refactoring get-devices; improved support for 3rd party module integration
git-svn-id: https://svn.fhem.de/fhem/trunk@13171 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
@@ -25,8 +25,6 @@
|
|||||||
#
|
#
|
||||||
################################################################################
|
################################################################################
|
||||||
# TODO
|
# TODO
|
||||||
# - help users setting powerMap attribute using internal hash database or
|
|
||||||
# by copying from $defs{$name}{powerMap}
|
|
||||||
# - document how to include powerMap for other module maintainers
|
# - document how to include powerMap for other module maintainers
|
||||||
# (see 50_HP1000)
|
# (see 50_HP1000)
|
||||||
#
|
#
|
||||||
@@ -47,9 +45,9 @@ sub powerMap_Attr(@);
|
|||||||
sub powerMap_Notify($$);
|
sub powerMap_Notify($$);
|
||||||
|
|
||||||
sub powerMap_AttrVal($$$$);
|
sub powerMap_AttrVal($$$$);
|
||||||
sub powerMap_load($$;$);
|
sub powerMap_load($$;$$);
|
||||||
sub powerMap_unload($$);
|
sub powerMap_unload($$);
|
||||||
sub powerMap_FindPowerMaps(;$);
|
sub powerMap_findPowerMaps(;$);
|
||||||
sub powerMap_power($$$;$);
|
sub powerMap_power($$$;$);
|
||||||
sub powerMap_energy($$;$);
|
sub powerMap_energy($$;$);
|
||||||
sub powerMap_update($;$);
|
sub powerMap_update($;$);
|
||||||
@@ -588,7 +586,7 @@ sub powerMap_Set($@) {
|
|||||||
my $value = join( " ", @a ) if (@a);
|
my $value = join( " ", @a ) if (@a);
|
||||||
|
|
||||||
my $assign;
|
my $assign;
|
||||||
my $maps = powerMap_FindPowerMaps();
|
my $maps = powerMap_findPowerMaps();
|
||||||
foreach ( sort keys %{$maps} ) {
|
foreach ( sort keys %{$maps} ) {
|
||||||
$assign .= "," if ($assign);
|
$assign .= "," if ($assign);
|
||||||
$assign .= $_;
|
$assign .= $_;
|
||||||
@@ -602,14 +600,7 @@ sub powerMap_Set($@) {
|
|||||||
|
|
||||||
my $ret;
|
my $ret;
|
||||||
|
|
||||||
if ( $argument eq "devices" ) {
|
if ( $argument eq "assign" ) {
|
||||||
my @devices = devspec2array("$TYPE=.+");
|
|
||||||
return @devices
|
|
||||||
? join( "\n", sort(@devices) )
|
|
||||||
: "no devices with $TYPE attribute defined";
|
|
||||||
}
|
|
||||||
|
|
||||||
elsif ( $argument eq "assign" ) {
|
|
||||||
my @devices = devspec2array($value);
|
my @devices = devspec2array($value);
|
||||||
return "No matching device found." unless (@devices);
|
return "No matching device found." unless (@devices);
|
||||||
|
|
||||||
@@ -659,14 +650,16 @@ sub powerMap_Get($@) {
|
|||||||
. join( " ", values %powerMap_gets )
|
. join( " ", values %powerMap_gets )
|
||||||
unless ( exists( $powerMap_gets{$argument} ) );
|
unless ( exists( $powerMap_gets{$argument} ) );
|
||||||
|
|
||||||
|
my $ret;
|
||||||
|
|
||||||
if ( $argument eq "devices" ) {
|
if ( $argument eq "devices" ) {
|
||||||
my @devices = devspec2array("i:$TYPE=.+");
|
my $pmdevs = powerMap_findPowerMaps(":PM_ENABLED");
|
||||||
return @devices
|
return keys %{$pmdevs}
|
||||||
? join( "\n", sort(@devices) )
|
? join( "\n", sort keys %{$pmdevs} )
|
||||||
: "no devices with $TYPE attribute defined";
|
: "No powerMap enabled devices found.";
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
return $ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub powerMap_Attr(@) {
|
sub powerMap_Attr(@) {
|
||||||
@@ -722,43 +715,21 @@ sub powerMap_Notify($$) {
|
|||||||
foreach my $event ( @{$events} ) {
|
foreach my $event ( @{$events} ) {
|
||||||
next unless ( defined($event) );
|
next unless ( defined($event) );
|
||||||
|
|
||||||
if ( $event =~ m/^(INITIALIZED|SHUTDOWN)$/ ) {
|
# initialize or terminate powerMap for each device
|
||||||
my $event_prefix = $1;
|
if ( $event =~ /^(INITIALIZED|SHUTDOWN)$/ ) {
|
||||||
|
foreach ( keys %{ powerMap_findPowerMaps(":PM_$1") } ) {
|
||||||
# search for devices with user defined
|
|
||||||
# powerMap support to be initialized
|
|
||||||
my @slaves =
|
|
||||||
devspec2array( "a:$TYPE=.+:FILTER=$TYPE" . "_noEnergy!=1" );
|
|
||||||
|
|
||||||
# search for loaded modules with direct
|
|
||||||
# powerMap support to be initialized
|
|
||||||
foreach ( keys %modules ) {
|
|
||||||
if ( defined( $modules{$_}{$TYPE} ) ) {
|
|
||||||
my @instances =
|
|
||||||
devspec2array(
|
|
||||||
"a:TYPE=$_:FILTER=$TYPE" . "_noEnergy!=1" );
|
|
||||||
push @slaves, @instances;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# search for devices with direct
|
|
||||||
# powerMap support to be initialized
|
|
||||||
foreach ( keys %defs ) {
|
|
||||||
push( @slaves, $_ )
|
|
||||||
if ( defined( $defs{$_}{$TYPE} ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
# remove duplicates
|
|
||||||
my %h = map { $_ => 1 } @slaves;
|
|
||||||
@slaves = keys %h;
|
|
||||||
|
|
||||||
# initialize or terminate powerMap for each device
|
|
||||||
foreach (@slaves) {
|
|
||||||
next if ( $_ eq "global" or $_ eq $name );
|
|
||||||
next
|
next
|
||||||
unless ( $event_prefix eq "SHUTDOWN"
|
if ( $_ eq "global"
|
||||||
or powerMap_load( $name, $_ ) );
|
or $_ eq $name
|
||||||
Log3 $name, 4, "$TYPE: $event_prefix for $_";
|
or
|
||||||
|
powerMap_AttrVal( $name, $_, $TYPE . "_noEnergy", 0 ) );
|
||||||
|
|
||||||
|
powerMap_update("$name|$dev") if ( $1 eq "SHUTDOWN" );
|
||||||
|
|
||||||
|
next
|
||||||
|
unless ( $1 eq "SHUTDOWN"
|
||||||
|
|| powerMap_load( $name, $_, undef, 1 ) );
|
||||||
|
Log3 $name, 4, "$TYPE: $1 for $_";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -896,8 +867,8 @@ sub powerMap_AttrVal($$$$) {
|
|||||||
return AttrVal( $p, $TYPE . "_" . $n, AttrVal( $p, $n, $default ) );
|
return AttrVal( $p, $TYPE . "_" . $n, AttrVal( $p, $n, $default ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub powerMap_load($$;$) {
|
sub powerMap_load($$;$$) {
|
||||||
my ( $name, $dev, $unload ) = @_;
|
my ( $name, $dev, $unload, $modSupport ) = @_;
|
||||||
my $dev_hash = $defs{$dev};
|
my $dev_hash = $defs{$dev};
|
||||||
my $TYPE = $defs{$name}{TYPE};
|
my $TYPE = $defs{$name}{TYPE};
|
||||||
|
|
||||||
@@ -954,8 +925,7 @@ sub powerMap_load($$;$) {
|
|||||||
|
|
||||||
unless ($powerMap) {
|
unless ($powerMap) {
|
||||||
return powerMap_update("$name|$dev")
|
return powerMap_update("$name|$dev")
|
||||||
if ( defined( $dev_hash->{$TYPE}{map} )
|
if ($modSupport);
|
||||||
|| defined( $modules{ $dev_hash->{TYPE} }{$TYPE}{map} ) );
|
|
||||||
|
|
||||||
RemoveInternalTimer("$name|$dev");
|
RemoveInternalTimer("$name|$dev");
|
||||||
delete $dev_hash->{pM_update}
|
delete $dev_hash->{pM_update}
|
||||||
@@ -1009,23 +979,42 @@ sub powerMap_unload($$) {
|
|||||||
return powerMap_load( $n, $d, 1 );
|
return powerMap_load( $n, $d, 1 );
|
||||||
}
|
}
|
||||||
|
|
||||||
sub powerMap_FindPowerMaps(;$) {
|
sub powerMap_findPowerMaps(;$) {
|
||||||
my ($device) = @_;
|
my ($device) = @_;
|
||||||
|
|
||||||
my %maps;
|
my %maps;
|
||||||
|
|
||||||
# collect all active definitions
|
# directly return any existing device specific definition
|
||||||
unless ($device) {
|
if ( $device && $device !~ /^:/ ) {
|
||||||
foreach ( devspec2array("i:TYPE=.*:FILTER=powerMap=.+") ) {
|
return {}
|
||||||
|
unless ( defined( $defs{$device} )
|
||||||
|
&& defined( $defs{$device}{TYPE} ) );
|
||||||
|
|
||||||
|
return $defs{$device}{powerMap}{map}
|
||||||
|
if ( $defs{$device}{powerMap}{map}
|
||||||
|
&& ref( $defs{$device}{powerMap}{map} ) eq "HASH"
|
||||||
|
&& keys %{ $defs{$device}{powerMap}{map} } );
|
||||||
|
}
|
||||||
|
|
||||||
|
# get all devices with direct powerMap definitions
|
||||||
|
else {
|
||||||
|
foreach ( devspec2array("i:powerMap=.+") ) {
|
||||||
$maps{$_}{map} = $defs{$_}{powerMap}{map}
|
$maps{$_}{map} = $defs{$_}{powerMap}{map}
|
||||||
if ( $defs{$_}{powerMap}{map}
|
if ( $defs{$_}{powerMap}{map}
|
||||||
&& ref( $defs{$_}{powerMap}{map} ) eq "HASH"
|
&& ref( $defs{$_}{powerMap}{map} ) eq "HASH"
|
||||||
&& keys %{ $defs{$_}{powerMap}{map} } );
|
&& keys %{ $defs{$_}{powerMap}{map} } );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ( $device && $device eq ":PM_INITIALIZED" ) {
|
||||||
|
foreach ( devspec2array("a:powerMap=.+") ) {
|
||||||
|
$maps{$_}{map} = $_ if ( !$maps{$_}{map} );
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# add templates from modules
|
# search templates from modules
|
||||||
foreach my $TYPE ( keys %modules ) {
|
foreach my $TYPE ( $device
|
||||||
|
&& $device !~ /^:/ ? $defs{$device}{TYPE} : keys %modules )
|
||||||
|
{
|
||||||
next unless ( $modules{$TYPE}{powerMap} );
|
next unless ( $modules{$TYPE}{powerMap} );
|
||||||
my $t = $modules{$TYPE}{powerMap};
|
my $t = $modules{$TYPE}{powerMap};
|
||||||
my $modelSupport = 0;
|
my $modelSupport = 0;
|
||||||
@@ -1075,9 +1064,8 @@ sub powerMap_FindPowerMaps(;$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unless ( $device && $device =~ /^MODULE:/ ) {
|
# find possible template for each Fhem device
|
||||||
|
unless ($device) {
|
||||||
# find possible template for each Fhem device
|
|
||||||
foreach my $TYPE ( keys %powerMap_tmpl ) {
|
foreach my $TYPE ( keys %powerMap_tmpl ) {
|
||||||
next unless ( $modules{$TYPE} );
|
next unless ( $modules{$TYPE} );
|
||||||
|
|
||||||
@@ -1130,8 +1118,10 @@ sub powerMap_FindPowerMaps(;$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# filter devices where no reading exists
|
# filter devices where no reading exists
|
||||||
|
unless ( $device && $device eq ":PM_INITIALIZED" ) {
|
||||||
foreach my $d ( keys %maps ) {
|
foreach my $d ( keys %maps ) {
|
||||||
if ( !$maps{$d}{map} || ref( $maps{$d}{map} ) ne "HASH" ) {
|
if ( !$maps{$d}{map} || ref( $maps{$d}{map} ) ne "HASH" ) {
|
||||||
delete $maps{$d};
|
delete $maps{$d};
|
||||||
@@ -1150,26 +1140,18 @@ sub powerMap_FindPowerMaps(;$) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( $device && $device =~ /^MODULE:(.*)$/ ) {
|
return {}
|
||||||
return if ( !$maps{$1} );
|
if ( $device && $device !~ /^:/ && !defined( $maps{$device} ) );
|
||||||
return \$maps{$1};
|
return \$maps{$device} if ( $device && $device !~ /^:/ );
|
||||||
}
|
|
||||||
return if ( $device && !$maps{$device} );
|
|
||||||
return \$maps{$device} if ($device);
|
|
||||||
return \%maps;
|
return \%maps;
|
||||||
}
|
}
|
||||||
|
|
||||||
sub powerMap_power($$$;$) {
|
sub powerMap_power($$$;$) {
|
||||||
my ( $name, $dev, $event, $loop ) = @_;
|
my ( $name, $dev, $event, $loop ) = @_;
|
||||||
my $hash = $defs{$name};
|
my $hash = $defs{$name};
|
||||||
my $TYPE = $hash->{TYPE};
|
my $TYPE = $hash->{TYPE};
|
||||||
my $power = 0;
|
my $power = 0;
|
||||||
my $powerMap =
|
my $powerMap = powerMap_findPowerMaps($dev);
|
||||||
$defs{$dev}{$TYPE}{map} ? $defs{$dev}{$TYPE}{map}
|
|
||||||
: (
|
|
||||||
$defs{$dev}{$TYPE}{map} ? $defs{$dev}{$TYPE}{map}
|
|
||||||
: $modules{ $defs{$dev}{TYPE} }{$TYPE}{map}
|
|
||||||
);
|
|
||||||
|
|
||||||
return unless ( defined($powerMap) and ref($powerMap) eq "HASH" );
|
return unless ( defined($powerMap) and ref($powerMap) eq "HASH" );
|
||||||
|
|
||||||
@@ -1535,7 +1517,7 @@ sub powerMap_update($;$) {
|
|||||||
<br>
|
<br>
|
||||||
In case several power values need to be summarized, the name of other readings may be added after
|
In case several power values need to be summarized, the name of other readings may be added after
|
||||||
number value, separated by comma. The current status of that reading will then be considered for
|
number value, separated by comma. The current status of that reading will then be considered for
|
||||||
the total power calculcation. To consider all readings known to powerMap, just as an *.
|
the total power calculcation. To consider all readings known to powerMap, just as an *.<br>
|
||||||
<br>
|
<br>
|
||||||
Example for FS20 socket:
|
Example for FS20 socket:
|
||||||
<ul>
|
<ul>
|
||||||
@@ -1705,7 +1687,7 @@ sub powerMap_update($;$) {
|
|||||||
Readings direkt hinter dem eigentliche Wert mit einem Komma abgetrennt angegeben werden.
|
Readings direkt hinter dem eigentliche Wert mit einem Komma abgetrennt angegeben werden.
|
||||||
Der aktuelle Status dieses Readings wird dann bei der Berechnung des Gesamtverbrauchs ebenfalls
|
Der aktuelle Status dieses Readings wird dann bei der Berechnung des Gesamtverbrauchs ebenfalls
|
||||||
ber&uumL;cksichtigt. Sollen alle in powerMap bekannten Readings berücksichtigt werden, kann
|
ber&uumL;cksichtigt. Sollen alle in powerMap bekannten Readings berücksichtigt werden, kann
|
||||||
auch einfach ein * angegeben werden.
|
auch einfach ein * angegeben werden.<br>
|
||||||
<br>
|
<br>
|
||||||
Beispiel für einen FS20 Stecker:
|
Beispiel für einen FS20 Stecker:
|
||||||
<ul>
|
<ul>
|
||||||
|
|||||||
Reference in New Issue
Block a user