From 0f0ead4cfe41461dba2ac8f54d9ef5602d457226 Mon Sep 17 00:00:00 2001 From: "klaus.schauer" <> Date: Thu, 26 Sep 2019 15:54:41 +0000 Subject: [PATCH] 98_ModbusElsnerWS: wind observation readings added git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@20252 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- FHEM/98_ModbusElsnerWS.pm | 82 ++++++++++++++++++++++++++++++--------- 1 file changed, 64 insertions(+), 18 deletions(-) diff --git a/FHEM/98_ModbusElsnerWS.pm b/FHEM/98_ModbusElsnerWS.pm index 08aeac83c..86b5fcaa1 100644 --- a/FHEM/98_ModbusElsnerWS.pm +++ b/FHEM/98_ModbusElsnerWS.pm @@ -173,6 +173,20 @@ sub ModbusElsnerWS_Eval($$$) { my $name = $hash->{NAME}; my $ctrl = 1; my ($temperature, $sunSouth, $sunWest, $sunEast, $brightness, $windSpeed, $gps, $isRaining, $date, $time, $sunAzimuth, $sunElevation, $latitude, $longitude) = split(' ', $readingVal); + my ($windAvg2min, $windGust10min, $windGustCurrent, $windPeak10min); + if ($hash->{INTERVAL} =~ m/^1$/) { + $hash->{helper}{wind}{windSpeedNumArrayElements} = ModubusElsnerWS_updateArrayElement($hash, 'windSpeed', $windSpeed, 'wind', 600); + my ($windAvg10min, $windSpeedMin10min, $windSpeedMax10min) = ModubusElsnerWS_SMA($hash, 'windSpeed', $windSpeed, 'windAvg10min', 'windSpeedMax10min', 'windSpeedMin10min', 'wind', 600); + ($windAvg2min, undef, undef) = ModubusElsnerWS_SMA($hash, 'windSpeed', $windSpeed, 'windAvg2min', undef, undef, 'wind', 120); + my ($windAvg20s, $windSpeedMin20s, $windSpeedMax20s) = ModubusElsnerWS_SMA($hash, 'windSpeed', $windSpeed, 'windAvg20s', 'windSpeedMax20s', 'windSpeedMin20s', 'wind', 20); + ($windGustCurrent, undef, undef) = ModubusElsnerWS_SMA($hash, 'windSpeed', $windSpeed, 'windGustCurrent', undef, undef, 'wind', 3); + $windPeak10min = $windSpeedMax10min >= 12.86 ? $windSpeedMax10min : $windAvg2min; + my $windGust20s = $windGustCurrent >= $windSpeedMin20s + 5.144 ? $windGustCurrent : 0; + $windGustCurrent = $windGustCurrent >= $windSpeedMin20s + 5.144 ? $windGustCurrent : $windAvg2min; + $hash->{helper}{wind}{windGustNumArrayElements} = ModubusElsnerWS_updateArrayElement($hash, 'windGust', $windGust20s, 'wind', 600); + my ($windGustAvg10min, $windGustMin10min, $windGustMax10min) = ModubusElsnerWS_SMA($hash, 'windGust', $windGust20s, 'windGustAvg10min', 'windGustMax10min', 'windGustMin10min', 'wind', 600); + $windGust10min = $windGustMax10min >= 5.144 ? $windGustMax10min : $windAvg2min; + } my @sunlight = ($sunSouth, $sunWest, $sunEast); my ($sunMin, $sunMax) = (sort {$a <=> $b} @sunlight)[0,-1]; $sunSouth = $sunSouth == 0 ? $brightness : $sunSouth; @@ -191,6 +205,14 @@ sub ModbusElsnerWS_Eval($$$) { while($windSpeed > $windStrength[$windStrength] && $windStrength <= @windStrength + 1) { $windStrength ++; } + if ($hash->{INTERVAL} =~ m/^1$/ && (!exists($hash->{helper}{timer}{lastUpdate}) || $hash->{helper}{timer}{lastUpdate} < gettimeofday() - 60)) { + # update every 60 sec + readingsBulkUpdateIfChanged($hash, "windAvg2min", sprintf("%0.1f", $windAvg2min)); + readingsBulkUpdateIfChanged($hash, "windGust10min", sprintf("%0.1f", $windGust10min)); + readingsBulkUpdateIfChanged($hash, "windGustCurrent", sprintf("%0.1f", $windGustCurrent)); + readingsBulkUpdateIfChanged($hash, "windPeak10min", sprintf("%0.1f", $windPeak10min)); + $hash->{helper}{timer}{lastUpdate} = gettimeofday(); + } if (exists $hash->{helper}{timer}{heartbeat}) { readingsBulkUpdateIfChanged($hash, "isRaining", $isRaining); readingsBulkUpdateIfChanged($hash, "windStrength", $windStrength); @@ -356,25 +378,42 @@ sub ModbusElsnerWS_Notify(@) { return undef; } -sub ModbusElsnerWS_SMA($$$$) { - # simple moving average (SMA) - my ($hash, $readingName, $readingVal, $averageOrder) = @_; - my $average = exists($hash->{helper}{sma}{$readingName}{average}) ? $hash->{helper}{sma}{$readingName}{average} : $readingVal; - my $numArrayElements = $#{$hash->{helper}{sma}{$readingName}{val}}; - if (defined($numArrayElements) && $numArrayElements >= 0) { - if ($numArrayElements < $averageOrder - 1) { - $average = $average + $readingVal / ($numArrayElements + 1) - - $hash->{helper}{sma}{$readingName}{val}[$numArrayElements] / ($numArrayElements + 1); - } else { - $average = $average + $readingVal / ($numArrayElements + 1) - - pop(@{$hash->{helper}{sma}{$readingName}{val}}) / ($numArrayElements + 1); - } +sub ModubusElsnerWS_updateArrayElement($$$$$) { + # read und update values to array + my ($hash, $readingName, $readingVal, $arrayName, $numArrayElementsMax) = @_; + my $numArrayElements = $#{$hash->{helper}{$arrayName}{$readingName}{val}}; + if (!defined $numArrayElements) { + $numArrayElements = 1; + } elsif ($numArrayElements + 1 >= $numArrayElementsMax) { + $numArrayElements = $numArrayElementsMax; + pop(@{$hash->{helper}{$arrayName}{$readingName}{val}}); } else { - $average = $readingVal; + $numArrayElements ++; } - unshift(@{$hash->{helper}{sma}{$readingName}{val}}, $readingVal); - $hash->{helper}{sma}{$readingName}{average} = $average; - return $average; + unshift(@{$hash->{helper}{$arrayName}{$readingName}{val}}, $readingVal); + return $numArrayElements; +} + +sub ModubusElsnerWS_SMA($$$$$$$$) { + # simple moving average (SMA) + my ($hash, $readingName, $readingVal, $averageName, $valMaxName, $valMinName, $arrayName, $numArrayElementsCalc) = @_; + my $average = exists($hash->{helper}{$arrayName}{$readingName}{average}) ? $hash->{helper}{$arrayName}{$readingName}{average} : $readingVal; + my ($valMin, $valMax) = ($readingVal, $readingVal); + my $numArrayElements = $#{$hash->{helper}{$arrayName}{$readingName}{val}}; + if (!defined $numArrayElements) { + $average = $readingVal; + } else { + $numArrayElements = $numArrayElementsCalc - 1 if ($numArrayElements + 1 >= $numArrayElementsCalc); + $average = $average + $readingVal / ($numArrayElements + 1) + - $hash->{helper}{$arrayName}{$readingName}{val}[$numArrayElements] / ($numArrayElements + 1); + } + if (defined($valMaxName) && defined($valMinName)) { + ($valMin, $valMax) = (sort {$a <=> $b} @{$hash->{helper}{$arrayName}{$readingName}{val}})[0, $numArrayElements]; + $hash->{helper}{$arrayName}{$readingName}{$valMaxName} = $valMax; + $hash->{helper}{$arrayName}{$readingName}{$valMinName} = $valMin; + } + $hash->{helper}{$arrayName}{$readingName}{$averageName} = $average; + return ($average, $valMin, $valMax); } sub ModbusElsnerWS_LWMA($$$$) { @@ -596,6 +635,7 @@ sub ModbusElsnerWS_Delete($$) {