ExOwm v2.0 is a major refactor with breaking changes. Your v1.x code will still work with deprecation warnings, but you should migrate to the new API for better performance and cleaner code.
Quick Migration
If you just want to get rid of deprecation warnings with minimal changes, replace the old function names:
# Old v1.x functions -> New v2.0 functions
get_current_weather -> current_weather / current_weather_batch
get_weather -> one_call / one_call_batch
get_five_day_forecast -> forecast_5day / forecast_5day_batch
get_hourly_forecast -> forecast_hourly / forecast_hourly_batch
get_sixteen_day_forecast -> forecast_16day / forecast_16day_batch
get_historical_weather -> historical / historical_batchReturn Value Changes
Single location requests now return {:ok, data} instead of [{:ok, data}]:
# v1.x - always returns a list
ExOwm.get_current_weather([%{city: "Warsaw"}])
# => [{:ok, data}]
# v2.0 - single location returns tuple
ExOwm.current_weather(%{city: "Warsaw"})
# => {:ok, data}
# v2.0 - batch returns list
ExOwm.current_weather_batch([%{city: "Warsaw"}])
# => [{:ok, data}]Pattern matching update:
# v1.x
case ExOwm.get_current_weather([location]) do
[{:ok, data}] -> handle_success(data)
[{:error, reason}] -> handle_error(reason)
end
# v2.0
case ExOwm.current_weather(location) do
{:ok, data} -> handle_success(data)
{:error, reason} -> handle_error(reason)
endLocation Validation (Recommended)
Use ExOwm.Location constructors for type safety and validation:
# Old style - maps (still works)
location = %{city: "Warsaw", country_code: "pl"}
# New style - validated constructors
location = ExOwm.Location.by_city("Warsaw", country: "pl")
location = ExOwm.Location.by_coords(52.374031, 4.88969)
location = ExOwm.Location.by_id(2759794)
location = ExOwm.Location.by_zip("94040", country: "us")Benefits:
Raises ArgumentError immediately if coordinates are invalid (lat not in [-90, 90], lon not in [-180, 180])
Validates required fields (e.g., ZIP code requires country)
Type-safe and self-documenting
Batch Requests
Explicit *_batch functions for multiple locations:
# v1.x - implicit batch
locations = [%{city: "Warsaw"}, %{city: "London"}]
results = ExOwm.get_current_weather(locations)
# => [{:ok, data1}, {:ok, data2}]
# v2.0 - explicit batch function
locations = [
ExOwm.Location.by_city("Warsaw"),
ExOwm.Location.by_city("London")
]
results = ExOwm.current_weather_batch(locations)
# => [{:ok, data1}, {:ok, data2}]Error Handling
Error tuples are now consistent:
# v2.0 errors
{:ok, data} # Success
{:error, :not_found} # Simple error
{:error, :api_key_invalid, details} # Error with details
{:error, :request_failed, reason} # HTTP errorHandle errors properly:
case ExOwm.current_weather(location) do
{:ok, data} ->
process_weather(data)
{:error, :not_found, details} ->
Logger.warning("Location not found: #{inspect(details)}")
{:error, :api_key_invalid, _} ->
Logger.error("Invalid API key configured")
{:error, reason} ->
Logger.error("Request failed: #{inspect(reason)}")
endConfiguration
No configuration changes needed. Same as v1.x:
config :ex_owm, api_key: System.get_env("OWM_API_KEY")
# Optional cache TTL per endpoint
config :ex_owm, :default_ttl, :timer.minutes(10)
config :ex_owm, :current_weather_ttl, :timer.minutes(5)Override TTL per request:
ExOwm.current_weather(location, ttl: :timer.minutes(1))Dependency Changes
Update your mix.exs:
defp deps do
[
{:ex_owm, "~> 2.0"}
]
endRun mix deps.update ex_owm to pull new dependencies:
HTTPoison removed, Req added (handles retries and telemetry better)
Telemetry added for observability
New Features in v2.0
Air quality APIs:
location = ExOwm.Location.by_coords(52.37, 4.89)
{:ok, data} = ExOwm.air_pollution(location)
{:ok, forecast} = ExOwm.air_pollution_forecast(location)
now = System.system_time(:second)
yesterday = now - 86_400
{:ok, history} = ExOwm.air_pollution_history(location, start: yesterday, end: now)Geocoding APIs:
# Name to coordinates
{:ok, locations} = ExOwm.geocode("London", limit: 5)
{:ok, [location]} = ExOwm.geocode("London,GB", limit: 1)
# Coordinates to name
{:ok, locations} = ExOwm.reverse_geocode(52.374031, 4.88969, limit: 1)Telemetry integration:
:telemetry.attach_many(
"owm-handler",
[
[:ex_owm, :request, :start],
[:ex_owm, :request, :stop]
],
&MyApp.handle_owm_event/4,
nil
)Deprecated APIs
One Call API 2.5 was deprecated by OpenWeatherMap in June 2024:
# These still work but emit deprecation warnings
ExOwm.one_call(location) # One Call 2.5 deprecated
ExOwm.historical(location) # Part of One Call 2.5
# Consider using specific endpoint APIs instead
ExOwm.current_weather(location) # Current weather only
ExOwm.forecast_5day(location) # 5-day forecast
ExOwm.air_pollution_history(location, start: ts, end: ts) # Air quality historyComplete Migration Example
Before (v1.x):
defmodule MyApp.Weather do
def get_weather(city) do
case ExOwm.get_current_weather([%{city: city}], units: :metric) do
[{:ok, data}] ->
{:ok, extract_temp(data)}
[{:error, reason}] ->
{:error, reason}
end
end
defp extract_temp(data) do
data["main"]["temp"]
end
endAfter (v2.0):
defmodule MyApp.Weather do
def get_weather(city) do
location = ExOwm.Location.by_city(city)
case ExOwm.current_weather(location, units: :metric) do
{:ok, data} ->
{:ok, extract_temp(data)}
{:error, reason} ->
{:error, reason}
end
end
defp extract_temp(data) do
data["main"]["temp"]
end
endBreaking Changes Summary
Function names changed (old ones deprecated)
Single location requests return {:ok, data} not [{:ok, data}]
Batch requests require explicit *_batch functions
HTTPoison replaced with Req
GenServer coordinators and workers removed
ExOwm.Supervisor module removed
Direct GenServer calls no longer supported (use ExOwm module functions)
Need Help?
Check the README for full documentation
See CHANGELOG for complete list of changes
Open an issue on GitHub if you encounter problems