From 82a2832794f7d65a5b48de014ec0911a78ffdb82 Mon Sep 17 00:00:00 2001 From: jpawlowski Date: Sun, 16 Apr 2017 19:04:18 +0000 Subject: [PATCH] HP1000: replace sum10m readings by max10m; add conditions for temperature and wind git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@14007 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- FHEM/50_HP1000.pm | 629 ++++++++++++++++++++++++++-------------------- 1 file changed, 363 insertions(+), 266 deletions(-) diff --git a/FHEM/50_HP1000.pm b/FHEM/50_HP1000.pm index e9b655008..5d2d39427 100755 --- a/FHEM/50_HP1000.pm +++ b/FHEM/50_HP1000.pm @@ -1,44 +1,18 @@ +############################################################################### # $Id$ -############################################################################## -# -# 50_HP1000.pm -# An FHEM Perl module to receive data from HP1000 weather stations. -# -# Copyright by Julian Pawlowski -# e-mail: julian.pawlowski at gmail.com -# -# This file is part of fhem. -# -# Fhem is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 2 of the License, or -# (at your option) any later version. -# -# Fhem is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with fhem. If not, see . -# -############################################################################## - package main; - use strict; use warnings; -use vars qw(%data); -use HttpUtils; -use utf8; -use Encode qw(encode_utf8 decode_utf8); -use Unit; -use Time::Local; -use List::Util qw(sum); -use Scalar::Util qw(looks_like_number); use Data::Dumper; +use Time::Local; +use Encode qw(encode_utf8 decode_utf8); +use List::Util qw(sum); -my %HP1000_wuMapping = ( +use HttpUtils; +use Unit; + +# module hashes ############################################################### +my %HP1000_pwsMapping = ( # PWS => 'FHEM', @@ -47,10 +21,11 @@ my %HP1000_wuMapping = ( solarradiation => 'solarradiation', windcomp => 'wind_compasspoint', windcomp_avg2m => 'wind_compasspoint_avg2m', + windcomp_avg10m => 'wind_compasspoint_avg10m', winddir => 'wind_direction', winddir_avg2m => 'wind_direction_avg2m', windgustdir => 'wind_gust_direction', - windgustdir_10m => 'wind_gust_direction_sum10m', + windgustdir_10m => 'wind_gust_direction_avg10m', # name translation for Metric standard dewpoint => 'dewpoint', @@ -70,9 +45,9 @@ my %HP1000_wuMapping = ( intemp => 'indoorTemperature', windchill => 'wind_chill', windgust => 'wind_gust', - windgust_10m => 'wind_gust_sum10m', + windgust_10m => 'wind_gust_max10m', windgustmps => 'wind_gust_mps', - windgustmps_10m => 'wind_gust_mps_sum10m', + windgustmps_10m => 'wind_gust_mps_max10m', windspeed => 'wind_speed', windspeed_avg2m => 'wind_speed_avg2m', windspeedmps => 'wind_speed_mps', @@ -82,9 +57,9 @@ my %HP1000_wuMapping = ( barommm => 'pressure_mm', absbarommm => 'pressureAbs_mm', windgustbft => 'wind_gust_bft', - windgustbft_10m => 'wind_gust_bft_sum10m', + windgustbft_10m => 'wind_gust_bft_max10m', windgustkn => 'wind_gust_kn', - windgustkn_10m => 'wind_gust_kn_sum10m', + windgustkn_10m => 'wind_gust_kn_max10m', windspeedbft => 'wind_speed_bft', windspdbft_avg2m => 'wind_speed_bft_avg2m', windspeedkn => 'wind_speed_kn', @@ -108,37 +83,51 @@ my %HP1000_wuMapping = ( indoortempf => 'indoorTemperature_f', windchillf => 'wind_chill_f', windgustfts => 'wind_gust_fts', - windgustfts_10m => 'wind_gust_fts_sum10m', + windgustfts_10m => 'wind_gust_fts_max10m', windgustmph => 'wind_gust_mph', - windgustmph_10m => 'wind_gust_mph_sum10m', + windgustmph_10m => 'wind_gust_mph_max10m', windspeedfts => 'wind_speed_fts', windspdfts_avg2m => 'wind_speed_fts_avg2m', windspeedmph => 'wind_speed_mph', windspdmph_avg2m => 'wind_speed_mph_avg2m', ); -######################### -sub HP1000_addExtension($$$) { - my ( $name, $func, $link ) = @_; +my %HP1000_wuParams = ( + action => 1, + baromin => 1, + clouds => 1, + dailyrainin => 1, + dateutc => 1, + dewptf => 1, + humidity => 1, + ID => 1, + indoorhumidity => 1, + indoortempf => 1, + lowbatt => 1, + monthlyrainin => 1, + PASSWORD => 1, + rainin => 1, + realtime => 1, + rtfreq => 1, + softwaretype => 1, + solarradiation => 1, + tempf => 1, + UV => 1, + weather => 1, + weeklyrainin => 1, + windchillf => 1, + winddir => 1, + winddir_avg2m => 1, + windgustdir => 1, + windgustdir_10m => 1, + windgustmph => 1, + windgustmph_10m => 1, + windspdmph_avg2m => 1, + windspeedmph => 1, + yearlyrainin => 1, +); - my $url = "/$link"; - Log3 $name, 2, "Registering HP1000 $name for URL $url..."; - $data{FWEXT}{$url}{deviceName} = $name; - $data{FWEXT}{$url}{FUNC} = $func; - $data{FWEXT}{$url}{LINK} = $link; -} - -######################### -sub HP1000_removeExtension($) { - my ($link) = @_; - - my $url = "/$link"; - my $name = $data{FWEXT}{$url}{deviceName}; - Log3 $name, 2, "Unregistering HP1000 $name for URL $url..."; - delete $data{FWEXT}{$url}; -} - -################################### +# initialize ################################################################## sub HP1000_Initialize($) { my ($hash) = @_; @@ -158,9 +147,17 @@ sub HP1000_Initialize($) { $hash->{parseParams} = 1; $hash->{AttrList} = -"wu_push:1,0 wu_indoorValues:1,0 wu_id wu_password wu_realtime:1,0 wu_dataValues extSrvPush_Url stateReadingsLang:en,de,at,ch,nl,fr,pl stateReadings stateReadingsFormat:0,1 " +"disable:1,0 disabledForIntervals do_not_notify:1,0 wu_push:1,0 wu_indoorValues:1,0 wu_id wu_password wu_realtime:1,0 wu_dataValues extSrvPush_Url stateReadingsLang:en,de,at,ch,nl,fr,pl stateReadings stateReadingsFormat:0,1 " . $readingFnAttributes; + my @wu; + foreach ( keys %HP1000_wuParams ) { + next unless ( $HP1000_pwsMapping{$_} ); + push @wu, $HP1000_pwsMapping{$_}; + } + + $hash->{AttrList} .= " wu_pushValues:multiple," . join( ",", sort @wu ); + # Unit.pm support $hash->{readingsDesc} = { 'Activity' => { rtype => 'oknok', }, @@ -188,43 +185,57 @@ sub HP1000_Initialize($) { 'indoorHumidityCondition_rgb' => { rtype => 'rgbhex', }, 'indoorTemperature' => { rtype => 'c', formula_symbol => 'Ti', }, 'indoorTemperature_f' => { rtype => 'f', formula_symbol => 'Ti', }, - 'israining' => { rtype => 'yesno', }, - 'luminosity' => { rtype => 'lx', }, - 'pressure' => { rtype => 'hpamb', }, - 'pressureAbs' => { rtype => 'hpamb', }, - 'pressureAbs_in' => { rtype => 'inhg', }, - 'pressureAbs_mm' => { rtype => 'mmhg', }, - 'pressure_in' => { rtype => 'inhg', }, - 'pressure_mm' => { rtype => 'mmhg', }, - 'rain' => { rtype => 'mm', }, - 'rain_day' => { rtype => 'mm', }, - 'rain_day_in' => { rtype => 'in', }, - 'rain_in' => { rtype => 'in', }, - 'rain_month' => { rtype => 'mm', }, - 'rain_month_in' => { rtype => 'in', }, - 'rain_week' => { rtype => 'mm', }, - 'rain_week_in' => { rtype => 'in', }, - 'rain_year' => { rtype => 'mm', }, - 'rain_year_in' => { rtype => 'in', }, - 'solarradiation' => { rtype => 'wpsm', }, - 'temperature' => { rtype => 'c', }, - 'temperature_f' => { rtype => 'f', }, - 'wind_compasspoint' => { rtype => 'compasspoint', }, - 'wind_compasspoint_avg2m' => { rtype => 'compasspoint', }, - 'wind_chill' => { rtype => 'c', formula_symbol => 'Wc', }, - 'wind_chill_f' => { rtype => 'f', formula_symbol => 'Wc', }, + + #'indoorTemperatureCondition' => {}, + 'indoorTemperatureCondition_rgb' => { rtype => 'rgbhex', }, + 'israining' => { rtype => 'yesno', }, + 'luminosity' => { rtype => 'lx', }, + 'pressure' => { rtype => 'hpamb', }, + 'pressureAbs' => { rtype => 'hpamb', }, + 'pressureAbs_in' => { rtype => 'inhg', }, + 'pressureAbs_mm' => { rtype => 'mmhg', }, + 'pressure_in' => { rtype => 'inhg', }, + 'pressure_mm' => { rtype => 'mmhg', }, + 'rain' => { rtype => 'mm', }, + 'rain_day' => { rtype => 'mm', }, + 'rain_day_in' => { rtype => 'in', }, + 'rain_in' => { rtype => 'in', }, + 'rain_month' => { rtype => 'mm', }, + 'rain_month_in' => { rtype => 'in', }, + 'rain_week' => { rtype => 'mm', }, + 'rain_week_in' => { rtype => 'in', }, + 'rain_year' => { rtype => 'mm', }, + 'rain_year_in' => { rtype => 'in', }, + 'solarradiation' => { rtype => 'wpsm', }, + 'temperature' => { rtype => 'c', }, + 'temperature_f' => { rtype => 'f', }, + + #'temperatureCondition' => {}, + 'temperatureCondition_rgb' => { rtype => 'rgbhex', }, + + #'windCondition' => {}, + 'windCondition_rgb' => { rtype => 'rgbhex', }, + + #'windWarning' => {}, + 'wind_compasspoint' => { rtype => 'compasspoint', }, + 'wind_compasspoint_avg2m' => { rtype => 'compasspoint', }, + 'wind_compasspoint_avg10m' => { rtype => 'compasspoint', }, + 'wind_chill' => { rtype => 'c', formula_symbol => 'Wc', }, + 'wind_chill_f' => { rtype => 'f', formula_symbol => 'Wc', }, 'wind_direction' => { rtype => 'compasspoint', formula_symbol => 'Wdir', }, 'wind_direction_avg2m' => { rtype => 'compasspoint', formula_symbol => 'Wdir', }, - 'wind_gust' => { rtype => 'kmph', formula_symbol => 'Wg', }, - 'wind_gust_bft' => { rtype => 'bft', formula_symbol => 'Wg', }, + 'wind_gust' => { rtype => 'kmph', formula_symbol => 'Wg', }, + 'wind_gust_bft' => { rtype => 'bft', formula_symbol => 'Wg', }, + 'wind_gust_direction_avg10m' => + { rtype => 'compasspoint', formula_symbol => 'Wdir', }, 'wind_gust_fts' => { rtype => 'fts', formula_symbol => 'Wg', }, 'wind_gust_kn' => { rtype => 'kn', formula_symbol => 'Wg', }, 'wind_gust_mph' => { rtype => 'mph', formula_symbol => 'Wg', }, - 'wind_gust_mph_sum10m' => { rtype => 'mph', formula_symbol => 'Wg', }, + 'wind_gust_mph_max10m' => { rtype => 'mph', formula_symbol => 'Wg', }, 'wind_gust_mps' => { rtype => 'mps', formula_symbol => 'Wg', }, - 'wind_gust_sum10m' => { rtype => 'kmph', formula_symbol => 'Wg', }, + 'wind_gust_max10m' => { rtype => 'kmph', formula_symbol => 'Wg', }, 'wind_speed' => { rtype => 'kmph', formula_symbol => 'W', }, 'wind_speed_avg2m' => { rtype => 'kmph', formula_symbol => 'W', }, 'wind_speed_bft' => { rtype => 'bft', formula_symbol => 'W', }, @@ -254,53 +265,7 @@ sub HP1000_Initialize($) { }; } -################################### -sub HP1000_Get($$$) { - my ( $hash, $a, $h ) = @_; - my $name = $hash->{NAME}; - my $wu_id = AttrVal( $name, "wu_id", "" ); - - Log3 $name, 5, "HP1000 $name: called function HP1000_Get()"; - - return "Argument is missing" if ( int(@$a) < 1 ); - - my $usage = "Unknown argument " . @$a[1] . ", choose one of"; - $usage .= " createWUforecast" if ( $wu_id ne "" ); - - my $cmd = ''; - my $result; - - # createWUforecast - if ( lc( @$a[1] ) eq "createwuforecast" ) { - return -"Attribute wu_id does not contain a PWS ID to create a Wunderground device" - if ( $wu_id eq "" ); - - my @wudev = devspec2array("TYPE=Wunderground:FILTER=PWS_ID=$wu_id"); - - if ( !@wudev ) { - return "Missing WU API key" if ( !defined( @$a[2] ) ); - Log3 $name, 3, "HP1000 get $name " . @$a[1] . " " . @$a[2]; - - $result = - fhem "define $name" . "_WU Wunderground " . @$a[2] . " $wu_id"; - $result = $name . "_WU created" - if ( !defined($result) ); - } - else { - $result = "Found existing WU device for this PWS ID: $wudev[0]"; - } - } - - # return usage hint - else { - return $usage; - } - - return $result; -} - -################################### +# regular Fn ################################################################## sub HP1000_Define($$$) { my ( $hash, $a, $h ) = @_; my $name = $hash->{NAME}; @@ -369,7 +334,6 @@ sub HP1000_Define($$$) { return undef; } -################################### sub HP1000_Undefine($$$) { my ( $hash, $a, $h ) = @_; my $name = $hash->{NAME}; @@ -386,33 +350,52 @@ sub HP1000_Undefine($$$) { return undef; } -############################################################################################################ -# -# Begin of helper functions -# -############################################################################################################ - -##################################### -sub HP1000_SetAliveState($;$) { - my ( $hash, $alive ) = @_; +sub HP1000_Get($$$) { + my ( $hash, $a, $h ) = @_; my $name = $hash->{NAME}; + my $wu_id = AttrVal( $name, "wu_id", "" ); - Log3 $name, 5, "HP1000 $name: called function HP1000_SetAliveState()"; - RemoveInternalTimer($hash); + Log3 $name, 5, "HP1000 $name: called function HP1000_Get()"; - my $activity = "dead"; - $activity = "alive" if ($alive); + return "Argument is missing" if ( int(@$a) < 1 ); - readingsBeginUpdate($hash); - readingsBulkUpdateIfChanged( $hash, "Activity", $activity ); - readingsEndUpdate( $hash, 1 ); + my $usage = "Unknown argument " . @$a[1] . ", choose one of"; + $usage .= " createWUforecast" if ( $wu_id ne "" ); - InternalTimer( gettimeofday() + 120, "HP1000_SetAliveState", $hash, 0 ); + my $cmd = ''; + my $result; - return; + # createWUforecast + if ( lc( @$a[1] ) eq "createwuforecast" ) { + return +"Attribute wu_id does not contain a PWS ID to create a Wunderground device" + if ( $wu_id eq "" ); + + my @wudev = devspec2array("TYPE=Wunderground:FILTER=PWS_ID=$wu_id"); + + if ( !@wudev ) { + return "Missing WU API key" if ( !defined( @$a[2] ) ); + Log3 $name, 3, "HP1000 get $name " . @$a[1] . " " . @$a[2]; + + $result = + fhem "define $name" . "_WU Wunderground " . @$a[2] . " $wu_id"; + $result = $name . "_WU created" + if ( !defined($result) ); + } + else { + $result = "Found existing WU device for this PWS ID: $wudev[0]"; + } + } + + # return usage hint + else { + return $usage; + } + + return $result; } -################################### +# module Fn #################################################################### sub HP1000_CGI() { my ($request) = @_; @@ -500,6 +483,7 @@ sub HP1000_CGI() { } $hash = $defs{$name}; + my $uptime = time() - $fhem_started; delete $hash->{FORECASTDEV} if ( $hash->{FORECASTDEV} ); my @wudev = devspec2array( @@ -533,7 +517,8 @@ sub HP1000_CGI() { } } - Log3 $name, 5, "HP1000: received data:\n" . Dumper($webArgs); + Log3 $name, 5, + "HP1000: received data (uptime=$uptime):\n" . Dumper($webArgs); # rename wind speed values as those are in m/sec and # we want km/h to be our metric default @@ -563,7 +548,7 @@ sub HP1000_CGI() { if ( defined( $webArgs->{outhumi} ) && !defined( $webArgs->{humidity} ) ); - my %HP1000_wuMappingEquivalent = ( + my %HP1000_pwsMappingEquivalent = ( # Metric => 'Angloamerican', @@ -587,15 +572,15 @@ sub HP1000_CGI() { windspeedmps => 'windspeedmph', ); - my %HP1000_wuMappingEquivalent_rev = - %{ { reverse %HP1000_wuMappingEquivalent } }; + my %HP1000_pwsMappingEquivalent_rev = + %{ { reverse %HP1000_pwsMappingEquivalent } }; # calculate readings for Metric standard from Angloamerican standard # # calculate Celsius based values based on Fahrenheit foreach ( 'dewptf', 'tempf', 'indoortempf', 'windchillf' ) { - my $k = $HP1000_wuMappingEquivalent_rev{$_}; + my $k = $HP1000_pwsMappingEquivalent_rev{$_}; next unless ( $webArgs->{$_} && $k && !defined( $webArgs->{$k} ) ); Log3 $name, 5, "HP1000: Adding calculated value for $k from $_"; @@ -604,7 +589,7 @@ sub HP1000_CGI() { # calculate hPa based values based on inHg foreach ( 'baromin', 'absbaromin' ) { - my $k = $HP1000_wuMappingEquivalent_rev{$_}; + my $k = $HP1000_pwsMappingEquivalent_rev{$_}; next unless ( $webArgs->{$_} && $k && !defined( $webArgs->{$k} ) ); Log3 $name, 5, "HP1000: Adding calculated value for $k from $_"; @@ -617,7 +602,7 @@ sub HP1000_CGI() { 'monthlyrainin', 'yearlyrainin' ) { - my $k = $HP1000_wuMappingEquivalent_rev{$_}; + my $k = $HP1000_pwsMappingEquivalent_rev{$_}; next unless ( $webArgs->{$_} && $k && !defined( $webArgs->{$k} ) ); Log3 $name, 5, "HP1000: Adding calculated value for $k from $_"; @@ -626,7 +611,7 @@ sub HP1000_CGI() { # calculate kph based values based on mph foreach ( 'windgustmph', 'windspeedmph' ) { - my $k = $HP1000_wuMappingEquivalent_rev{$_}; + my $k = $HP1000_pwsMappingEquivalent_rev{$_}; next unless ( $webArgs->{$_} && $k && !defined( $webArgs->{$k} ) ); Log3 $name, 5, "HP1000: Adding calculated value for $k from $_"; @@ -678,7 +663,7 @@ sub HP1000_CGI() { # calculate Fahrenheit based values based on Celsius foreach ( 'dewpoint', 'outtemp', 'intemp', 'windchill' ) { - my $k = $HP1000_wuMappingEquivalent{$_}; + my $k = $HP1000_pwsMappingEquivalent{$_}; next unless ( $webArgs->{$_} && $k && !defined( $webArgs->{$k} ) ); Log3 $name, 5, "HP1000: Adding calculated value for $k from $_"; @@ -687,7 +672,7 @@ sub HP1000_CGI() { # calculate inHg based values based on hPa foreach ( 'relbaro', 'absbaro' ) { - my $k = $HP1000_wuMappingEquivalent{$_}; + my $k = $HP1000_pwsMappingEquivalent{$_}; next unless ( $webArgs->{$_} && $k && !defined( $webArgs->{$k} ) ); Log3 $name, 5, "HP1000: Adding calculated value for $k from $_"; @@ -698,7 +683,7 @@ sub HP1000_CGI() { foreach ( 'rainrate', 'dailyrain', 'weeklyrain', 'monthlyrain', 'yearlyrain' ) { - my $k = $HP1000_wuMappingEquivalent{$_}; + my $k = $HP1000_pwsMappingEquivalent{$_}; next unless ( $webArgs->{$_} && $k && !defined( $webArgs->{$k} ) ); Log3 $name, 5, "HP1000: Adding calculated value for $k from $_"; @@ -707,7 +692,7 @@ sub HP1000_CGI() { # calculate kph based values based on mph foreach ( 'windgustmps', 'windspeedmps' ) { - my $k = $HP1000_wuMappingEquivalent{$_}; + my $k = $HP1000_pwsMappingEquivalent{$_}; next unless ( $webArgs->{$_} && $k && !defined( $webArgs->{$k} ) ); Log3 $name, 5, "HP1000: Adding calculated value for $k from $_"; @@ -755,7 +740,7 @@ sub HP1000_CGI() { || $p eq "ID" || $p eq "PASSWORD" ); - $p = $HP1000_wuMapping{$p} ? $HP1000_wuMapping{$p} : "_" . $p; + $p = $HP1000_pwsMapping{$p} ? $HP1000_pwsMapping{$p} : "_" . $p; readingsBulkUpdate( $hash, $p, $v ); } @@ -816,6 +801,21 @@ sub HP1000_CGI() { ); } + # temperatureCondition + if ( defined( $webArgs->{outtemp} ) ) { + my ( $v, $rgb ) = UConv::c2condition( $webArgs->{outtemp} ); + readingsBulkUpdateIfChanged( $hash, "temperatureCondition", $v ); + readingsBulkUpdateIfChanged( $hash, "temperatureCondition_rgb", $rgb ); + } + + # indoorTemperatureCondition + if ( defined( $webArgs->{intemp} ) ) { + my ( $v, $rgb ) = UConv::c2condition( $webArgs->{intemp}, 1 ); + readingsBulkUpdateIfChanged( $hash, "indoorTemperatureCondition", $v ); + readingsBulkUpdateIfChanged( $hash, "indoorTemperatureCondition_rgb", + $rgb ); + } + # humidityCondition if ( defined( $webArgs->{outhumi} ) ) { my ( $v, $rgb ) = UConv::humidity2condition( $webArgs->{outhumi} ); @@ -825,7 +825,7 @@ sub HP1000_CGI() { # indoorHumidityCondition if ( defined( $webArgs->{inhumi} ) ) { - my ( $v, $rgb ) = UConv::humidity2condition( $webArgs->{inhumi} ); + my ( $v, $rgb ) = UConv::humidity2condition( $webArgs->{inhumi}, 1 ); readingsBulkUpdateIfChanged( $hash, "indoorHumidityCondition", $v ); readingsBulkUpdateIfChanged( $hash, "indoorHumidityCondition_rgb", $rgb ); @@ -1021,46 +1021,63 @@ sub HP1000_CGI() { readingsBulkUpdate( $hash, "wind_gust_fts", $webArgs->{windgustfts} ); } + # averages/wind_direction_avg10m # averages/wind_direction_avg2m if ( defined( $webArgs->{winddir} ) ) { my $v = - round( HP1000_GetAvg( $hash, "winddir", 2 * 60, $webArgs->{winddir} ), + round( HP1000_GetAvg( $hash, "winddir", 600, $webArgs->{winddir} ), 0 ); - if ( $hash->{INTERVAL} > 0 ) { - readingsBulkUpdate( $hash, "wind_direction_avg2m", $v ); - $webArgs->{winddir_avg2m} = $v; + if ( $hash->{INTERVAL} > 0 && $uptime >= 600 ) { + $webArgs->{windgustdir_10m} = $v; + readingsBulkUpdateIfChanged( $hash, + "wind_gust_direction_avg10m", $webArgs->{windgustdir_10m} ); } + + if ( $hash->{INTERVAL} > 0 && $uptime >= 120 ) { + my $v2 = round( HP1000_GetAvg( $hash, "winddir", 120, -1 ), 0 ); + $webArgs->{winddir_avg2m} = $v2; + readingsBulkUpdateIfChanged( $hash, "wind_direction_avg2m", + $webArgs->{winddir_avg2m} ); + } + } + + # averages/wind_compasspoint_avg10m + if ( defined( $webArgs->{windgustdir_10m} ) ) { + $webArgs->{windcomp_avg10m} = + UConv::direction2compasspoint( $webArgs->{windgustdir_10m} ); + readingsBulkUpdateIfChanged( $hash, "wind_compasspoint_avg10m", + $webArgs->{windcomp_avg10m} ); } # averages/wind_compasspoint_avg2m if ( defined( $webArgs->{winddir_avg2m} ) ) { $webArgs->{windcomp_avg2m} = UConv::direction2compasspoint( $webArgs->{winddir_avg2m} ); - readingsBulkUpdate( $hash, "wind_compasspoint_avg2m", + readingsBulkUpdateIfChanged( $hash, "wind_compasspoint_avg2m", $webArgs->{windcomp_avg2m} ); } # averages/wind_speed_avg2m in km/h if ( defined( $webArgs->{windspeed} ) ) { - my $v = - HP1000_GetAvg( $hash, "windspeed", 2 * 60, $webArgs->{windspeed} ); + my $v = HP1000_GetAvg( $hash, "windspeed", 120, $webArgs->{windspeed} ); - if ( $hash->{INTERVAL} > 0 ) { - readingsBulkUpdate( $hash, "wind_speed_avg2m", $v ); + if ( $hash->{INTERVAL} > 0 && $uptime >= 120 ) { $webArgs->{windspeed_avg2m} = $v; + readingsBulkUpdateIfChanged( $hash, "wind_speed_avg2m", + $webArgs->{windspeed_avg2m} ); } } # averages/wind_speed_mph_avg2m in mph if ( defined( $webArgs->{windspeedmph} ) ) { my $v = - HP1000_GetAvg( $hash, "windspeedmph", 2 * 60, - $webArgs->{windspeedmph} ); + HP1000_GetAvg( $hash, "windspeedmph", 120, $webArgs->{windspeedmph} ); - if ( $hash->{INTERVAL} > 0 ) { - readingsBulkUpdate( $hash, "wind_speed_mph_avg2m", $v ); + if ( $hash->{INTERVAL} > 0 && $uptime >= 120 ) { $webArgs->{windspdmph_avg2m} = $v; + readingsBulkUpdateIfChanged( $hash, "wind_speed_mph_avg2m", + $webArgs->{windspdmph_avg2m} ); } } @@ -1068,7 +1085,7 @@ sub HP1000_CGI() { if ( defined( $webArgs->{windspeed_avg2m} ) ) { $webArgs->{windspdbft_avg2m} = UConv::kph2bft( $webArgs->{windspeed_avg2m} ); - readingsBulkUpdate( $hash, "wind_speed_bft_avg2m", + readingsBulkUpdateIfChanged( $hash, "wind_speed_bft_avg2m", $webArgs->{windspdbft_avg2m} ); } @@ -1076,7 +1093,7 @@ sub HP1000_CGI() { if ( defined( $webArgs->{windspeed_avg2m} ) ) { $webArgs->{windspdkn_avg2m} = UConv::kph2kn( $webArgs->{windspeed_avg2m} ); - readingsBulkUpdate( $hash, "wind_speed_kn_avg2m", + readingsBulkUpdateIfChanged( $hash, "wind_speed_kn_avg2m", $webArgs->{windspdkn_avg2m} ); } @@ -1085,30 +1102,36 @@ sub HP1000_CGI() { my $v = UConv::kph2mps( $webArgs->{windspeed_avg2m} ); $webArgs->{windspdmps_avg2m} = ( $v > 0.5 ? round( $v, 1 ) : "0.0" ); - readingsBulkUpdate( $hash, "wind_speed_mps_avg2m", + readingsBulkUpdateIfChanged( $hash, "wind_speed_mps_avg2m", $webArgs->{windspdmps_avg2m} ); } - # averages/wind_gust_sum10m + # maximum/wind_gust_max10m if ( defined( $webArgs->{windgust} ) ) { - my $v = - HP1000_GetSum( $hash, "windgust", 10 * 60, $webArgs->{windgust} ); + my $v = HP1000_GetMax( $hash, "windgust", 600, $webArgs->{windgust} ); - if ( $hash->{INTERVAL} > 0 ) { - readingsBulkUpdate( $hash, "wind_gust_sum10m", $v ); + if ( $hash->{INTERVAL} > 0 && $uptime >= 600 ) { $webArgs->{windgust_10m} = $v; + readingsBulkUpdateIfChanged( $hash, "wind_gust_max10m", + $webArgs->{windgust_10m} ); + + my ( $val, $rgb, $cond, $warn ) = + UConv::kph2bft( $webArgs->{windgust_10m} ); + readingsBulkUpdateIfChanged( $hash, "windCondition", $cond ); + readingsBulkUpdateIfChanged( $hash, "windCondition_rgb", $rgb ); + readingsBulkUpdateIfChanged( $hash, "windWarning", $warn ); } } - # averages/wind_gust_mph_sum10m + # maximum/wind_gust_mph_max10m if ( defined( $webArgs->{windgustmph} ) ) { my $v = - HP1000_GetSum( $hash, "windgustmph", 10 * 60, - $webArgs->{windgustmph} ); + HP1000_GetMax( $hash, "windgustmph", 600, $webArgs->{windgustmph} ); - if ( $hash->{INTERVAL} > 0 ) { - readingsBulkUpdate( $hash, "wind_gust_mph_sum10m", $v ); + if ( $hash->{INTERVAL} > 0 && $uptime >= 600 ) { $webArgs->{windgustmph_10m} = $v; + readingsBulkUpdateIfChanged( $hash, "wind_gust_mph_max10m", + $webArgs->{windgustmph_10m} ); } } @@ -1147,47 +1170,44 @@ sub HP1000_CGI() { return ( "text/plain; charset=utf-8", "success" ); } -################################### -sub HP1000_GetAvg($$$$) { - my ( $hash, $t, $s, $v, $avg ) = @_; - return HP1000_GetSum( $hash, $t, $s, $v, 1 ); +sub HP1000_addExtension($$$) { + my ( $name, $func, $link ) = @_; + + my $url = "/$link"; + Log3 $name, 2, "Registering HP1000 $name for URL $url..."; + $data{FWEXT}{$url}{deviceName} = $name; + $data{FWEXT}{$url}{FUNC} = $func; + $data{FWEXT}{$url}{LINK} = $link; } -sub HP1000_GetSum($$$$;$) { - my ( $hash, $t, $s, $v, $avg ) = @_; +sub HP1000_removeExtension($) { + my ($link) = @_; + + my $url = "/$link"; + my $name = $data{FWEXT}{$url}{deviceName}; + Log3 $name, 2, "Unregistering HP1000 $name for URL $url..."; + delete $data{FWEXT}{$url}; +} + +sub HP1000_SetAliveState($;$) { + my ( $hash, $alive ) = @_; my $name = $hash->{NAME}; - return $v if ( $avg && $hash->{INTERVAL} < 1 ); - return "0" if ( $hash->{INTERVAL} < 1 ); + Log3 $name, 5, "HP1000 $name: called function HP1000_SetAliveState()"; + RemoveInternalTimer($hash); - my $max = round( $s / $hash->{INTERVAL}, 0 ); - $max = "1" if ( $max < 1 ); - my $return; + my $activity = "dead"; + $activity = "alive" if ($alive); - my $v2 = unshift @{ $hash->{helper}{history}{$t} }, $v; - my $v3 = splice @{ $hash->{helper}{history}{$t} }, $max; + readingsBeginUpdate($hash); + readingsBulkUpdateIfChanged( $hash, "Activity", $activity ); + readingsEndUpdate( $hash, 1 ); - Log3 $name, 5, "HP1000 $name: Updated history for $t:" - . Dumper( $hash->{helper}{history}{$t} ); + InternalTimer( gettimeofday() + 120, "HP1000_SetAliveState", $hash, 0 ); - if ($avg) { - $return = round( - sum( @{ $hash->{helper}{history}{$t} } ) / - @{ $hash->{helper}{history}{$t} }, - 1 - ); - - Log3 $name, 5, "HP1000 $name: Average for $t: $return"; - } - else { - $return = round( sum( @{ $hash->{helper}{history}{$t} } ), 1 ); - Log3 $name, 5, "HP1000 $name: Sum for $t: $return"; - } - - return $return; + return; } -################################### sub HP1000_PushSrv($$) { my ( $hash, $webArgs ) = @_; my $name = $hash->{NAME}; @@ -1241,7 +1261,7 @@ m/(https?):\/\/([\w\.]+):?(\d+)?([a-zA-Z0-9\~\!\@\#\$\%\^\&\*\(\)_\-\=\+\\\/\?\. 'User-Agent' => 'FHEM-HP1000/1.0.0', }, sslargs => { - SSL_verify_mode => 0, + SSL_verify_mode => 'SSL_VERIFY_NONE', }, } ); @@ -1249,7 +1269,6 @@ m/(https?):\/\/([\w\.]+):?(\d+)?([a-zA-Z0-9\~\!\@\#\$\%\^\&\*\(\)_\-\=\+\\\/\?\. return; } -################################### sub HP1000_PushWU($$) { # @@ -1265,6 +1284,9 @@ sub HP1000_PushWU($$) { my $wu_realtime = AttrVal( $name, "wu_realtime", undef ); my $wu_indoorValues = AttrVal( $name, "wu_indoorValues", 1 ); my $wu_dataValues = AttrVal( $name, "wu_dataValues", undef ); + my $wu_pushValues = AttrVal( $name, "wu_pushValues", undef ); + my @whitelist = + ( 'action', 'dateutc', 'ID', 'PASSWORD', 'rtfreq', 'softwaretype' ); Log3 $name, 5, "HP1000 $name: called function HP1000_PushWU()"; @@ -1291,34 +1313,51 @@ sub HP1000_PushWU($$) { $webArgs->{realtime} = 1; } - if ($wu_dataValues) { - my %HP1000_wuMapping_rev = %{ { reverse %HP1000_wuMapping } }; + if ( $wu_dataValues || $wu_pushValues ) { + my %HP1000_pwsMapping_rev = %{ { reverse %HP1000_pwsMapping } }; + + if ($wu_dataValues) { + my %dummy; + $wu_dataValues =~ s/\$name/$name/g; + my ( $err, @a ) = ReplaceSetMagic( \%dummy, 0, ($wu_dataValues) ); + if ($err) { + Log3 $name, 3, + "HP1000 $name: error parsing wu_dataValues: $err"; + } + else { + my ( undef, $h ) = parseParams( \@a ); + foreach ( keys %$h ) { + next unless $_ ne ""; + my $n = $_; + if ( $HP1000_pwsMapping_rev{$_} ) { + $n = $HP1000_pwsMapping_rev{$_}; + Log3 $name, 4, + "HP1000 $name: Remapping reading name from $_ to $n"; + } - my %dummy; - $wu_dataValues =~ s/\$name/$name/g; - my ( $err, @a ) = ReplaceSetMagic( \%dummy, 0, ($wu_dataValues) ); - if ($err) { - Log3 $name, 3, "HP1000 $name: error parsing wu_dataValues: $err"; - } - else { - my ( undef, $h ) = parseParams( \@a ); - foreach ( keys %$h ) { - next unless $_ ne ""; - my $n = $_; - if ( $HP1000_wuMapping_rev{$_} ) { - $n = $HP1000_wuMapping_rev{$_}; Log3 $name, 4, - "HP1000 $name: Remapping reading name from $_ to $n"; + "HP1000 $name: Adding new value for WU: $n=$h->{$_}" + unless ( defined( $webArgs->{$n} ) ); + Log3 $name, 4, +"HP1000 $name: Replacing existing value for WU: $n=$h->{$_}" + if ( defined( $webArgs->{$n} ) ); + + $webArgs->{$n} = $h->{$_}; } + } + } - Log3 $name, 4, - "HP1000 $name: Adding new value for WU: $n=$h->{$_}" - unless ( defined( $webArgs->{$n} ) ); - Log3 $name, 4, - "HP1000 $name: Replacing existing value for WU: $n=$h->{$_}" - if ( defined( $webArgs->{$n} ) ); - - $webArgs->{$n} = $h->{$_}; + if ($wu_pushValues) { + foreach ( split( /,/, $wu_pushValues ) ) { + if ( $HP1000_pwsMapping_rev{$_} ) { + my $v = $HP1000_pwsMapping_rev{$_}; + $v = "humidity" if ( $v eq "outhumi" ); + $v = "indoorhumidity" if ( $v eq "inhumi" ); + push @whitelist, $v; + } + else { + push @whitelist, $_; + } } } } @@ -1343,16 +1382,14 @@ sub HP1000_PushWU($$) { $value = urlEncode($value) if ( $key =~ /^(softwaretype|dateutc)$/i ); - if ( !$wu_indoorValues && $key =~ m/^in/i ) { - Log3 $name, 4, "HP1000 $name: excluding indoor value $key=$value"; - next; + if ( ( $wu_indoorValues || $key =~ m/^in/i ) + && ( !$wu_pushValues || grep ( $_ eq $key, @whitelist ) ) ) + { + Log3 $name, 4, "HP1000 $name: pushing data to WU: $key=$value"; + $cmd .= "$key=" . $value . "&"; } - - $cmd .= "$key=" . $value . "&"; } - Log3 $name, 4, "HP1000 $name: pushing data to WU: " . $cmd; - HttpUtils_NonblockingGet( { url => $wu_url . $cmd, @@ -1373,7 +1410,6 @@ sub HP1000_PushWU($$) { return; } -################################### sub HP1000_ReturnSrv($$$) { my ( $param, $err, $data ) = @_; my $hash = $param->{hash}; @@ -1409,7 +1445,6 @@ sub HP1000_ReturnSrv($$$) { return; } -################################### sub HP1000_ReturnWU($$$) { my ( $param, $err, $data ) = @_; my $hash = $param->{hash}; @@ -1447,6 +1482,60 @@ sub HP1000_ReturnWU($$$) { return; } +sub HP1000_GetSum($$$$) { + my ( $hash, $t, $s, $v ) = @_; + return HP1000_GetHistory( $hash, $t, $s, $v ); +} + +sub HP1000_GetAvg($$$$) { + my ( $hash, $t, $s, $v ) = @_; + return HP1000_GetHistory( $hash, $t, $s, $v, 1 ); +} + +sub HP1000_GetMax($$$$) { + my ( $hash, $t, $s, $v ) = @_; + return HP1000_GetHistory( $hash, $t, $s, $v, 2 ); +} + +sub HP1000_GetHistory($$$$;$) { + my ( $hash, $t, $s, $v, $type ) = @_; + my $name = $hash->{NAME}; + + return $v if ( $type && $type == 1 && $hash->{INTERVAL} < 1 ); + return "0" if ( $hash->{INTERVAL} < 1 ); + + my $max = round( $s / $hash->{INTERVAL}, 0 ); + $max = "1" if ( $max < 1 ); + my $return = $v; + + my $v2 = unshift @{ $hash->{helper}{history}{$t} }, $v + unless ( $v < 0 || ( !$type && $v <= 0 ) ); + my $v3 = splice @{ $hash->{helper}{history}{$t} }, $max unless ( $v < 0 ); + + Log3 $name, 5, "HP1000 $name: Updated history for $t:" + . Dumper( $hash->{helper}{history}{$t} ); + + if ( !$type ) { + $return = round( sum( @{ $hash->{helper}{history}{$t} } ), 1 ); + Log3 $name, 5, "HP1000 $name: Sum for $t: $return"; + } + elsif ( $type == 1 ) { + $return = round( + sum( @{ $hash->{helper}{history}{$t} } ) / + @{ $hash->{helper}{history}{$t} }, + 1 + ); + + Log3 $name, 5, "HP1000 $name: Average for $t: $return"; + } + elsif ( $type == 2 ) { + $return = maxNum( 0, @{ $hash->{helper}{history}{$t} } ); + Log3 $name, 5, "HP1000 $name: Max for $t: $return"; + } + + return $return; +} + 1; =pod @@ -1514,6 +1603,10 @@ sub HP1000_ReturnWU($$$) {
  • wu_push
  • Enable or disable to push data forward to Weather Underground (defaults to 0=no) +
  • wu_pushValues
  • + Restrict values to be transferred to Weather Underground, + otherwise all values will be transferred. +
  • wu_realtime
  • Send the data to the WU realtime server instead of using the standard server (defaults to 1=yes) @@ -1582,6 +1675,10 @@ sub HP1000_ReturnWU($$$) {
  • wu_push
  • Pushen der Daten zu Weather Underground aktivieren oder deaktivieren (Standard ist 0=aus) +
  • wu_pushValues
  • + Schränkt die Werte ein, die an Weather Underground übertragen werden. + Andernfalls werden alle Werte übertragen. +
  • wu_realtime
  • Sendet die Daten an den WU Echtzeitserver statt an den Standard Server (Standard ist 1=an)