#!/usr/bin/perl use strict; use warnings "all"; use bytes; use XML::Simple; #use Data::Dumper; use POSIX qw(strftime); use Fcntl; my $tmpdir = '/tmp'; my $citiesfile = "$tmpdir/cities.xml"; my $outfile = "$tmpdir/munin_weather.txt"; my $date = strftime "%Y-%m-%d", localtime; sub parsedata($); # give $filename, returns [pressure, humidity, temperature, geomag index] sub getIdByCountryAndCity(@); # get yandex data with city<->id stuff unless(-f $citiesfile){ `curl -s -q -k --no-buffer --retry 3 --retry-delay 1 --connect-timeout 15 --tcp-nodelay 'https://pogoda.yandex.ru/static/cities.xml' >$citiesfile`; unless($? == 0){ print "unable to download https://pogoda.yandex.ru/static/cities.xml"; unlink($citiesfile); exit 1; } } my %city; $city{'msk'} = getIdByCountryAndCity('Россия', 'Москва'); $city{'spb'} = getIdByCountryAndCity('Россия', 'Санкт-Петербург'); $city{'nsk'} = getIdByCountryAndCity('Россия', 'Новосибирск'); $city{'ksk'} = getIdByCountryAndCity('Россия', 'Красноярск'); $city{'nnov'} = getIdByCountryAndCity('Россия', 'Нижний Новгород'); $city{'vld'} = getIdByCountryAndCity('Россия', 'Владивосток'); $city{'vlg'} = getIdByCountryAndCity('Россия', 'Волгоград'); $city{'ast'} = getIdByCountryAndCity('Казахстан', 'Астана'); my $str = ''; foreach my $c (keys(%city)){ my $id = $city{$c}; my $xmldata = ''; unless(-f "$tmpdir/$id.xml"){ for(1..9){ $xmldata .= `curl -s -k --no-buffer --connect-timeout 20 --tcp-nodelay https://export.yandex.ru/weather-ng/forecasts/$id.xml`; if($? == 0){ sysopen(XMLDATA, "$tmpdir/$id.xml", O_WRONLY|O_CREAT|O_TRUNC)||die("Unable to write to $tmpdir/$id.xml"); syswrite XMLDATA, $xmldata; close XMLDATA; last; } sleep 1; } } my @array = @{parsedata("$tmpdir/$id.xml")}; $str .= sprintf( "%stemp:%s %spres:%s %shum:%s %smag:%s ", $c, $array[2], $c, $array[0], $c, $array[1], $c, $array[3] ); } sysopen(RESULT, $outfile, O_WRONLY|O_CREAT|O_TRUNC)||die("Unable to write to $outfile"); syswrite RESULT, $str; close RESULT; exit 0; sub getIdByCountryAndCity(@){ my ($country, $city) = @_; my $id = undef; my $simple = XML::Simple->new( KeyAttr => '' ); my $ref = eval(sprintf("\$simple->XMLin('%s')", $citiesfile)); foreach (@{$ref->{country}}){ my %hash = %$_; my $a = sprintf("%s", $hash{'name'}); next unless ($a eq $country); foreach(@{$hash{'city'}}){ next unless(${$_}{'content'} eq $city); $id = ${$_}{'id'}; last; } } return $id; } sub parsedata($){ my $file = shift ; my @a; my $simple = XML::Simple->new(KeyAttr => ''); # WTF?!!! my $data = eval(sprintf("\$simple->XMLin('%s')\n", $file)); # okay, parse stuff $a[0] = $data->{fact}->{pressure}->{content}; $a[1] = $data->{fact}->{humidity}; $a[2] = $data->{fact}->{temperature}->{content}; foreach (@{$data->{day}}){ my $ref = $_; if (defined($ref->{biomet}) and ($ref->{date} eq $date)){ $a[3] = $ref->{biomet}{geomag}; last; } } unless(defined($a[3])){ my $newdate = strftime('%Y-%m-%d', localtime(time + 86400)); foreach (@{$data->{day}}){ my $ref = $_; if (defined($ref->{biomet}) and ($ref->{date} eq $newdate)){ $a[3] = $ref->{biomet}{geomag}; last; } } } unlink($file); return \@a; }