API Documentation - async API client
A Python client for the MeteoLux API.
AsyncMeteoLuxClient
A Python client for the MeteoLux API, built with httpx and Pydantic.
This client is generated from the OpenAPI specification and provides methods for all available endpoints, returning structured Pydantic models.
Source code in meteolux/async_api.py
class AsyncMeteoLuxClient:
"""A Python client for the MeteoLux API, built with httpx and Pydantic.
This client is generated from the OpenAPI specification and provides
methods for all available endpoints, returning structured Pydantic models.
"""
def __init__(
self,
base_url: str = 'https://metapi.ana.lu/api/v1',
session: httpx.AsyncClient | None = None,
timeout: int = 10,
) -> None:
"""Initializes the client with the base URL.
Args:
base_url (str): The base URL for the API.
session (httpx.AsyncClient, optional): An optional session to use.
timeout (int, optional): The maximum number of seconds to wait before timing out a request.
"""
if base_url.endswith('/'):
base_url = base_url[:-1]
self.base_url = base_url
if session is None:
self.client = httpx.AsyncClient(timeout=timeout)
else:
self.client = session
async def _request(self, method: str, endpoint: str, response_model: Any | None = None, **kwargs: Any) -> Any:
"""Internal method to handle all API requests and common error handling.
Args:
method (str): The HTTP method (e.g., "GET", "POST").
endpoint (str): The API endpoint path.
response_model (Optional[Any]): The Pydantic model to use for response parsing.
**kwargs: Additional arguments for the httpx request (e.g., params, json).
Returns:
Any: The Pydantic model instance or raw JSON data.
Raises:
NotFoundError: If the API returns a 404 Not Found status code.
httpx.HTTPStatusError: If the response status code is another error.
httpx.RequestError: For network-related issues.
"""
_endpoint = f'{self.base_url}{endpoint}'
try:
response = await self.client.request(method, _endpoint, **kwargs)
response.raise_for_status()
if response.status_code == 204:
return None
data = response.json()
if response_model:
return response_model.model_validate(data)
return data
except httpx.HTTPStatusError as exc:
if exc.response.status_code == 404:
raise NotFoundError(detail=exc.response.text) from exc
raise
except httpx.RequestError:
raise
# --- ATC Endpoints ---
async def get_atc_report(self) -> ATCReport:
"""Get data for the ATC dashboard.
Corresponds to GET /atc/report.
Returns:
ATCReport: An ATCReport Pydantic model instance.
"""
endpoint = '/atc/report'
return await self._request('GET', endpoint, response_model=ATCReport)
# --- HVD Endpoints ---
async def get_observations_hvd(self) -> ObservationResponse:
"""Return last minute observation data.
Corresponds to GET /hvd/observations.
Returns:
ObservationResponse: An ObservationResponse Pydantic model instance.
"""
endpoint = '/hvd/observations'
return await self._request('GET', endpoint, response_model=ObservationResponse)
async def get_observations_metadata_hvd(self) -> ObservationMetadataResponse:
"""Return observations metadata.
Corresponds to GET /hvd/observations/metadata.
Returns:
ObservationMetadataResponse: An ObservationMetadataResponse Pydantic model instance.
"""
endpoint = '/hvd/observations/metadata'
return await self._request('GET', endpoint, response_model=ObservationMetadataResponse)
async def get_station_information_hvd(self, station_id: str) -> list[Any]:
"""Return station information, by ID.
Corresponds to GET /hvd/stations/{station_id}.
Args:
station_id (str): The ID of the station to retrieve.
Returns:
Any: Station data from the response. The OpenAPI spec indicates the return type is a list of Stations.
"""
endpoint = f'/hvd/stations/{station_id}'
return await self._request('GET', endpoint)
async def get_all_station_information_hvd(self) -> list[Any]:
"""Return all station information.
Corresponds to GET /hvd/stations.
Returns:
list[Any]: A list of station objects. The OpenAPI spec indicates the return type is a list of Stations.
"""
endpoint = '/hvd/stations'
return await self._request('GET', endpoint)
# --- MetApp Endpoints ---
async def get_weather(self, langcode: str = 'fr', city: int | None = None, lat: float | None = None, long: float | None = None) -> WeatherResponse:
"""Get weather for a city/language or lat/long.
Corresponds to GET /metapp/weather.
Args:
langcode (str): The language code (fr, de, en, lb).
city (Optional[int]): The city ID.
lat (Optional[float]): Latitude.
long (Optional[float]): Longitude.
Returns:
WeatherResponse: A WeatherResponse Pydantic model instance.
"""
endpoint = '/metapp/weather'
params: dict[str, str] = {'langcode': langcode}
if city is not None:
params['city'] = str(city)
if lat is not None:
params['lat'] = str(lat)
if long is not None:
params['long'] = str(long)
return await self._request('GET', endpoint, params=params, response_model=WeatherResponse)
async def update_user(self, user_data: User) -> None:
"""Add or update a user's token and preferences.
Corresponds to POST /metapp/user.
Args:
user_data (User): A Pydantic User model instance.
"""
endpoint = '/metapp/user'
await self._request('POST', endpoint, json=user_data.model_dump(by_alias=True))
async def get_bookmarks(self, langcode: str = 'fr', lat: float | None = None, long: float | None = None) -> Bookmarks:
"""Return all cities and the closest one if lat/long are given.
Corresponds to GET /metapp/bookmarks.
Args:
langcode (str): The language code (fr, de, en, lb).
lat (Optional[float]): Latitude.
long (Optional[float]): Longitude.
Returns:
Bookmarks: A Bookmarks Pydantic model instance.
"""
endpoint = '/metapp/bookmarks'
params: dict[str, str] = {'langcode': langcode}
if lat is not None:
params['lat'] = str(lat)
if long is not None:
params['long'] = str(long)
return await self._request('GET', endpoint, params=params, response_model=Bookmarks)
async def get_interface_texts(self, lang: typing.Literal['fr', 'de', 'en', 'lb'] = 'fr') -> dict[str, Any]:
"""Return translated interface texts for the mobile app.
Note: The spec for this endpoint's response is an un-typed object.
Corresponds to GET /metapp/text.
Args:
lang (str): The language code (fr, de, en, lb).
Returns:
dict[str, Any]: A dictionary with translated strings.
"""
endpoint = '/metapp/text'
params = {'lang': lang}
return await self._request('GET', endpoint, params=params)
async def stream_image(self, filename: str) -> httpx.Response:
"""Stream an image from the cluster.
Corresponds to GET /metapp/image/{filename}.
Args:
filename (str): The name of the image file.
Returns:
httpx.Response: The raw httpx Response object to handle streaming.
"""
endpoint = f'/metapp/image/{filename}'
return await self.client.get(endpoint, timeout=10.0)
async def get_observations_metapp(self) -> list[Any]:
"""Return participative observations in the last 30 minutes.
Note: The spec for this endpoint's response is an array of untyped objects.
Corresponds to GET /metapp/observations.
Returns:
list[Any]: A list of objects.
"""
endpoint = '/metapp/observations'
return await self._request('GET', endpoint)
async def add_observation(self, observation_data: InObservation) -> str:
"""Add a new observation.
Corresponds to POST /metapp/observation.
Args:
observation_data (InObservation): An InObservation Pydantic model instance.
Returns:
str: The successful response message.
"""
endpoint = '/metapp/observation'
return await self._request('POST', endpoint, json=observation_data.model_dump())
async def close(self) -> None:
"""Closes the httpx client."""
await self.client.aclose()
__init__(base_url='https://metapi.ana.lu/api/v1', session=None, timeout=10)
Initializes the client with the base URL.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
base_url
|
str
|
The base URL for the API. |
'https://metapi.ana.lu/api/v1'
|
session
|
AsyncClient
|
An optional session to use. |
None
|
timeout
|
int
|
The maximum number of seconds to wait before timing out a request. |
10
|
Source code in meteolux/async_api.py
def __init__(
self,
base_url: str = 'https://metapi.ana.lu/api/v1',
session: httpx.AsyncClient | None = None,
timeout: int = 10,
) -> None:
"""Initializes the client with the base URL.
Args:
base_url (str): The base URL for the API.
session (httpx.AsyncClient, optional): An optional session to use.
timeout (int, optional): The maximum number of seconds to wait before timing out a request.
"""
if base_url.endswith('/'):
base_url = base_url[:-1]
self.base_url = base_url
if session is None:
self.client = httpx.AsyncClient(timeout=timeout)
else:
self.client = session
add_observation(observation_data)
async
Add a new observation.
Corresponds to POST /metapp/observation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
observation_data
|
InObservation
|
An InObservation Pydantic model instance. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
str |
str
|
The successful response message. |
Source code in meteolux/async_api.py
async def add_observation(self, observation_data: InObservation) -> str:
"""Add a new observation.
Corresponds to POST /metapp/observation.
Args:
observation_data (InObservation): An InObservation Pydantic model instance.
Returns:
str: The successful response message.
"""
endpoint = '/metapp/observation'
return await self._request('POST', endpoint, json=observation_data.model_dump())
close()
async
Closes the httpx client.
Source code in meteolux/async_api.py
async def close(self) -> None:
"""Closes the httpx client."""
await self.client.aclose()
get_all_station_information_hvd()
async
Return all station information.
Corresponds to GET /hvd/stations.
Returns:
| Type | Description |
|---|---|
list[Any]
|
list[Any]: A list of station objects. The OpenAPI spec indicates the return type is a list of Stations. |
Source code in meteolux/async_api.py
async def get_all_station_information_hvd(self) -> list[Any]:
"""Return all station information.
Corresponds to GET /hvd/stations.
Returns:
list[Any]: A list of station objects. The OpenAPI spec indicates the return type is a list of Stations.
"""
endpoint = '/hvd/stations'
return await self._request('GET', endpoint)
get_atc_report()
async
Get data for the ATC dashboard.
Corresponds to GET /atc/report.
Returns:
| Name | Type | Description |
|---|---|---|
ATCReport |
ATCReport
|
An ATCReport Pydantic model instance. |
Source code in meteolux/async_api.py
async def get_atc_report(self) -> ATCReport:
"""Get data for the ATC dashboard.
Corresponds to GET /atc/report.
Returns:
ATCReport: An ATCReport Pydantic model instance.
"""
endpoint = '/atc/report'
return await self._request('GET', endpoint, response_model=ATCReport)
get_bookmarks(langcode='fr', lat=None, long=None)
async
Return all cities and the closest one if lat/long are given.
Corresponds to GET /metapp/bookmarks.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
langcode
|
str
|
The language code (fr, de, en, lb). |
'fr'
|
lat
|
Optional[float]
|
Latitude. |
None
|
long
|
Optional[float]
|
Longitude. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
Bookmarks |
Bookmarks
|
A Bookmarks Pydantic model instance. |
Source code in meteolux/async_api.py
async def get_bookmarks(self, langcode: str = 'fr', lat: float | None = None, long: float | None = None) -> Bookmarks:
"""Return all cities and the closest one if lat/long are given.
Corresponds to GET /metapp/bookmarks.
Args:
langcode (str): The language code (fr, de, en, lb).
lat (Optional[float]): Latitude.
long (Optional[float]): Longitude.
Returns:
Bookmarks: A Bookmarks Pydantic model instance.
"""
endpoint = '/metapp/bookmarks'
params: dict[str, str] = {'langcode': langcode}
if lat is not None:
params['lat'] = str(lat)
if long is not None:
params['long'] = str(long)
return await self._request('GET', endpoint, params=params, response_model=Bookmarks)
get_interface_texts(lang='fr')
async
Return translated interface texts for the mobile app.
Note: The spec for this endpoint's response is an un-typed object.
Corresponds to GET /metapp/text.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
lang
|
str
|
The language code (fr, de, en, lb). |
'fr'
|
Returns:
| Type | Description |
|---|---|
dict[str, Any]
|
dict[str, Any]: A dictionary with translated strings. |
Source code in meteolux/async_api.py
async def get_interface_texts(self, lang: typing.Literal['fr', 'de', 'en', 'lb'] = 'fr') -> dict[str, Any]:
"""Return translated interface texts for the mobile app.
Note: The spec for this endpoint's response is an un-typed object.
Corresponds to GET /metapp/text.
Args:
lang (str): The language code (fr, de, en, lb).
Returns:
dict[str, Any]: A dictionary with translated strings.
"""
endpoint = '/metapp/text'
params = {'lang': lang}
return await self._request('GET', endpoint, params=params)
get_observations_hvd()
async
Return last minute observation data.
Corresponds to GET /hvd/observations.
Returns:
| Name | Type | Description |
|---|---|---|
ObservationResponse |
ObservationResponse
|
An ObservationResponse Pydantic model instance. |
Source code in meteolux/async_api.py
async def get_observations_hvd(self) -> ObservationResponse:
"""Return last minute observation data.
Corresponds to GET /hvd/observations.
Returns:
ObservationResponse: An ObservationResponse Pydantic model instance.
"""
endpoint = '/hvd/observations'
return await self._request('GET', endpoint, response_model=ObservationResponse)
get_observations_metadata_hvd()
async
Return observations metadata.
Corresponds to GET /hvd/observations/metadata.
Returns:
| Name | Type | Description |
|---|---|---|
ObservationMetadataResponse |
ObservationMetadataResponse
|
An ObservationMetadataResponse Pydantic model instance. |
Source code in meteolux/async_api.py
async def get_observations_metadata_hvd(self) -> ObservationMetadataResponse:
"""Return observations metadata.
Corresponds to GET /hvd/observations/metadata.
Returns:
ObservationMetadataResponse: An ObservationMetadataResponse Pydantic model instance.
"""
endpoint = '/hvd/observations/metadata'
return await self._request('GET', endpoint, response_model=ObservationMetadataResponse)
get_observations_metapp()
async
Return participative observations in the last 30 minutes.
Note: The spec for this endpoint's response is an array of untyped objects.
Corresponds to GET /metapp/observations.
Returns:
| Type | Description |
|---|---|
list[Any]
|
list[Any]: A list of objects. |
Source code in meteolux/async_api.py
async def get_observations_metapp(self) -> list[Any]:
"""Return participative observations in the last 30 minutes.
Note: The spec for this endpoint's response is an array of untyped objects.
Corresponds to GET /metapp/observations.
Returns:
list[Any]: A list of objects.
"""
endpoint = '/metapp/observations'
return await self._request('GET', endpoint)
get_station_information_hvd(station_id)
async
Return station information, by ID.
Corresponds to GET /hvd/stations/{station_id}.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
station_id
|
str
|
The ID of the station to retrieve. |
required |
Returns:
| Name | Type | Description |
|---|---|---|
Any |
list[Any]
|
Station data from the response. The OpenAPI spec indicates the return type is a list of Stations. |
Source code in meteolux/async_api.py
async def get_station_information_hvd(self, station_id: str) -> list[Any]:
"""Return station information, by ID.
Corresponds to GET /hvd/stations/{station_id}.
Args:
station_id (str): The ID of the station to retrieve.
Returns:
Any: Station data from the response. The OpenAPI spec indicates the return type is a list of Stations.
"""
endpoint = f'/hvd/stations/{station_id}'
return await self._request('GET', endpoint)
get_weather(langcode='fr', city=None, lat=None, long=None)
async
Get weather for a city/language or lat/long.
Corresponds to GET /metapp/weather.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
langcode
|
str
|
The language code (fr, de, en, lb). |
'fr'
|
city
|
Optional[int]
|
The city ID. |
None
|
lat
|
Optional[float]
|
Latitude. |
None
|
long
|
Optional[float]
|
Longitude. |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
WeatherResponse |
WeatherResponse
|
A WeatherResponse Pydantic model instance. |
Source code in meteolux/async_api.py
async def get_weather(self, langcode: str = 'fr', city: int | None = None, lat: float | None = None, long: float | None = None) -> WeatherResponse:
"""Get weather for a city/language or lat/long.
Corresponds to GET /metapp/weather.
Args:
langcode (str): The language code (fr, de, en, lb).
city (Optional[int]): The city ID.
lat (Optional[float]): Latitude.
long (Optional[float]): Longitude.
Returns:
WeatherResponse: A WeatherResponse Pydantic model instance.
"""
endpoint = '/metapp/weather'
params: dict[str, str] = {'langcode': langcode}
if city is not None:
params['city'] = str(city)
if lat is not None:
params['lat'] = str(lat)
if long is not None:
params['long'] = str(long)
return await self._request('GET', endpoint, params=params, response_model=WeatherResponse)
stream_image(filename)
async
Stream an image from the cluster.
Corresponds to GET /metapp/image/{filename}.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
filename
|
str
|
The name of the image file. |
required |
Returns:
| Type | Description |
|---|---|
Response
|
httpx.Response: The raw httpx Response object to handle streaming. |
Source code in meteolux/async_api.py
async def stream_image(self, filename: str) -> httpx.Response:
"""Stream an image from the cluster.
Corresponds to GET /metapp/image/{filename}.
Args:
filename (str): The name of the image file.
Returns:
httpx.Response: The raw httpx Response object to handle streaming.
"""
endpoint = f'/metapp/image/{filename}'
return await self.client.get(endpoint, timeout=10.0)
update_user(user_data)
async
Add or update a user's token and preferences.
Corresponds to POST /metapp/user.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
user_data
|
User
|
A Pydantic User model instance. |
required |
Source code in meteolux/async_api.py
async def update_user(self, user_data: User) -> None:
"""Add or update a user's token and preferences.
Corresponds to POST /metapp/user.
Args:
user_data (User): A Pydantic User model instance.
"""
endpoint = '/metapp/user'
await self._request('POST', endpoint, json=user_data.model_dump(by_alias=True))