| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544 |
- # $Id: 50_HP1000.pm 13431 2017-02-18 14:59:51Z loredo $
- ##############################################################################
- #
- # 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 <http://www.gnu.org/licenses/>.
- #
- ##############################################################################
- 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;
- #########################
- 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_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_Initialize($) {
- my ($hash) = @_;
- Log3 $hash, 5, "HP1000_Initialize: Entering";
- if ( !$modules{dewpoint}{LOADED}
- && -f "$attr{global}{modpath}/FHEM/98_dewpoint.pm" )
- {
- my $ret = CommandReload( undef, "98_dewpoint" );
- Log3 undef, 1, $ret if ($ret);
- }
- $hash->{GetFn} = "HP1000_Get";
- $hash->{DefFn} = "HP1000_Define";
- $hash->{UndefFn} = "HP1000_Undefine";
- $hash->{DbLog_splitFn} = "Unit_DbLog_split";
- $hash->{parseParams} = 1;
- $hash->{AttrList} =
- "wu_push:1,0 wu_id wu_password wu_realtime:1,0 extSrvPush_Url stateReadingsLang:en,de,at,ch,nl,fr,pl stateReadings stateReadingsFormat:0,1 "
- . $readingFnAttributes;
- # Unit.pm support
- $hash->{readingsDesc} = {
- 'Activity' => { rtype => 'oknok', },
- 'UV' => { rtype => 'uvi', },
- 'UVR' => { rtype => 'uwpscm', },
- 'UVcondition' => { rtype => 'condition_uvi', },
- 'condition' => { rtype => 'condition_weather', },
- 'daylight' => { rtype => 'yesno', },
- 'dewpoint' => { rtype => 'c', formula_symbol => 'Td', },
- 'dewpoint_f' => { rtype => 'f', formula_symbol => 'Td', },
- 'extsrv_state' => { rtype => 'oknok', },
- 'humidity' => { rtype => 'pct', formula_symbol => 'H', },
- 'humidityAbs' => { rtype => 'c', formula_symbol => 'Tabs', },
- 'humidityAbs_f' => { rtype => 'f', formula_symbol => 'Tabs', },
- 'humidityCondition' => { rtype => 'condition_hum', },
- 'indoorDewpoint' => { rtype => 'c', formula_symbol => 'Tdi', },
- 'indoorDewpoint_f' => { rtype => 'f', formula_symbol => 'Tdi', },
- 'indoorHumidity' => { rtype => 'pct', formula_symbol => 'Hi', },
- 'indoorHumidityAbs' => { rtype => 'c', formula_symbol => 'Tabsi', },
- 'indoorHumidityAbs_f' => { rtype => 'f', formula_symbol => 'Tabsi', },
- 'indoorHumidityCondition' => { rtype => 'condition_hum', },
- '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', },
- '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_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_mps' => { rtype => 'mps', formula_symbol => 'Wg', },
- 'wind_gust_sum10m' => { 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', },
- 'wind_speed_bft_avg2m' => { rtype => 'bft', formula_symbol => 'W', },
- 'wind_speed_kn' => { rtype => 'kn', formula_symbol => 'W', },
- 'wind_speed_kn_avg2m' => { rtype => 'kn', formula_symbol => 'W', },
- 'wind_speed_mph' => { rtype => 'mph', formula_symbol => 'W', },
- 'wind_speed_mph_avg2m' => { rtype => 'mph', formula_symbol => 'W', },
- 'wind_speed_mps' => { rtype => 'mps', formula_symbol => 'W', },
- 'wind_speed_mps_avg2m' => { rtype => 'mps', formula_symbol => 'W', },
- 'wu_state' => { rtype => 'oknok', },
- };
- # 98_powerMap.pm support
- $hash->{powerMap} = {
- rname_E => 'energy',
- rname_P => 'consumption',
- map => {
- Activity => {
- 'dead' => 0,
- 'alive' => 5,
- },
- state => {
- '*' => 'Activity',
- },
- },
- };
- }
- ###################################
- 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;
- }
- ###################################
- sub HP1000_Define($$$) {
- my ( $hash, $a, $h ) = @_;
- my $name = $hash->{NAME};
- return "Usage: define <name> HP1000 [<ID> <PASSWORD>]"
- if ( int(@$a) < 2 );
- $hash->{ID} = @$a[2] if ( defined( @$a[2] ) );
- $hash->{PASSWORD} = @$a[3] if ( defined( @$a[3] ) );
- return
- "Device already defined: "
- . $modules{HP1000}{defptr}{NAME}
- . " (there can only be one instance as per restriction of the weather station itself)"
- if ( defined( $modules{HP1000}{defptr} ) && !defined( $hash->{OLDDEF} ) );
- # check FHEMWEB instance
- if ( $init_done && !defined( $hash->{OLDDEF} ) ) {
- my $FWports;
- foreach ( devspec2array('TYPE=FHEMWEB:FILTER=TEMPORARY!=1') ) {
- $hash->{FW} = $_
- if ( AttrVal( $_, "webname", "fhem" ) eq "weatherstation" );
- push( @{$FWports}, $defs{$_}->{PORT} )
- if ( defined( $defs{$_}->{PORT} ) );
- }
- if ( !defined( $hash->{FW} ) ) {
- $hash->{FW} = "WEBweatherstation";
- my $port = 8084;
- until ( !grep ( /^$port$/, @{$FWports} ) ) {
- $port++;
- }
- if ( !defined( $defs{ $hash->{FW} } ) ) {
- Log3 $name, 3,
- "HP1000 $name: Creating new FHEMWEB instance "
- . $hash->{FW}
- . " with webname 'weatherstation'";
- fhem "define " . $hash->{FW} . " FHEMWEB $port global";
- fhem "attr " . $hash->{FW} . " webname weatherstation";
- }
- }
- $hash->{FW_PORT} = $defs{ $hash->{FW} }{PORT};
- fhem 'attr ' . $name . ' stateReadings temperature humidity';
- fhem 'attr ' . $name . ' stateReadingsFormat 1';
- }
- if ( HP1000_addExtension( $name, "HP1000_CGI", "updateweatherstation" ) ) {
- $hash->{fhem}{infix} = "updateweatherstation";
- }
- else {
- return "Error registering FHEMWEB infix";
- }
- # create global unique device definition
- $modules{HP1000}{defptr} = $hash;
- RemoveInternalTimer($hash);
- InternalTimer( gettimeofday() + 120, "HP1000_SetAliveState", $hash, 0 );
- return undef;
- }
- ###################################
- sub HP1000_Undefine($$$) {
- my ( $hash, $a, $h ) = @_;
- my $name = $hash->{NAME};
- Log3 $name, 5, "HP1000 $name: called function HP1000_Undefine()";
- HP1000_removeExtension( $hash->{fhem}{infix} );
- # release global unique device definition
- delete $modules{HP1000}{defptr};
- RemoveInternalTimer($hash);
- return undef;
- }
- ############################################################################################################
- #
- # Begin of helper functions
- #
- ############################################################################################################
- #####################################
- sub HP1000_SetAliveState($;$) {
- my ( $hash, $alive ) = @_;
- my $name = $hash->{NAME};
- Log3 $name, 5, "HP1000 $name: called function HP1000_SetAliveState()";
- RemoveInternalTimer($hash);
- my $activity = "dead";
- $activity = "alive" if ($alive);
- readingsBeginUpdate($hash);
- readingsBulkUpdateIfChanged( $hash, "Activity", $activity );
- readingsEndUpdate( $hash, 1 );
- InternalTimer( gettimeofday() + 120, "HP1000_SetAliveState", $hash, 0 );
- return;
- }
- ###################################
- sub HP1000_CGI() {
- my ($request) = @_;
- my $hash;
- my $name = "";
- my $link;
- my $URI;
- my $result = "Initialized";
- my $webArgs;
- my $servertype;
- # incorrect FHEMWEB instance used
- if ( AttrVal( $FW_wname, "webname", "fhem" ) ne "weatherstation" ) {
- return ( "text/plain; charset=utf-8",
- "incorrect FHEMWEB instance to receive data" );
- }
- # data received
- elsif ( $request =~ /^\/updateweatherstation\.(\w{3})\?(.+=.+)/ ) {
- $servertype = lc($1);
- $URI = $2;
- # get device name
- $name = $data{FWEXT}{"/updateweatherstation"}{deviceName}
- if ( defined( $data{FWEXT}{"/updateweatherstation"} ) );
- # return error if no such device
- return ( "text/plain; charset=utf-8",
- "No HP1000 device for webhook /updateweatherstation" )
- unless ($name);
- # extract values from URI
- foreach my $pv ( split( "&", $URI ) ) {
- next if ( $pv eq "" );
- $pv =~ s/\+/ /g;
- $pv =~ s/%([\dA-F][\dA-F])/chr(hex($1))/ige;
- my ( $p, $v ) = split( "=", $pv, 2 );
- $webArgs->{$p} = $v ne "" ? Encode::encode_utf8($v) : $v;
- }
- if ( !defined( $webArgs->{softwaretype} )
- || !defined( $webArgs->{dateutc} )
- || !defined( $webArgs->{ID} )
- || !defined( $webArgs->{PASSWORD} )
- || !defined( $webArgs->{action} ) )
- {
- Log3 $name, 5,
- "HP1000: received insufficient data:\n" . Dumper($webArgs);
- return ( "text/plain; charset=utf-8", "Insufficient data" );
- }
- }
- # no data received
- else {
- return ( "text/plain; charset=utf-8", "Missing data" );
- }
- $hash = $defs{$name};
- delete $hash->{FORECASTDEV} if ( $hash->{FORECASTDEV} );
- my @wudev = devspec2array(
- "TYPE=Wunderground:FILTER=PWS_ID=" . AttrVal( $name, "wu_id", "-" ) );
- $hash->{FORECASTDEV} = $wudev[0]
- if ( defined( $wudev[0] ) );
- HP1000_SetAliveState( $hash, 1 );
- $hash->{IP} = $defs{$FW_cname}{PEER};
- $hash->{SERVER_TYPE} = $servertype;
- $hash->{SWVERSION} = $webArgs->{softwaretype};
- $hash->{INTERVAL} = (
- $hash->{SYSTEMTIME_UTC}
- ? time_str2num( $webArgs->{dateutc} ) -
- time_str2num( $hash->{SYSTEMTIME_UTC} )
- : 0
- );
- $hash->{SYSTEMTIME_UTC} = $webArgs->{dateutc};
- $hash->{FW} = "";
- $hash->{FW_PORT} = "";
- foreach ( devspec2array('TYPE=FHEMWEB:FILTER=TEMPORARY!=1') ) {
- if ( AttrVal( $_, "webname", "fhem" ) eq "weatherstation" ) {
- $hash->{FW} = $_;
- $hash->{FW_PORT} = $defs{$_}{PORT};
- last;
- }
- }
- if (
- defined( $hash->{ID} )
- && defined( $hash->{PASSWORD} )
- && ( $hash->{ID} ne $webArgs->{ID}
- || $hash->{PASSWORD} ne $webArgs->{PASSWORD} )
- )
- {
- Log3 $name, 4, "HP1000: received data containing wrong credentials:\n"
- . Dumper($webArgs);
- return ( "text/plain; charset=utf-8", "Wrong credentials" );
- }
- Log3 $name, 5, "HP1000: received data:\n" . Dumper($webArgs);
- # rename wind speed values as those are in m/sec and
- # we want km/h to be our metric default
- if ( defined( $webArgs->{windspeed} ) ) {
- $webArgs->{windspeedmps} = $webArgs->{windspeed};
- delete $webArgs->{windspeed};
- }
- if ( defined( $webArgs->{windgust} ) ) {
- $webArgs->{windgustmps} = $webArgs->{windgust};
- delete $webArgs->{windgust};
- }
- # calculate readings for Metric standard from Angloamerican standard
- #
- # humidity (special case here!)
- $webArgs->{inhumi} = $webArgs->{indoorhumidity}
- if ( defined( $webArgs->{indoorhumidity} )
- && !defined( $webArgs->{inhumi} ) );
- $webArgs->{indoorhumidity} = $webArgs->{inhumi}
- if ( defined( $webArgs->{inhumi} )
- && !defined( $webArgs->{indoorhumidity} ) );
- $webArgs->{outhumi} = $webArgs->{humidity}
- if ( defined( $webArgs->{humidity} )
- && !defined( $webArgs->{outhumi} ) );
- $webArgs->{humidity} = $webArgs->{outhumi}
- if ( defined( $webArgs->{outhumi} )
- && !defined( $webArgs->{humidity} ) );
- # dewpoint in Celsius (convert from dewptf)
- if ( defined( $webArgs->{dewptf} )
- && $webArgs->{dewptf} ne ""
- && !defined( $webArgs->{dewpoint} ) )
- {
- $webArgs->{dewpoint} =
- UConv::f2c( $webArgs->{dewptf} );
- }
- # relbaro in hPa (convert from baromin)
- if ( defined( $webArgs->{baromin} )
- && $webArgs->{baromin} ne ""
- && !defined( $webArgs->{relbaro} ) )
- {
- $webArgs->{relbaro} = UConv::inhg2hpa( $webArgs->{baromin} );
- }
- # absbaro in hPa (convert from absbaromin)
- if ( defined( $webArgs->{absbaromin} )
- && $webArgs->{absbaromin} ne ""
- && !defined( $webArgs->{absbaro} ) )
- {
- $webArgs->{absbaro} =
- UConv::inhg2hpa( $webArgs->{absbaromin} );
- }
- # rainrate in mm/h (convert from rainin)
- if ( defined( $webArgs->{rainin} )
- && $webArgs->{rainin} ne ""
- && !defined( $webArgs->{rainrate} ) )
- {
- $webArgs->{rainrate} = UConv::in2mm( $webArgs->{rainin} );
- }
- # dailyrain in mm (convert from dailyrainin)
- if ( defined( $webArgs->{dailyrainin} )
- && $webArgs->{dailyrainin} ne ""
- && !defined( $webArgs->{dailyrain} ) )
- {
- $webArgs->{dailyrain} =
- UConv::in2mm( $webArgs->{dailyrainin} );
- }
- # weeklyrain in mm (convert from weeklyrainin)
- if ( defined( $webArgs->{weeklyrainin} )
- && $webArgs->{weeklyrainin} ne ""
- && !defined( $webArgs->{weeklyrain} ) )
- {
- $webArgs->{weeklyrain} =
- UConv::in2mm( $webArgs->{weeklyrainin} );
- }
- # monthlyrain in mm (convert from monthlyrainin)
- if ( defined( $webArgs->{monthlyrainin} )
- && $webArgs->{monthlyrainin} ne ""
- && !defined( $webArgs->{monthlyrain} ) )
- {
- $webArgs->{monthlyrain} =
- UConv::in2mm( $webArgs->{monthlyrainin} );
- }
- # yearlyrain in mm (convert from yearlyrainin)
- if ( defined( $webArgs->{yearlyrainin} )
- && $webArgs->{yearlyrainin} ne ""
- && !defined( $webArgs->{yearlyrain} ) )
- {
- $webArgs->{yearlyrain} =
- UConv::in2mm( $webArgs->{yearlyrainin} );
- }
- # outtemp in Celsius (convert from tempf)
- if ( defined( $webArgs->{tempf} )
- && $webArgs->{tempf} ne ""
- && !defined( $webArgs->{outtemp} ) )
- {
- $webArgs->{outtemp} =
- UConv::f2c( $webArgs->{tempf} );
- }
- # intemp in Celsius (convert from indoortempf)
- if ( defined( $webArgs->{indoortempf} )
- && $webArgs->{indoortempf} ne ""
- && !defined( $webArgs->{intemp} ) )
- {
- $webArgs->{intemp} =
- UConv::f2c( $webArgs->{indoortempf} );
- }
- # windchill in Celsius (convert from windchillf)
- if ( defined( $webArgs->{windchillf} )
- && $webArgs->{windchillf} ne ""
- && !defined( $webArgs->{windchill} ) )
- {
- $webArgs->{windchill} =
- UConv::f2c( $webArgs->{windchillf} );
- }
- # windgust in km/h (convert from windgustmph)
- if ( defined( $webArgs->{windgustmph} )
- && $webArgs->{windgustmph} ne ""
- && !defined( $webArgs->{windgust} ) )
- {
- $webArgs->{windgust} =
- UConv::mph2kph( $webArgs->{windgustmph} );
- }
- # windspeed in km/h (convert from windspdmph)
- if ( defined( $webArgs->{windspdmph} )
- && $webArgs->{windspdmph} ne ""
- && !defined( $webArgs->{windspeed} ) )
- {
- $webArgs->{windspeed} =
- UConv::mph2kph( $webArgs->{windspdmph} );
- }
- # calculate readings for Angloamerican standard from Metric standard
- #
- # humidity (special case here!)
- $webArgs->{indoorhumidity} = $webArgs->{inhumi}
- if ( defined( $webArgs->{inhumi} )
- && !defined( $webArgs->{indoorhumidity} ) );
- # dewptf in Fahrenheit (convert from dewpoint)
- if ( defined( $webArgs->{dewpoint} )
- && $webArgs->{dewpoint} ne ""
- && !defined( $webArgs->{dewptf} ) )
- {
- $webArgs->{dewptf} =
- UConv::c2f( $webArgs->{dewpoint} );
- }
- # baromin in inch (convert from relbaro)
- if ( defined( $webArgs->{relbaro} )
- && $webArgs->{relbaro} ne ""
- && !defined( $webArgs->{baromin} ) )
- {
- $webArgs->{baromin} = UConv::hpa2inhg( $webArgs->{relbaro} );
- }
- # absbaromin in inch (convert from absbaro)
- if ( defined( $webArgs->{absbaro} )
- && $webArgs->{absbaro} ne ""
- && !defined( $webArgs->{absbaromin} ) )
- {
- $webArgs->{absbaromin} =
- UConv::hpa2inhg( $webArgs->{absbaro} );
- }
- # rainin in in/h (convert from rainrate)
- if ( defined( $webArgs->{rainrate} )
- && $webArgs->{rainrate} ne ""
- && !defined( $webArgs->{rainin} ) )
- {
- $webArgs->{rainin} = UConv::mm2in( $webArgs->{rainrate} );
- }
- # dailyrainin in inch (convert from dailyrain)
- if ( defined( $webArgs->{dailyrain} )
- && $webArgs->{dailyrain} ne ""
- && !defined( $webArgs->{dailyrainin} ) )
- {
- $webArgs->{dailyrainin} =
- UConv::mm2in( $webArgs->{dailyrain} );
- }
- # weeklyrainin in inch (convert from weeklyrain)
- if ( defined( $webArgs->{weeklyrain} )
- && $webArgs->{weeklyrain} ne ""
- && !defined( $webArgs->{weeklyrainin} ) )
- {
- $webArgs->{weeklyrainin} =
- UConv::mm2in( $webArgs->{weeklyrain} );
- }
- # monthlyrainin in inch (convert from monthlyrain)
- if ( defined( $webArgs->{monthlyrain} )
- && $webArgs->{monthlyrain} ne ""
- && !defined( $webArgs->{monthlyrainin} ) )
- {
- $webArgs->{monthlyrainin} =
- UConv::mm2in( $webArgs->{monthlyrain} );
- }
- # yearlyrainin in inch (convert from yearlyrain)
- if ( defined( $webArgs->{yearlyrain} )
- && $webArgs->{yearlyrain} ne ""
- && !defined( $webArgs->{yearlyrainin} ) )
- {
- $webArgs->{yearlyrainin} =
- UConv::mm2in( $webArgs->{yearlyrain} );
- }
- # tempf in Fahrenheit (convert from outtemp)
- if ( defined( $webArgs->{outtemp} )
- && $webArgs->{outtemp} ne ""
- && !defined( $webArgs->{tempf} ) )
- {
- $webArgs->{tempf} =
- UConv::c2f( $webArgs->{outtemp} );
- }
- # indoortempf in Fahrenheit (convert from intemp)
- if ( defined( $webArgs->{intemp} )
- && $webArgs->{intemp} ne ""
- && !defined( $webArgs->{indoortempf} ) )
- {
- $webArgs->{indoortempf} =
- UConv::c2f( $webArgs->{intemp} );
- }
- # windchillf in Fahrenheit (convert from windchill)
- if ( defined( $webArgs->{windchill} )
- && $webArgs->{windchill} ne ""
- && !defined( $webArgs->{windchillf} ) )
- {
- $webArgs->{windchillf} =
- UConv::c2f( $webArgs->{windchill} );
- }
- # windgustmps in m/s (convert from windgust)
- if ( defined( $webArgs->{windgust} )
- && $webArgs->{windgust} ne ""
- && !defined( $webArgs->{windgustmps} ) )
- {
- $webArgs->{windgustmps} =
- UConv::kph2mps( $webArgs->{windgust} );
- }
- # windgust in km/h (convert from windgustmps,
- # not exactly from angloamerican...)
- if ( defined( $webArgs->{windgustmps} )
- && $webArgs->{windgustmps} ne ""
- && !defined( $webArgs->{windgust} ) )
- {
- $webArgs->{windgust} =
- UConv::mps2kph( $webArgs->{windgustmps} );
- }
- # windgustmph in mph (convert from windgust)
- if ( defined( $webArgs->{windgust} )
- && $webArgs->{windgust} ne ""
- && !defined( $webArgs->{windgustmph} ) )
- {
- $webArgs->{windgustmph} =
- UConv::kph2mph( $webArgs->{windgust} );
- }
- # windspeedmps in m/s (convert from windspeed,
- # not exactly from angloamerican...)
- if ( defined( $webArgs->{windspeed} )
- && $webArgs->{windspeed} ne ""
- && !defined( $webArgs->{windspeedmps} ) )
- {
- $webArgs->{windspeedmps} =
- UConv::kph2mps( $webArgs->{windspeed} );
- }
- # windspeed in km/h (convert from windspeedmps)
- if ( defined( $webArgs->{windspeedmps} )
- && $webArgs->{windspeedmps} ne ""
- && !defined( $webArgs->{windspeed} ) )
- {
- $webArgs->{windspeed} =
- UConv::mps2kph( $webArgs->{windspeedmps} );
- }
- # windspdmph in mph (convert from windspeed)
- if ( defined( $webArgs->{windspeed} )
- && $webArgs->{windspeed} ne ""
- && !defined( $webArgs->{windspdmph} ) )
- {
- $webArgs->{windspdmph} =
- UConv::kph2mph( $webArgs->{windspeed} );
- }
- # write general readings
- #
- readingsBeginUpdate($hash);
- while ( ( my $p, my $v ) = each %$webArgs ) {
- # delete empty values
- if ( $v eq "" ) {
- delete $webArgs->{$p};
- next;
- }
- # ignore those values
- next
- if ( $p eq "dateutc"
- || $p eq "action"
- || $p eq "softwaretype"
- || $p eq "realtime"
- || $p eq "rtfreq"
- || $p eq "humidity"
- || $p eq "indoorhumidity"
- || $p eq "ID"
- || $p eq "PASSWORD" );
- $p = "_" . $p;
- # name translation for general readings
- $p = "humidity" if ( $p eq "_outhumi" );
- $p = "indoorHumidity" if ( $p eq "_inhumi" );
- $p = "luminosity" if ( $p eq "_light" );
- $p = "UVR" if ( $p eq "_UV" );
- $p = "wind_direction" if ( $p eq "_winddir" );
- # name translation for Metric standard
- $p = "dewpoint" if ( $p eq "_dewpoint" );
- $p = "pressure" if ( $p eq "_relbaro" );
- $p = "pressureAbs" if ( $p eq "_absbaro" );
- $p = "rain" if ( $p eq "_rainrate" );
- $p = "rain_day" if ( $p eq "_dailyrain" );
- $p = "rain_week" if ( $p eq "_weeklyrain" );
- $p = "rain_month" if ( $p eq "_monthlyrain" );
- $p = "rain_year" if ( $p eq "_yearlyrain" );
- $p = "temperature" if ( $p eq "_outtemp" );
- $p = "indoorTemperature" if ( $p eq "_intemp" );
- $p = "wind_chill" if ( $p eq "_windchill" );
- $p = "wind_gust" if ( $p eq "_windgust" );
- $p = "wind_gust_mps" if ( $p eq "_windgustmps" );
- $p = "wind_speed" if ( $p eq "_windspeed" );
- $p = "wind_speed_mps" if ( $p eq "_windspeedmps" );
- # name translation for Angloamerican standard
- $p = "dewpoint_f" if ( $p eq "_dewptf" );
- $p = "pressure_in" if ( $p eq "_baromin" );
- $p = "pressureAbs_in" if ( $p eq "_absbaromin" );
- $p = "rain_in" if ( $p eq "_rainin" );
- $p = "rain_day_in" if ( $p eq "_dailyrainin" );
- $p = "rain_week_in" if ( $p eq "_weeklyrainin" );
- $p = "rain_month_in" if ( $p eq "_monthlyrainin" );
- $p = "rain_year_in" if ( $p eq "_yearlyrainin" );
- $p = "temperature_f" if ( $p eq "_tempf" );
- $p = "indoorTemperature_f" if ( $p eq "_indoortempf" );
- $p = "wind_chill_f" if ( $p eq "_windchillf" );
- $p = "wind_gust_mph" if ( $p eq "_windgustmph" );
- $p = "wind_speed_mph" if ( $p eq "_windspdmph" );
- readingsBulkUpdate( $hash, $p, $v );
- }
- # calculate additional readings
- #
- # israining
- my $israining = 0;
- $israining = 1
- if ( defined( $webArgs->{rainrate} ) && $webArgs->{rainrate} > 0 );
- readingsBulkUpdateIfChanged( $hash, "israining", $israining );
- # daylight
- my $daylight = 0;
- $daylight = 1
- if ( defined( $webArgs->{light} ) && $webArgs->{light} > 50 );
- readingsBulkUpdateIfChanged( $hash, "daylight", $daylight );
- # condition
- if ( defined( $webArgs->{light} ) ) {
- my $temp = ( $webArgs->{outtemp} ? $webArgs->{outtemp} : "10" );
- my $hum = ( $webArgs->{outhumi} ? $webArgs->{outhumi} : "50" );
- readingsBulkUpdateIfChanged(
- $hash,
- "condition",
- UConv::values2weathercondition(
- $temp, $hum, $webArgs->{light}, $daylight, $israining
- )
- );
- }
- # humidityCondition
- if ( defined( $webArgs->{outhumi} ) ) {
- readingsBulkUpdateIfChanged( $hash, "humidityCondition",
- UConv::humidity2condition( $webArgs->{outhumi} ) );
- }
- # indoorHumidityCondition
- if ( defined( $webArgs->{inhumi} ) ) {
- readingsBulkUpdateIfChanged( $hash, "indoorHumidityCondition",
- UConv::humidity2condition( $webArgs->{inhumi} ) );
- }
- # UV (convert from uW/cm2)
- if ( defined( $webArgs->{UV} ) ) {
- $webArgs->{UVI} = UConv::uwpscm2uvi( $webArgs->{UV} );
- readingsBulkUpdate( $hash, "UV", $webArgs->{UVI} );
- }
- # UVcondition
- if ( defined( $webArgs->{UVI} ) ) {
- readingsBulkUpdateIfChanged( $hash, "UVcondition",
- UConv::uvi2condition( $webArgs->{UVI} ) );
- }
- # solarradiation in W/m2 (convert from lux)
- if ( defined( $webArgs->{light} ) ) {
- $webArgs->{solarradiation} =
- UConv::lux2wpsm( $webArgs->{light} );
- readingsBulkUpdate( $hash, "solarradiation",
- $webArgs->{solarradiation} );
- }
- # pressure_mm in mmHg (convert from hpa)
- if ( defined( $webArgs->{relbaro} ) ) {
- $webArgs->{barommm} = UConv::hpa2mmhg( $webArgs->{relbaro} );
- readingsBulkUpdate( $hash, "pressure_mm", $webArgs->{barommm} );
- }
- # pressureAbs_mm in mmHg (convert from hpa)
- if ( defined( $webArgs->{absbaro} ) ) {
- $webArgs->{absbarommm} =
- UConv::hpa2mmhg( $webArgs->{absbaro} );
- readingsBulkUpdate( $hash, "pressureAbs_mm", $webArgs->{absbarommm} );
- }
- # indoorDewpoint in Celsius
- if ( defined( $webArgs->{intemp} )
- && defined( $webArgs->{inhumi} )
- && exists &dewpoint_dewpoint )
- {
- my $h = (
- $webArgs->{inhumi} > 110
- ? 110
- : ( $webArgs->{inhumi} <= 0 ? 0.01 : $webArgs->{inhumi} )
- );
- $webArgs->{indewpoint} =
- round( dewpoint_dewpoint( $webArgs->{intemp}, $h ), 1 );
- readingsBulkUpdate( $hash, "indoorDewpoint", $webArgs->{indewpoint} );
- }
- # indoorDewpoint in Fahrenheit
- if ( defined( $webArgs->{indoortempf} )
- && defined( $webArgs->{indoorhumidity} )
- && exists &dewpoint_dewpoint )
- {
- my $h = (
- $webArgs->{indoorhumidity} > 110 ? 110
- : (
- $webArgs->{indoorhumidity} <= 0 ? 0.01
- : $webArgs->{indoorhumidity}
- )
- );
- $webArgs->{indoordewpointf} =
- round( dewpoint_dewpoint( $webArgs->{indoortempf}, $h ), 1 );
- readingsBulkUpdate( $hash, "indoorDewpoint_f",
- $webArgs->{indoordewpointf} );
- }
- # humidityAbs
- if ( defined( $webArgs->{outtemp} )
- && defined( $webArgs->{outhumi} )
- && looks_like_number( $webArgs->{outtemp} )
- && looks_like_number( $webArgs->{outhumi} )
- && exists &dewpoint_absFeuchte )
- {
- my $h = (
- $webArgs->{outhumi} > 110
- ? 110
- : ( $webArgs->{outhumi} <= 0 ? 0.01 : $webArgs->{outhumi} )
- );
- $webArgs->{outhumiabs} =
- round( dewpoint_absFeuchte( $webArgs->{outtemp}, $h ), 1 );
- readingsBulkUpdate( $hash, "humidityAbs", $webArgs->{outhumiabs} );
- }
- # humidityAbs_f
- if ( defined( $webArgs->{tempf} )
- && defined( $webArgs->{outhumi} )
- && looks_like_number( $webArgs->{tempf} )
- && looks_like_number( $webArgs->{outhumi} )
- && exists &dewpoint_absFeuchte )
- {
- my $h = (
- $webArgs->{outhumi} > 110
- ? 110
- : ( $webArgs->{outhumi} <= 0 ? 0.01 : $webArgs->{outhumi} )
- );
- $webArgs->{outhumiabsf} =
- round( dewpoint_absFeuchte( $webArgs->{tempf}, $h ), 1 );
- readingsBulkUpdate( $hash, "humidityAbs_f", $webArgs->{outhumiabsf} );
- }
- # indoorHumidityAbs
- if ( defined( $webArgs->{intemp} )
- && defined( $webArgs->{inhumi} )
- && looks_like_number( $webArgs->{intemp} )
- && looks_like_number( $webArgs->{inhumi} )
- && exists &dewpoint_absFeuchte )
- {
- my $h = (
- $webArgs->{inhumi} > 110
- ? 110
- : ( $webArgs->{inhumi} <= 0 ? 0.01 : $webArgs->{inhumi} )
- );
- $webArgs->{inhumiabs} =
- round( dewpoint_absFeuchte( $webArgs->{intemp}, $h ), 1 );
- readingsBulkUpdate( $hash, "indoorHumidityAbs", $webArgs->{inhumiabs} );
- }
- # indoorHumidityAbs_f
- if ( defined( $webArgs->{indoortempf} )
- && defined( $webArgs->{indoorhumidity} )
- && looks_like_number( $webArgs->{indoortempf} )
- && looks_like_number( $webArgs->{indoorhumidity} )
- && exists &dewpoint_absFeuchte )
- {
- my $h = (
- $webArgs->{indoorhumidity} > 110 ? 110
- : (
- $webArgs->{indoorhumidity} <= 0 ? 0.01
- : $webArgs->{indoorhumidity}
- )
- );
- $webArgs->{indoorhumidityabsf} =
- round( dewpoint_absFeuchte( $webArgs->{indoortempf}, $h ), 1 );
- readingsBulkUpdate( $hash, "indoorHumidityAbs_f",
- $webArgs->{indoorhumidityabsf} );
- }
- # wind_compasspoint
- if ( defined( $webArgs->{winddir} ) ) {
- $webArgs->{windcompasspoint} =
- UConv::direction2compasspoint( $webArgs->{winddir} );
- readingsBulkUpdate( $hash, "wind_compasspoint",
- $webArgs->{windcompasspoint} );
- }
- # wind_speed_bft in Beaufort (convert from km/h)
- if ( defined( $webArgs->{windspeed} ) ) {
- $webArgs->{windspeedbft} =
- UConv::kph2bft( $webArgs->{windspeed} );
- readingsBulkUpdate( $hash, "wind_speed_bft", $webArgs->{windspeedbft} );
- }
- # wind_speed_kn in kn (convert from km/h)
- if ( defined( $webArgs->{windspeed} ) ) {
- my $v = UConv::kph2kn( $webArgs->{windspeed} );
- $webArgs->{windspeedkn} = ( $v > 0.5 ? round( $v, 1 ) : "0.0" );
- readingsBulkUpdate( $hash, "wind_speed_kn", $webArgs->{windspeedkn} );
- }
- # wind_speed_fts in ft/s (convert from mph)
- if ( defined( $webArgs->{windspeedmph} ) ) {
- my $v = UConv::mph2fts( $webArgs->{windspeedmph} );
- $webArgs->{windspeedfts} = ( $v > 0.5 ? round( $v, 1 ) : "0.0" );
- readingsBulkUpdate( $hash, "wind_speed_fts", $webArgs->{windspeedfts} );
- }
- # wind_gust_bft in Beaufort (convert from km/h)
- if ( defined( $webArgs->{windgust} ) ) {
- $webArgs->{windgustbft} =
- UConv::kph2bft( $webArgs->{windgust} );
- readingsBulkUpdate( $hash, "wind_gust_bft", $webArgs->{windgustbft} );
- }
- # wind_gust_kn in m/s (convert from km/h)
- if ( defined( $webArgs->{windgust} ) ) {
- my $v = UConv::kph2kn( $webArgs->{windgust} );
- $webArgs->{windgustkn} = ( $v > 0.5 ? round( $v, 1 ) : "0.0" );
- readingsBulkUpdate( $hash, "wind_gust_kn", $webArgs->{windgustkn} );
- }
- # wind_gust_fts ft/s (convert from mph)
- if ( defined( $webArgs->{windgustmph} ) ) {
- my $v = UConv::mph2fts( $webArgs->{windgustmph} );
- $webArgs->{windgustfts} = ( $v > 0.5 ? round( $v, 1 ) : "0.0" );
- readingsBulkUpdate( $hash, "wind_gust_fts", $webArgs->{windgustfts} );
- }
- # averages/wind_direction_avg2m
- if ( defined( $webArgs->{winddir} ) ) {
- my $v = sprintf( '%0.0f',
- HP1000_GetAvg( $hash, "winddir", 2 * 60, $webArgs->{winddir} ) );
- if ( $hash->{INTERVAL} > 0 ) {
- readingsBulkUpdate( $hash, "wind_direction_avg2m", $v );
- $webArgs->{winddir_avg2m} = $v;
- }
- }
- # averages/wind_compasspoint_avg2m
- if ( defined( $webArgs->{winddir_avg2m} ) ) {
- $webArgs->{windcompasspoint_avg2m} =
- UConv::direction2compasspoint( $webArgs->{winddir_avg2m} );
- readingsBulkUpdate( $hash, "wind_compasspoint_avg2m",
- $webArgs->{windcompasspoint_avg2m} );
- }
- # averages/wind_speed_avg2m in km/h
- if ( defined( $webArgs->{windspeed} ) ) {
- my $v =
- HP1000_GetAvg( $hash, "windspeed", 2 * 60, $webArgs->{windspeed} );
- if ( $hash->{INTERVAL} > 0 ) {
- readingsBulkUpdate( $hash, "wind_speed_avg2m", $v );
- $webArgs->{windspeed_avg2m} = $v;
- }
- }
- # averages/wind_speed_mph_avg2m in mph
- if ( defined( $webArgs->{windspdmph} ) ) {
- my $v =
- HP1000_GetAvg( $hash, "windspdmph", 2 * 60, $webArgs->{windspdmph} );
- if ( $hash->{INTERVAL} > 0 ) {
- readingsBulkUpdate( $hash, "wind_speed_mph_avg2m", $v );
- $webArgs->{windspdmph_avg2m} = $v;
- }
- }
- # averages/wind_speed_bft_avg2m in Beaufort (convert from km/h)
- if ( defined( $webArgs->{windspeed_avg2m} ) ) {
- $webArgs->{windspeedbft_avg2m} =
- UConv::kph2bft( $webArgs->{windspeed_avg2m} );
- readingsBulkUpdate( $hash, "wind_speed_bft_avg2m",
- $webArgs->{windspeedbft_avg2m} );
- }
- # averages/wind_speed_kn_avg2m in Kn (convert from km/h)
- if ( defined( $webArgs->{windspeed_avg2m} ) ) {
- $webArgs->{windspeedkn_avg2m} =
- UConv::kph2kn( $webArgs->{windspeed_avg2m} );
- readingsBulkUpdate( $hash, "wind_speed_kn_avg2m",
- $webArgs->{windspeedkn_avg2m} );
- }
- # averages/wind_speed_mps_avg2m in m/s
- if ( defined( $webArgs->{windspeed_avg2m} ) ) {
- my $v = UConv::kph2mps( $webArgs->{windspeed_avg2m} );
- $webArgs->{windspeedmps_avg2m} =
- ( $v > 0.5 ? round( $v, 1 ) : "0.0" );
- readingsBulkUpdate( $hash, "wind_speed_mps_avg2m",
- $webArgs->{windspeedmps_avg2m} );
- }
- # averages/wind_gust_sum10m
- if ( defined( $webArgs->{windgust} ) ) {
- my $v =
- HP1000_GetSum( $hash, "windgust", 10 * 60, $webArgs->{windgust} );
- if ( $hash->{INTERVAL} > 0 ) {
- readingsBulkUpdate( $hash, "wind_gust_sum10m", $v );
- $webArgs->{windgust_10m} = $v;
- }
- }
- # averages/wind_gust_mph_sum10m
- if ( defined( $webArgs->{windgustmph} ) ) {
- my $v =
- HP1000_GetSum( $hash, "windgustmph", 10 * 60,
- $webArgs->{windgustmph} );
- if ( $hash->{INTERVAL} > 0 ) {
- readingsBulkUpdate( $hash, "wind_gust_mph_sum10m", $v );
- $webArgs->{windgustmph_10m} = $v;
- }
- }
- # from WU API - can we somehow calculate these as well?
- # weather - [text] -- metar style (+RA)
- # clouds - [text] -- SKC, FEW, SCT, BKN, OVC
- # soiltempf - [F soil temperature]
- # soilmoisture - [%]
- # leafwetness - [%]
- # visibility - [nm visibility]
- # condition_forecast (based on pressure trend)
- # dayNight
- # soilTemperature
- # brightness in % ??
- # state
- my $stateReadings = AttrVal( $name, "stateReadings", "" );
- my $stateReadingsLang = AttrVal( $name, "stateReadingsLang", "en" );
- my $stateReadingsFormat = AttrVal( $name, "stateReadingsFormat", "0" );
- # $result =
- # makeSTATE( $name, $stateReadings,
- # $stateReadingsLang, $stateReadingsFormat );
- $result = makeSTATE( $name, $stateReadings, $stateReadingsFormat );
- readingsBulkUpdate( $hash, "state", $result );
- readingsEndUpdate( $hash, 1 );
- HP1000_PushWU( $hash, $webArgs )
- if AttrVal( $name, "wu_push", 0 ) eq "1";
- HP1000_PushSrv( $hash, $webArgs )
- if AttrVal( $name, "extSrvPush_Url", undef );
- 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_GetSum($$$$;$) {
- my ( $hash, $t, $s, $v, $avg ) = @_;
- my $name = $hash->{NAME};
- return $v if ( $avg && $hash->{INTERVAL} < 1 );
- return "0" if ( $hash->{INTERVAL} < 1 );
- my $max = sprintf( "%.0f", $s / $hash->{INTERVAL} );
- $max = "1" if ( $max < 1 );
- my $return;
- my $v2 = unshift @{ $hash->{helper}{history}{$t} }, $v;
- my $v3 = splice @{ $hash->{helper}{history}{$t} }, $max;
- Log3 $name, 5, "HP1000 $name: Updated history for $t:"
- . Dumper( $hash->{helper}{history}{$t} );
- if ($avg) {
- $return = sprintf( "%.1f",
- sum( @{ $hash->{helper}{history}{$t} } ) /
- @{ $hash->{helper}{history}{$t} } );
- Log3 $name, 5, "HP1000 $name: Average for $t: $return";
- }
- else {
- $return = sprintf( "%.1f", sum( @{ $hash->{helper}{history}{$t} } ) );
- Log3 $name, 5, "HP1000 $name: Sum for $t: $return";
- }
- return $return;
- }
- ###################################
- sub HP1000_PushSrv($$) {
- my ( $hash, $webArgs ) = @_;
- my $name = $hash->{NAME};
- my $timeout = AttrVal( $name, "timeout", 7 );
- my $http_noshutdown = AttrVal( $name, "http-noshutdown", "1" );
- my $srv_url = AttrVal( $name, "extSrvPush_Url", "" );
- my $cmd = "";
- Log3 $name, 5, "HP1000 $name: called function HP1000_PushSrv()";
- if ( $srv_url !~
- /(https?):\/\/([\w\.]+):?(\d+)?([a-zA-Z0-9\~\!\@\#\$\%\^\&\*\(\)_\-\=\+\\\/\?\.\:\;\'\,]*)?/
- )
- {
- return;
- }
- elsif ( $4 !~ /\?/ ) {
- $cmd = "?";
- }
- else {
- $cmd = "&";
- }
- $webArgs->{PASSWORD} = "";
- while ( my ( $key, $value ) = each %{$webArgs} ) {
- if ( $key eq "softwaretype" || $key eq "dateutc" ) {
- $value = urlEncode($value);
- }
- $cmd .= "$key=" . $value . "&";
- }
- Log3 $name, 4,
- "HP1000 $name: pushing data to external Server: $srv_url$cmd";
- HttpUtils_NonblockingGet(
- {
- url => $srv_url . $cmd,
- timeout => $timeout,
- noshutdown => $http_noshutdown,
- data => undef,
- hash => $hash,
- httpversion => "1.1",
- callback => \&HP1000_ReturnSrv,
- }
- );
- return;
- }
- ###################################
- sub HP1000_PushWU($$) {
- #
- # See: http://wiki.wunderground.com/index.php/PWS_-_Upload_Protocol
- #
- my ( $hash, $webArgs ) = @_;
- my $name = $hash->{NAME};
- my $timeout = AttrVal( $name, "timeout", 7 );
- my $http_noshutdown = AttrVal( $name, "http-noshutdown", "1" );
- my $wu_user = AttrVal( $name, "wu_id", "" );
- my $wu_pass = AttrVal( $name, "wu_password", "" );
- Log3 $name, 5, "HP1000 $name: called function HP1000_PushWU()";
- if ( $wu_user eq "" && $wu_pass eq "" ) {
- Log3 $name, 4,
- "HP1000 $name: missing attributes for Weather Underground transfer: wu_user and wu_password";
- my $return = "error: missing attributes wu_user and wu_password";
- readingsBeginUpdate($hash);
- readingsBulkUpdateIfChanged( $hash, "wu_state", $return );
- readingsEndUpdate( $hash, 1 );
- return;
- }
- if ( AttrVal( $name, "wu_realtime", "1" ) eq "0" ) {
- Log3 $name, 5, "HP1000 $name: Explicitly turning off realtime";
- delete $webArgs->{realtime};
- delete $webArgs->{rtfreq};
- }
- elsif ( AttrVal( $name, "wu_realtime", "0" ) eq "1" ) {
- Log3 $name, 5, "HP1000 $name: Explicitly turning on realtime";
- $webArgs->{realtime} = 1;
- }
- $webArgs->{rtfreq} = 5
- if ( defined( $webArgs->{realtime} )
- && !defined( $webArgs->{rtfreq} ) );
- my $wu_url = (
- defined( $webArgs->{realtime} )
- && $webArgs->{realtime} eq "1"
- ? "https://rtupdate.wunderground.com/weatherstation/updateweatherstation.php?"
- : "https://weatherstation.wunderground.com/weatherstation/updateweatherstation.php?"
- );
- $webArgs->{ID} = $wu_user;
- $webArgs->{PASSWORD} = $wu_pass;
- my $cmd;
- while ( my ( $key, $value ) = each %{$webArgs} ) {
- if ( $key eq "softwaretype" || $key eq "dateutc" ) {
- $value = urlEncode($value);
- }
- elsif ( $key eq "UVI" ) {
- $key = "UV";
- $value = $value;
- }
- elsif ( $key eq "UV" ) {
- next;
- }
- $cmd .= "$key=" . $value . "&";
- }
- Log3 $name, 4, "HP1000 $name: pushing data to WU: " . $cmd;
- HttpUtils_NonblockingGet(
- {
- url => $wu_url . $cmd,
- timeout => $timeout,
- noshutdown => $http_noshutdown,
- data => undef,
- hash => $hash,
- callback => \&HP1000_ReturnWU,
- }
- );
- return;
- }
- ###################################
- sub HP1000_ReturnSrv($$$) {
- my ( $param, $err, $data ) = @_;
- my $hash = $param->{hash};
- my $name = $hash->{NAME};
- # device not reachable
- if ($err) {
- my $return = "error: connection timeout";
- Log3 $name, 4, "HP1000 $name: EXTSRV HTTP " . $return;
- readingsBeginUpdate($hash);
- readingsBulkUpdateIfChanged( $hash, "extsrv_state", $return );
- readingsEndUpdate( $hash, 1 );
- }
- # data received
- elsif ($data) {
- my $logprio = 5;
- my $return = "ok";
- if ( $param->{code} ne "200" ) {
- $logprio = 4;
- $return = "error " . $param->{code} . ": $data";
- }
- Log3 $name, $logprio,
- "HP1000 $name: EXTSRV HTTP return: " . $param->{code} . " - $data";
- readingsBeginUpdate($hash);
- readingsBulkUpdateIfChanged( $hash, "extsrv_state", $return );
- readingsEndUpdate( $hash, 1 );
- }
- return;
- }
- ###################################
- sub HP1000_ReturnWU($$$) {
- my ( $param, $err, $data ) = @_;
- my $hash = $param->{hash};
- my $name = $hash->{NAME};
- # device not reachable
- if ($err) {
- my $return = "error: connection timeout";
- Log3 $name, 4, "HP1000 $name: WU HTTP " . $return;
- readingsBeginUpdate($hash);
- readingsBulkUpdateIfChanged( $hash, "wu_state", $return );
- readingsEndUpdate( $hash, 1 );
- }
- # data received
- elsif ($data) {
- my $logprio = 5;
- my $return = "ok";
- if ( $data !~ m/^success.*/ ) {
- $logprio = 4;
- $return = "error";
- $return .= " " . $param->{code} if ( $param->{code} ne "200" );
- $return .= ": $data";
- }
- Log3 $name, $logprio,
- "HP1000 $name: WU HTTP return: " . $param->{code} . " - $data";
- readingsBeginUpdate($hash);
- readingsBulkUpdateIfChanged( $hash, "wu_state", $return );
- readingsEndUpdate( $hash, 1 );
- }
- return;
- }
- 1;
- =pod
- =item device
- =item summary support for Wifi-based weather stations HP1000 and WH2600
- =item summary_DE Unterstützung für die WLAN-basierte HP1000 oder WH2600 Wetterstationen
- =begin html
- <p>
- <a name="HP1000" id="HP1000"></a>
- </p>
- <h3>
- HP1000
- </h3>
- <ul>
- <div>
- <a name="HP1000define" id="HP10000define"></a> <b>Define</b>
- <div>
- <ul>
- <code>define <WeatherStation> HP1000 [<ID> <PASSWORD>]</code><br>
- <br>
- Provides webhook receiver for Wifi-based weather station HP1000 and WH2600 of Fine Offset Electronics (e.g. also known as Ambient Weather WS-1001-WIFI).<br>
- There needs to be a dedicated FHEMWEB instance with attribute webname set to "weatherstation".<br>
- No other name will work as it's hardcoded in the HP1000/WH2600 device itself!<br>
- If necessary, this module will create a matching FHEMWEB instance named WEBweatherstation during initial definition.<br>
- <br>
- As the URI has a fixed coding as well there can only be one single HP1000/WH2600 station per FHEM installation.<br>
- <br>
- Example:<br>
- <div>
- <code># unprotected instance where ID and PASSWORD will be ignored<br>
- define WeatherStation HP1000<br>
- <br>
- # protected instance: Weather Station needs to be configured<br>
- # to send this ID and PASSWORD for data to be accepted<br>
- define WeatherStation HP1000 MyHouse SecretPassword</code>
- </div><br>
- IMPORTANT: In your HP1000/WH2600 hardware device, make sure you use a DNS name as most revisions cannot handle IP addresses correctly.<br>
- </ul>
- </div><br>
- </div>
- <br>
- <a name="HP1000Attr" id="HP10000Attr"></a> <b>Attributes</b>
- <div>
- <ul>
- <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
- <br>
- <a name="wu_id"></a><li><b>wu_id</b></li>
- Weather Underground (Wunderground) station ID
- <a name="wu_password"></a><li><b>wu_password</b></li>
- Weather Underground (Wunderground) password
- <a name="wu_push"></a><li><b>wu_push</b></li>
- Enable or disable to push data forward to Weather Underground (defaults to 0=no)
- <a name="wu_realtime"></a><li><b>wu_realtime</b></li>
- Send the data to the WU realtime server instead of using the standard server (defaults to 1=yes)
- </ul>
- </div>
- </ul>
- =end html
- =begin html_DE
- <p>
- <a name="HP1000" id="HP1000"></a>
- </p>
- <h3>
- HP1000
- </h3>
- <ul>
- <div>
- <a name="HP1000define" id="HP10000define"></a> <b>Define</b>
- <div>
- <ul>
- <code>define <WeatherStation> HP1000 [<ID> <PASSWORD>]</code><br>
- <br>
- Stellt einen Webhook für die WLAN-basierte HP1000 oder WH2600 Wetterstation von Fine Offset Electronics bereit (z.B. auch bekannt als Ambient Weather WS-1001-WIFI).<br>
- Es muss noch eine dedizierte FHEMWEB Instanz angelegt werden, wo das Attribut webname auf "weatherstation" gesetzt wurde.<br>
- Kein anderer Name funktioniert, da dieser hard im HP1000/WH2600 Gerät hinterlegt ist!<br>
- Sofern notwendig, erstellt dieses Modul eine passende FHEMWEB Instanz namens WEBweatherstation während der initialen Definition.<br>
- <br>
- Da die URI ebenfalls fest kodiert ist, kann mit einer einzelnen FHEM Installation maximal eine HP1000/WH2600 Station gleichzeitig verwendet werden.<br>
- <br>
- Beispiel:<br>
- <div>
- <code># ungeschützte Instanz bei der ID und PASSWORD ignoriert werden<br>
- define WeatherStation HP1000<br>
- <br>
- # geschützte Instanz: Die Wetterstation muss so konfiguriert sein, dass sie<br>
- # diese ID und PASSWORD sendet, damit Daten akzeptiert werden<br>
- define WeatherStation HP1000 MyHouse SecretPassword</code>
- </div><br>
- WICHTIG: Im HP1000/WH2600 Gerät selbst muss sichergestellt sein, dass ein DNS Name statt einer IP Adresse verwendet wird, da einige Revisionen damit nicht umgehen können.<br>
- </ul>
- </div><br>
- </div>
- <a name="HP1000Attr" id="HP10000Attr"></a> <b>Attributes</b>
- <div>
- <ul>
- <li><a href="#readingFnAttributes">readingFnAttributes</a></li>
- <br>
- <a name="wu_id"></a><li><b>wu_id</b></li>
- Weather Underground (Wunderground) Stations ID
- <a name="wu_password"></a><li><b>wu_password</b></li>
- Weather Underground (Wunderground) Passwort
- <a name="wu_push"></a><li><b>wu_push</b></li>
- Pushen der Daten zu Weather Underground aktivieren oder deaktivieren (Standard ist 0=aus)
- <a name="wu_realtime"></a><li><b>wu_realtime</b></li>
- Sendet die Daten an den WU Echtzeitserver statt an den Standard Server (Standard ist 1=an)
- </ul>
- </div>
- </ul>
- =end html_DE
- =cut
|