From 59f89fad99cee63cee11cabc2a0ed855ff9c52a5 Mon Sep 17 00:00:00 2001 From: jpawlowski Date: Sun, 22 Jan 2017 14:00:44 +0000 Subject: [PATCH] 98_powerMap: new attribute eventChainWarnOnly git-svn-id: https://svn.fhem.de/fhem/trunk@13186 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- fhem/FHEM/98_powerMap.pm | 142 +++++++++++++++++++++++++-------------- 1 file changed, 90 insertions(+), 52 deletions(-) diff --git a/fhem/FHEM/98_powerMap.pm b/fhem/FHEM/98_powerMap.pm index ed9e5ddda..7529a6000 100644 --- a/fhem/FHEM/98_powerMap.pm +++ b/fhem/FHEM/98_powerMap.pm @@ -47,8 +47,8 @@ sub powerMap_Notify($$); sub powerMap_AttrVal($$$$); sub powerMap_load($$;$$); sub powerMap_unload($$); -sub powerMap_findPowerMaps(;$); -sub powerMap_verifyEventChain($$); +sub powerMap_findPowerMaps($;$); +sub powerMap_verifyEventChain($$$); sub powerMap_power($$$;$); sub powerMap_energy($$;$); sub powerMap_update($;$); @@ -545,7 +545,12 @@ sub powerMap_Initialize($) { $hash->{NotifyFn} = $TYPE . "_Notify"; $hash->{AttrList} = - "disable:1,0 " . $TYPE . "_gridV:230,110 " . $readingFnAttributes; + "disable:1,0 " + . $TYPE + . "_gridV:230,110 " + . $TYPE + . "_eventChainWarnOnly:1,0 " + . $readingFnAttributes; addToAttrList( $TYPE . "_noEnergy:1,0" ); addToAttrList( $TYPE . "_noPower:1,0" ); @@ -604,7 +609,7 @@ sub powerMap_Set($@) { my $value = join( " ", @a ) if (@a); my $assign; - my $maps = powerMap_findPowerMaps(); + my $maps = powerMap_findPowerMaps($name); foreach ( sort keys %{$maps} ) { $assign .= "," if ($assign); $assign .= $_; @@ -671,7 +676,7 @@ sub powerMap_Get($@) { my $ret; if ( $argument eq "devices" ) { - my $pmdevs = powerMap_findPowerMaps(":PM_ENABLED"); + my $pmdevs = powerMap_findPowerMaps( $name, ":PM_ENABLED" ); return keys %{$pmdevs} ? join( "\n", sort keys %{$pmdevs} ) : "No powerMap enabled devices found."; @@ -735,7 +740,8 @@ sub powerMap_Notify($$) { # initialize or terminate powerMap for each device if ( $event =~ /^(INITIALIZED|SHUTDOWN)$/ ) { - foreach ( keys %{ powerMap_findPowerMaps(":PM_$1") } ) { + foreach ( keys %{ powerMap_findPowerMaps( $name, ":PM_$1" ) } ) + { next if ( $_ eq "global" or $_ eq $name @@ -982,6 +988,7 @@ sub powerMap_load($$;$$) { } $dev_hash->{$TYPE}{map} = $map; + powerMap_verifyEventChain( $name, $dev, $map ); return powerMap_update("$name|$dev"); } } @@ -997,22 +1004,25 @@ sub powerMap_unload($$) { return powerMap_load( $n, $d, 1 ); } -sub powerMap_findPowerMaps(;$) { - my ($device) = @_; +sub powerMap_findPowerMaps($;$) { + my ( $name, $dev ) = @_; my %maps; # directly return any existing device specific definition - if ( $device && $device !~ /^:/ ) { + if ( $dev && $dev !~ /^:/ ) { return {} - unless ( defined( $defs{$device} ) - && defined( $defs{$device}{TYPE} ) ); + unless ( defined( $defs{$dev} ) + && defined( $defs{$dev}{TYPE} ) ); - return $defs{$device}{powerMap}{map} - if ( $defs{$device}{powerMap}{map} - && ref( $defs{$device}{powerMap}{map} ) eq "HASH" - && keys %{ $defs{$device}{powerMap}{map} } - && powerMap_verifyEventChain( $device, - $defs{$device}{powerMap}{map} ) ); + return $defs{$dev}{powerMap}{map} + if ( + $defs{$dev}{powerMap}{map} + && ref( $defs{$dev}{powerMap}{map} ) eq "HASH" + && keys %{ $defs{$dev}{powerMap}{map} } + && powerMap_verifyEventChain( + $name, $dev, $defs{$dev}{powerMap}{map} + ) + ); } # get all devices with direct powerMap definitions @@ -1024,16 +1034,18 @@ sub powerMap_findPowerMaps(;$) { && keys %{ $defs{$_}{powerMap}{map} } ); } - if ( $device && $device eq ":PM_INITIALIZED" ) { + # during initialization, also find devices where we + # need to load their custom attribute into the hash + if ( $dev && $dev eq ":PM_INITIALIZED" ) { foreach ( devspec2array("a:powerMap=.+") ) { - $maps{$_}{map} = $_ if ( !$maps{$_}{map} ); + $maps{$_}{map} = {} if ( !$maps{$_}{map} ); } } } # search templates from modules - foreach my $TYPE ( $device - && $device !~ /^:/ ? $defs{$device}{TYPE} : keys %modules ) + foreach + my $TYPE ( $dev && $dev !~ /^:/ ? $defs{$dev}{TYPE} : keys %modules ) { next unless ( $modules{$TYPE}{powerMap} ); my $t = $modules{$TYPE}{powerMap}; @@ -1085,7 +1097,7 @@ sub powerMap_findPowerMaps(;$) { } # find possible template for each Fhem device - unless ($device) { + unless ($dev) { foreach my $TYPE ( keys %powerMap_tmpl ) { next unless ( $modules{$TYPE} ); @@ -1143,7 +1155,7 @@ sub powerMap_findPowerMaps(;$) { foreach my $d ( keys %maps ) { # filter devices where no reading exists - unless ( $device && $device eq ":PM_INITIALIZED" ) { + unless ( $dev && $dev eq ":PM_INITIALIZED" ) { if ( !$maps{$d}{map} || ref( $maps{$d}{map} ) ne "HASH" ) { delete $maps{$d}; next; @@ -1160,18 +1172,20 @@ sub powerMap_findPowerMaps(;$) { delete $maps{$d} unless ($verified); } - powerMap_verifyEventChain( $d, $maps{$d}{map} ); + powerMap_verifyEventChain( $name, $d, $maps{$d}{map} ); } return {} - if ( $device && $device !~ /^:/ && !defined( $maps{$device} ) ); - return \$maps{$device} if ( $device && $device !~ /^:/ ); + if ( $dev && $dev !~ /^:/ && !defined( $maps{$dev} ) ); + return \$maps{$dev} if ( $dev && $dev !~ /^:/ ); return \%maps; } -sub powerMap_verifyEventChain ($$) { - my ( $dev, $map ) = @_; +sub powerMap_verifyEventChain($$$) { + my ( $name, $dev, $map ) = @_; + my $TYPE = $defs{$name}{TYPE}; my %filter; + return 0 unless ( ref($map) eq "HASH" ); my $attrminint = AttrVal( $dev, "event-min-interval", undef ); if ($attrminint) { @@ -1236,8 +1250,9 @@ sub powerMap_verifyEventChain ($$) { && grep( $reading =~ m/^$_$/, @{ $filter{attrtocr} } ) ) { Log3 $dev, 2, - "powerMap $dev: Attribute timestamp-on-change-reading " - . "is not compatible when using powerMap with reading '$reading'"; + "$TYPE $dev: WARNING - Attribute " + . "timestamp-on-change-reading is not compatible " + . "when using $TYPE with reading '$reading'"; } } } @@ -1250,8 +1265,9 @@ sub powerMap_verifyEventChain ($$) { } @{ $filter{attrminint} }; if (@v) { Log3 $dev, 2, - "powerMap $dev: Attribute event-min-interval is not compatible " - . "when using powerMap with reading '$reading'"; + "$TYPE $dev: WARNING - Attribute " + . "event-min-interval is not compatible " + . "when using $TYPE with reading '$reading'"; } # verify aggregator @@ -1262,19 +1278,29 @@ sub powerMap_verifyEventChain ($$) { } @{ $filter{attraggr} }; if (@v2) { Log3 $dev, 2, - "powerMap $dev: Attribute event-aggregator is not compatible " - . "when using powerMap with reading '$reading'"; + "$TYPE $dev: WARNING - Attribute " + . "event-aggregator is not compatible " + . "when using $TYPE with reading '$reading'"; } } if ( $leocr ne "" ) { - Log3 $dev, 2, - "powerMap $dev: Attribute event-on-change-reading adjusted " - . "to fulfill event chain for reading(s) '$leocr'"; - $attreocr .= "," if ($attreocr); - $attreocr .= $leocr; - CommandAttr( undef, "$dev event-on-change-reading $attreocr" ); + if ( powerMap_AttrVal( $name, $dev, "eventChainWarnOnly", 0 ) ) { + Log3 $dev, 2, + "$TYPE $dev: ERROR: Broken event chain - Attributes " + . "event-on-change-reading or event-on-update-reading " + . "need to contain reading(s) '$leocr'"; + } + else { + Log3 $dev, 2, + "$TYPE $dev: NOTE - Attribute " + . "event-on-change-reading adjusted " + . "to fulfill event chain for reading(s) '$leocr'"; + $attreocr .= "," if ($attreocr); + $attreocr .= $leocr; + CommandAttr( undef, "$dev event-on-change-reading $attreocr" ); + } } return 1; @@ -1285,7 +1311,7 @@ sub powerMap_power($$$;$) { my $hash = $defs{$name}; my $TYPE = $hash->{TYPE}; my $power = 0; - my $powerMap = powerMap_findPowerMaps($dev); + my $powerMap = powerMap_findPowerMaps( $name, $dev ); return unless ( defined($powerMap) and ref($powerMap) eq "HASH" ); @@ -1596,6 +1622,13 @@ sub powerMap_update($;$) { disable 1
No readings will be created or calculated by this module.
+
  • + powerMap_eventChainWarnOnly <1>
    + When set, event chain will NOT be repaired automatically if readings + were found to be required for powerMap but their events are currently + suppressed because they are either missing from attributes event-on-change-reading + or event-on-update-reading. Instead, manual intervention is required. +

  • powerMap_interval <seconds>
    Interval in seconds to calculate energy.
    @@ -1651,7 +1684,7 @@ sub powerMap_update($;$) {
    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 - the total power calculcation. To consider all readings known to powerMap, just as an *.
    + total power calculcation. To consider all readings powerMap knows, just add an *.

    Example for FS20 socket: