NAME
Weather::OWM - Perl client for the OpenWeatherMap (OWM) API
SYNOPSIS
use Weather::OWM;
use strict;
use v5.10;
my $owm = Weather::OWM->new(key => 'Your API key');
### Using the free endpoints of the "classic" Weather API 2.5:
# Get current weather for the Stonehenge area using coordinates...
my %re = $owm->get_weather(lat => 51.18, lon => -1.83);
# ...and print temperature, humidity, wind speed
say "$re{main}->{temp}C $re{main}->{humidity}% $re{wind}->{speed}m/s"
unless $re{error};
# Get 3h/5d forecast for London, UK...
%re = $owm->get_weather(product => 'forecast', loc => 'London,UK');
# ...and print the temperature for every three hours over the next 5 days
say scalar(localtime($_->{dt}))." $_->{main}->{temp}C" for @{$re{list}};
### Using the newer One Call 3.0 API:
# Get current weather and min/h/day forecast for Punxsutawney, PA...
%re = $owm->one_call(city => 'Punxsutawney,PA,US', units => 'imperial');
# ...print current temperature, humidity, wind speed...
say "$re{current}->{temp}F $re{current}->{humidity}% $re{current}->{wind_speed}mph"
unless $re{error};
# ...and print the temperature for every hour over the next 2 days
say "$_->{temp}F" for @{$re{hourly}};
### Using the History API 2.5:
# Get the historical weather for the first 72 hours of 2023 at Greenwich, UK...
my %report = $owm->get_history(
product => 'hourly',
loc => 'Greenwich,UK',
start => '2023-01-01 00:00:00',
cnt => '72'
);
# ...and print the temperatures next to the date/time
say scalar(localtime($_->{dt}))." $_->{main}->{temp}C" for @{$re{list}};
### Using the Geocoder API:
# Fetch Portland, Maine from the Geocoder API...
my @locations = $owm->geo(city => 'Portland,ME,US');
# ...and print the latitude,longitude
say "$locations[0]->{lat},$locations[0]->{lon}";
# Get the top 5 cities named "Portland" in the US...
@locations = $owm->geo(city => 'Portland,US', limit=>5);
# ...and print their state and coordinates.
say "$_->{state} $_->{lat},$_->{lon}" for @locations;
# Perform reverse geocoding of coordinates 51.51 North, 0.12 West...
@locations = $owm->geo(lat=>51.51, lon=>-0.12);
# ...and print the location name, country
say "$locations[0]->{name}, $locations[0]->{country}";
DESCRIPTION
Weather::OWM is a lightweight Perl client supporting most OpenWeatherMap (OWM) APIs, including the latest One Call v3.0.
There is an easy-to-use object oriented interface that can return the data in hashes. There are virtually no dependencies, except LWP::UserAgent for the requests, and optionally JSON or XML::Simple if you want to decode JSON (most common) or XML data.
Current OWM API support:
OneCall API 3.0 for current weather, forecast and weather history.
Weather API 2.5 including free (current weather, 3h/5d forecast) and paid forecasts.
Historical APIs 2.5 (history, statistical, accumulated).
Geocoding API 1.0 for direct/reverse geocoding.
Please see the official OWM website for extensive documentation. Note that even the free APIs require signing up for an API key.
This module belongs to a family of weather modules (along with Weather::Astro7Timer and Weather::WeatherKit) created to serve the apps Xasteria and Polar Scope Align, but if your service requires some extra functionality, feel free to contact the author about adding it.
CONSTRUCTOR
new
my $owm = Weather::OWM->new(
key => $api_key, #required
timeout => $timeout_sec?,
agent => $user_agent_string?,
ua => $lwp_ua?,
lang => $lang?,
units => $units?,
error => $die_or_return?,
debug => $debug?,
scheme => $url_scheme?
);
Creates a Weather::OWM object.
Required parameters:
key
: The API key is required for both free and paid APIs. For the former, you can sign up for a free account.
Optional parameters:
timeout
: Timeout for requests in secs. Default:30
.agent
: Customize the user agent string.ua
: Pass your own LWP::UserAgent to customise further. Will overrideagent
.lang
: Set language (two letter language code) for requests. You can override per API call. Default:en
.units
: Set units (standard, metric, imperial). You can override per API call. Default:metric
. Available options:standard
: Temperature in Kelvin. Wind speed in metres/sec.metric
: Temperature in Celsius. Wind speed in metres/sec.imperial
: Temperature in Fahrenheit. Wind speed in mph.
error
: If there is an error response with the main methods, you have the options todie
orreturn
it. You can override per API call. Default:return
.debug
: If debug mode is enabled, API URLs accessed are printed in STDERR. Default:false
.scheme
: You can usehttp
as an option if you have trouble building https support for LWP in your system. Default:https
.
MAIN METHODS
The main methods will return a string containing the JSON (or XML etc where specified), except in the array context (my %hash = $owm->method
), where JSON (or similar) will be used to conveniently decode it to a Perl hash.
If the request is not successful, by default an ERROR: status_line
will be returned in scalar context or (error =
HTTP::Response)> in array context. If the constructor was set with an error
equal to die
, then it will die throwing the HTTP::Response->status_line
.
For custom error handling, see the alternative methods.
one_call
One Call 3.0 API
my $report = $owm->one_call(
product => $product, # Can be: forecast, historical, daily
lat => $lat, # Required unless city/zip specified
lon => $lon, # Required unless city/zip specified
city => $city?, # City,country (via Geocoder API)
zip => $zip?, # Zip/postcode,country (via Geocoder API)
date => $date?, # Date or unix timestamp: required for daily/historical
);
my %report = $owm->one_call( ... );
Fetches a One Call API v3.0 response for the desired location. The One Call API offers 3 products, which differ in some options as listed below. lang
, error
and units
options specified in the constructor can be overridden on each call.
For an explanation to the returned data, refer to the official API documentation.
Parameters common to all products:
lat
: Latitude (-90 to 90). South is negative.lon
: Longitude (-180 to 180). West is negative.Latitude/Longitude are normally required. As a convenience, you can specify a city name or a zip/post code instead:
city
: Expectscity name,country code
orcity name,state code,US
, wherecountry code
is ISO 3166.zip
: Expectszip/post code,country code
, wherecountry code
is ISO 3166.Note that to avoid issues with ambiguity of city names etc you can use the Geocoder API manually.
One Call API products
Three call types/products to use listed below, along with any custom parameters they support. If no product is specified, forecast
is used.
forecast
: Current weather and forecasts: Provides a minute forecast for 1 hour, hourly for 48 hours and daily for 8 days. Optional parameter:exclude
: Exclude data from the API response (to reduce size). It expects a comma-delimited list with any combination of the possible values:current
,minutely
,hourly
,daily
,alerts
historical
: Weather data for any timestamp: 40+ year historical archive and 4 days ahead forecast. Required parameter:date
: Unix timestamp for start of the data. Data is available from 1979-01-01. For convenience,date
can be specified instead in iso formatYYYY-MM-DD HH:mm:ss
for your local time (orYYYY-MM-DD HH:mm:ssZ
for UTC).
daily
: Daily aggregation: 40+ year weather archive and 1.5 years ahead forecast. Required parameter:date
: Date of request in the formatYYYY-MM-DD
. For convenience, the timestamp/date formats of thehistorical
product can be used (will be truncated to just the plain date).
get_weather
Weather API 2.5
my $report = $owm->get_weather(
product => $product, # Can be: current, forecast, hourly, daily, climate
lat => $lat, # Required unless loc/zip/city_id specified
lon => $lon, # Required unless loc/zip/city_id specified
loc => $location?, # Named location (deprecated)
zip => $zip?, # Zip/postcode (deprecated)
city_id => $city_id?, # city_id (deprecated)
mode => $mode?, # output mode - default: json
);
my %report = $owm->get_weather( ... );
Fetches a weather API v2.5 response for the desired location. The weather API has several products available (some free, others requiring paid subscription), some have special arguments as listed below. lang
, error
and units
options specified in the constructor can be overridden on each call.
For an explanation to the returned data, refer to the official API documentation or see below in the products list the links for each endpoint.
Parameters common to all products:
lat
: Latitude (-90 to 90). South is negative. Required unless loc/zip/city_id specified.lon
: Longitude (-180 to 180). West is negative. Required unless loc/zip/city_id specified.loc
: Deprecated (lat/lon recommended - see Geocoder API). Location given either as acity name
orcity name,country code
orcity name,state code,US
.zip
: Deprecated (lat/lon recommended - see Geocoder API). Expectszip/post code
(US) orzip/post code,country code
.city_id
: Deprecated (lat/lon recommended - see Geocoder API). City id from list here.mode
: Output mode. Default is jsonjson
,xml
is the supported alternative (unless otherwise specified).
API products
There are several API endpoints which are selected via product
(two of them accessible with a free key). They are listed below, along with any custom parameters they support. If no product is provided, current
is used.
current
: Current Weather Data (free product). For response details see official API doc.mode
:xml
andhtml
are supported as alternatives. (Optional)
forecast
: 5 Day / 3 Hour Forecast (free product). For response details see official API doc.cnt
: Limit the number of timestamps returned. (Optional)
hourly
: Hourly Forecast (4 days). For response details see official API doc.cnt
: Limit the number of timestamps returned. (Optional)
daily
: Daily Forecast (16 days). For response details see official API doc.cnt
: Number of days (1 to 16) to be returned. (Optional)
climate
: Climatic Forecast (30 days). For response details see official API doc.cnt
: Number of days (1 to 30) to be returned. (Optional)
get_history
History API 2.5
my $report = $owm->get_history(
product => $product, # Can be: hourly, year, month, day, temp, precip
lat => $lat, # Required unless loc/zip/city_id specified
lon => $lon, # Required unless loc/zip/city_id specified
loc => $location?, # Named location (deprecated)
zip => $zip?, # Zip/postcode (deprecated)
city_id => $city_id?, # city_id (deprecated)
);
my %report = $owm->get_history( ... );
Fetches a historical weather API v2.5 response for the desired location. The weather API has several products available, some have special arguments as listed below. lang
, error
and units
options specified in the constructor can be overridden on each call.
For an explanation to the returned data, refer to the official API documentation or see below in the products list the links for each endpoint.
Parameters common to all products:
lat
: Latitude (-90 to 90). South is negative. Required unless loc/zip/city_id specified.lon
: Longitude (-180 to 180). West is negative. Required unless loc/zip/city_id specified.loc
: Deprecated (lat/lon recommended - see Geocoder API). Location given either as acity name
orcity name,country code
orcity name,state code,US
.zip
: Deprecated (lat/lon recommended - see Geocoder API). Expectszip/post code
(US) orzip/post code,country code
.city_id
: Deprecated (lat/lon recommended - see Geocoder API). City id from list here.
API products
There are several API endpoints which are selected via product
. They are listed below, along with any custom parameters they support. If none is specified, hourly
is used.
hourly
: Hourly Historical Data. For response details see official API doc. Parameters:start
: (required) Start date. Unix timestamp (or iso date).end
: (required unlesscnt
specified) End date. Unix timestamp (or iso date).cnt
: (required unlessend
specified) Number of timestamps returned (used instead ofend
).
year
: Statistical Climate Data: Yearly aggregation. Returns statistical climate indicators for the entire year. For response details see official API doc.month
: Statistical Climate Data: Monthly aggregation. Returns statistical climate indicators for a specific month of the year. For response details see official API doc. Parameters:month
: (required) Specify the month (1-12) for which to return statistical climate data.
day
: Statistical Climate Data: Day aggregation. Returns statistical climate indicators for a specific month of the year. For response details see official API doc. Parameters:month
: (required) Specify the month (1-12) for which to return statistical climate data.day
: (required) Specify the day (1-31) of the month for which to return statistical climate data.
temp
: Accumulated temperature: The sum, counted in degrees (Kelvin), by which the actual air temperature rises above or falls below a threshold level during the chosen time period. For response details see official API doc. Parameters:start
: (required) Start date. Unix timestamp (or iso date).end
: (required) End date. Unix timestamp (or iso date).threshold
: All values smaller than indicated value are not taken into account.
precip
: Accumulated precipitation: The sum, counted in millimetres, of daily precipitation during the chosen time period. For response details see official API doc. Parameters:start
: (required) Start date. Unix timestamp (or iso date).end
: (required) End date. Unix timestamp (or iso date).
geo
Geocoding API 1.0
# Direct geocoding
my $locations = $owm->geo(
city => $city?, # City,country. Required if zip not specified.
zip => $zip?, # Zip/postcode,country. Required if city not specified.
limit => $limit # Limit number of results.
);
my @locations = $owm->geo( ... );
my ($lat, $lon) = ($locations[0]->{lat},$locations[0]->{lon});
# Reverse geocoding
my $locations = $owm->geo(
lat => $lat, # Latitude.
lon => $lon, # Longitude
limit => $limit # Limit number of results.
);
my @locations = $owm->geo( ... );
my ($name, $country) = ($locations[0]->{name},$locations[0]->{country});
# Checking for error with default error handling behaviour
warn "Error" if @locations && $locations[0] eq 'error';
warn "No results" if !@locations;
Will return a list of named locations with their central coordinates (lat/lon) that match the request. The request can include either city or zip/postcode (geocoding), or latitude/longitude (reverse geocoding).
All the OWM APIs work with coordinates, which are unambiguous. As a convenience, the 2.5 API accepted city names or zip codes. This is now deprecated and you are advised to use the geocoding to get the latitude/longitude of the desired location. The Weather::OWM one_call
method also accepts city or zip as a convenience, the top result of from the Geocoding API is used. You may want to use this API directly yourself as well to verify the location is as intended.
For an explanation to the returned data, refer to the official API documentation.
Due to the data returned being an array, for the default error mode (return
), on error a size-2 array will be returned: ('error', HTTP::Response)
. Alternatives are using the geo_response
function, or passing an error=
'die'> parameter and using try/catch
.
Common parameters:
limit
: Limit the number of location results from 1 to 5. Currently, the API default seems to be set to 1. Note that both direct and reverse geocoding can produce more than one result (either different cities with the same name, of a location belonging to different administrative units (e.g. city vs local municipality).
Geocoding parameters:
city
: Expectscity name
,city name,country code
orcity name,state code,US
, wherecountry code
is ISO 3166. If thecountry code
is skipped, the result may be ambiguous if there are similarly named/sized cities in different countries.zip
: Expectszip/post code,country code
, wherecountry code
is ISO 3166.
Reverse geocoding parameters:
lat
: Latitude.lon
: Longitude.
ALTERNATIVE METHODS
The main methods handle the HTTP response errors with a die
that throws the status line. There are alternative methods you can use that work exactly the same, except you get the full HTTP::Response object from the API endpoint, so that you can do the error handling yourself.
one_call_response
my $response = $owm->one_call_response(
%args
);
Alternative to one_call
(same parameters).
get_weather_response
my $response = $owm->get_weather_response(
%args
);
Alternative to get_weather
(same parameters).
get_history_response
my $response = $owm->get_history_response(
%args
);
Alternative to get_history
(same parameters).
geo_response
my $response = $owm->geo_response(
%args
);
Alternative to geo
(same parameters).
HELPER METHODS
icon_url
my $url = $owm->icon_url($icon, $small?);
The APIs may return an icon
key which corresponds to a specific icon. The URL to the 100x100 icon (png with transparent background) is provided by this function, unless you pass $small
in which case you get the URL to the 50x50 icon.
icon_data
my $data = $owm->icon_data($icon, $small?);
Similar to icon_url above, but downloads the png data (undef on error).
HELPER FUNCTIONS
ts_to_date
my $datetime = Weather::OWM::ts_to_date($timestamp, $utc?);
The OWM APIs usually return unix timestamps (key dt
). There are many ways to convert them to human readable dates, but for convenience you can use ts_to_date
, which will return the format YYYY-MM-DD HH:mm:ss
in your local time zone, or YYYY-MM-DD HH:mm:ssZ
in UTC if the second argument is true.
PERL WEATHER MODULES
A quick listing of Perl modules for current weather and forecasts from various sources:
OpenWeatherMap
OpenWeatherMap uses various weather sources combined with their own ML and offers a couple of free endpoints (the v2.5 current weather and 5d/3h forecast) with generous request limits. Their newer One Call 3.0 API also offers some free usage (1000 calls/day) and the cost is per call above that. If you want access to history APIs, extended hourly forecasts etc, there are monthly subscriptions. If you want to access an API that is missing from Weather::OWM, feel free to ask the author.
Note that there is an older Weather::OpenWeatherMap module, but it is no longer maintained and only supports the old (v2.5) Weather API. I looked into updating it for my purposes, but it was more complex (returns objects, so a new object definition is required per API endpoint added etc) and with more dependencies (including Moo), than what I wanted from such a module.
Apple WebKit
An alternative source for multi-source forecasts is Apple's WeatherKit (based on the old Dark Sky weather API). It offers 500k calls/day for free, but requires a paid Apple developer account. You can use Weather::WeatherKit, which is very similar to this module (same author).
7Timer!
If you are interested in astronomy/stargazing the 7Timer! weather forecast might be useful. It uses the standard NOAA forecast, but calculates astronomical seeing and transparency. It is completely free and can be accessed with Weather::Astro7Timer, which is another very similar to this module (same author).
YR.no
Finally, the Norwegian Meteorological Institute offers the free YR.no service, which can be accessed via Weather::YR, although I am not affiliated and have not tested that module.
AUTHOR
Dimitrios Kechagias, <dkechag at cpan.org>
BUGS
Please report any bugs or feature requests on GitHub.
GIT
https://github.com/dkechag/Weather-OWM
LICENSE AND COPYRIGHT
This software is copyright (c) 2024 by Dimitrios Kechagias.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.