NAME

Weather::OWM - Perl client for the OpenWeatherMap (OWM) API

SYNOPSIS

 use Weather::OWM;
 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 registering 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 override agent.

  • 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 to die or return 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 use http 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 : Expects city name,country code or city name,state code,US, where country code is ISO 3166.

  • zip : Expects zip/post code,country code, where country 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 format YYYY-MM-DD HH:mm:ss for your local time (or YYYY-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 format YYYY-MM-DD. For convenience, the timestamp/date formats of the historical 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 a city name or city name,country code or city name,state code,US.

  • zip : Deprecated (lat/lon recommended - see Geocoder API). Expects zip/post code (US) or zip/post code,country code.

  • city_id : Deprecated (lat/lon recommended - see Geocoder API). City id from list here.

  • mode : Output mode. Default is json json, 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 and html 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 a city name or city name,country code or city name,state code,US.

  • zip : Deprecated (lat/lon recommended - see Geocoder API). Expects zip/post code (US) or zip/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 unless cnt specified) End date. Unix timestamp (or iso date).

    • cnt : (required unless end specified) Number of timestamps returned (used instead of end).

  • 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 : Expects city name, city name,country code or city name,state code,US, where country code is ISO 3166. If the country code is skipped, the result may be ambiguous if there are similarly named/sized cities in different countries.

  • zip : Expects zip/post code,country code, where country 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 FROM Weather::API::Base

The parent class Weather::API::Base contains some useful functions:

use Weather::API::Base qw(:all);

# Get time in YYYY-MM-DD HH:mm:ss format, local time zone from a unix timestamp
my $datetime = ts_to_date(time());

# Convert 30 degrees Celsius to Fahrenheit
my $result = convert_units('C', 'F', 30);

See the doc for that module for more details.

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 for such a module.

Apple WeatherKit

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.