From 2ea58abdf0b3b29721e522609f3a1dc5597d97a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=99emysl=20Eric=20Janouch?= Date: Fri, 8 Oct 2021 23:09:19 +0200 Subject: wmstatus-weather.pl: update to use a newer API The old one has been obsoleted, and sometimes refuses to work. The "classic" endpoint is, sadly, not fully backwards-compatible. --- wmstatus-weather.pl | 68 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 39 insertions(+), 29 deletions(-) diff --git a/wmstatus-weather.pl b/wmstatus-weather.pl index bce6c3d..d5252f2 100755 --- a/wmstatus-weather.pl +++ b/wmstatus-weather.pl @@ -6,45 +6,55 @@ use strict; use warnings; use Time::Piece; -use IO::Socket::INET; +use File::Basename; -my $host = 'www.yr.no'; -my $path = '/place/Czech_Republic/Prague/Prague/forecast.xml'; +# Retrieve current weather information from the Norwegian weather service, +# see https://api.met.no/doc/ for its documentation +my $base = 'https://api.met.no/weatherapi'; +my $agent = basename($0) =~ s/[^-!#$%&'*+.^_`|~[:alnum:]]//gr; -# Retrieve current weather information from the Norwegian weather service -sub weather { - # There are no redirects and it's not exactly confidential either - my $sock = IO::Socket::INET->new( - PeerAddr => $host, - PeerPort => 'http(80)', - Proto => 'tcp' - ) or return '?'; +# https://www.yr.no/storage/lookup/English.csv.zip +my $where = 'lat=50.08804&lon=14.42076&altitude=202'; # Prague +my %legends; + +sub retrieve_legends { + # HTTP/Tiny supports TLS, but with non-core IO::Socket::SSL, so use cURL + open(my $sock, '-|', 'curl', '-sSA', $agent, + "$base/weathericon/2.0/legends.txt") or return $!; + while (local $_ = <$sock>) { $legends{$1} = $2 if /^(.+?),(.+?),/ } + close($sock); +} - print $sock "GET $path HTTP/1.1\r\n" - . "Host: $host\r\n" - . "Connection: close\r\n\r\n"; +sub weather { + # We might want to rewrite this to use the JSON API (/compact), + # see https://developer.yr.no/doc/guides/getting-started-from-forecast-xml + open(my $sock, '-|', 'curl', '-sA', $agent, + "$base/locationforecast/2.0/classic?$where") or return $!; # Quick and dirty XML parsing is more than fine for our purpose - my ($offset, $acceptable, $temp, $symbol) = (0, 0); + my ($acceptable, $temp, $symbol) = (0, undef, undef); while (<$sock>) { - $offset = $1 * 60 if /utcoffsetMinutes="(.+?)"/; - next unless /