Skip to content
Snippets Groups Projects
Commit 328c204b authored by Aaron Estrada Poggio's avatar Aaron Estrada Poggio
Browse files

Initial commit

- Retrieve list of variables for each measurement
- Download data for single measurement/variable on date range
parents
No related branches found
No related tags found
No related merge requests found
ABD API Client Connector
Copyright (c) 2021, Eurac Research
All rights reserved.
Contributors
------------
- Aaron Estrada Poggio [aaron.estrada@eurac.edu; aaron.estrada.poggio@gmail.com]
Disclaimer
----------
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the <organization> nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
recursive-include abd_api_connector *.py
include setup.py
include requirements.txt
include LICENSE.txt
include README.md
\ No newline at end of file
# Aeroporto di Bolzano API client connection
Custom client connection to Aeroporto di Bolzano API v1 (release v1.0).
## Project structure
```
/abd_api_connector Utility libraries
Connector.py ABD API client connector object
requirements.txt Requirements for package
setup.py Package setup
```
## Using the connector
The following example retrieves all the configured signals for the Meteo Station laboratory.
```python
from abd_api_connector import ABDApiClientConnector
api = ABDApiClientConnector(
base_url='http://abdapiurl/api/v1',
token='123456'
)
# Function to decorate error during connection to any resource
@api.connection_error
def connection_error(url, error):
print(f'Connection error for URL {url}: {error}')
response = api.get_station_data(
measurement='<measurement>',
variable='<variable>',
start_date='2020-01-01T00:00:00Z',
end_date='2020-01-01T23:59:59Z'
)
if response.status_code == 200 and response.content_json is not None:
print(response.content_json)
```
\ No newline at end of file
import requests
from urllib.parse import quote_plus
from requests.exceptions import ConnectionError
from requests import Response as RequestResponse
class ApiResponse(object):
# Response instance (from requests)
response = None
@property
def status_code(self):
if type(self.response) == RequestResponse:
return self.response.status_code
return None
@property
def content(self):
if type(self.response) == RequestResponse:
return self.response.content
return None
@property
def content_json(self):
json = None
if type(self.response) == RequestResponse:
try:
json = self.response.json()
except ValueError:
pass
return json
class ABDApiClientConnector:
"""
Client connector for resources in ABD API.
- All resources return an ApiResponse instance;
- Prior to retrieve results, check 'status_code' property from returned instance, generally it returns a 200 code;
- To retrieve results, access to the 'content_json' property from returned instance.
"""
def __init__(self, base_url: str, token: str = None):
"""
Class constructor
:param base_url: Base URL for API
:param token: Token to use as authentication for requests
"""
self._base_url = base_url
self._token = token
self._connection_error_callback = None
@property
def _authentication_header(self):
"""
Header including authentication token
:return:
"""
return {'X-API-KEY': self._token} if self._token is not None else None
def _request(self, method: str, url: str, data: dict = None) -> ApiResponse:
"""
Attempt to request using GET method
:param url: relative path inside API
:return: ApiResponse instance
"""
request_response = ApiResponse()
url_path = f'{self._base_url}{url}'
try:
response = requests.request(
method=method,
url=url_path,
headers=self._authentication_header,
json=data
)
request_response.response = response
except ConnectionError as error:
if self._connection_error_callback is not None:
self._connection_error_callback(url=url_path, error=error)
else:
raise error
return request_response
def _request_get(self, url: str, data: dict = None) -> ApiResponse:
"""
Attempt to request using GET method
:param url: relative path inside API
:param data: Data to send on request
:return: ApiResponse instance
"""
return self._request(method='GET', url=url, data=data)
def _request_put(self, url: str, data: dict = None) -> ApiResponse:
"""
Attempt to request using PUT method
:param url: relative path inside API
:param data: Data to send on request
:return: ApiResponse instance
"""
return self._request(method='PUT', url=url, data=data)
def _request_post(self, url: str, data: dict = None) -> ApiResponse:
"""
Attempt to request using POST method
:param url: relative path inside API
:param data: Data to send on request
:return: ApiResponse instance
"""
return self._request(method='POST', url=url, data=data)
def _request_delete(self, url: str, data: dict = None) -> ApiResponse:
"""
Attempt to request using DELETE method
:param url: relative path inside API
:param data: Data to send on request
:return: ApiResponse instance
"""
return self._request(method='DELETE', url=url, data=data)
@staticmethod
def _quote_variables(variables: dict) -> str:
"""
Join variables to include in GET method
:param variables: List of variables to quote
:return: String with quoted variables
"""
return '&'.join([f'{key}={quote_plus(str(value))}' for key, value in variables.items()])
def set_token(self, token):
"""
Set new token for API connection
:param token: Token to use as authentication for requests
:return:
"""
self._token = token
def connection_error(self, f):
"""
Error for connection not reachable
:param f: Function to set as ping error
:return:
"""
self._connection_error_callback = f
# ------------------
# Namespace: Station
# ------------------
def get_station_variables(self) -> ApiResponse:
"""
Get list of variables for each measurement from station
:return:
"""
return self._request_get(url='/station/variables')
def get_station_data(self,
measurement: str,
variable: str,
start_date: str,
end_date: str) -> ApiResponse:
"""
Retrieve values for a signal from Meteo Station laboratory
:param measurement: Measurement to retrieve values
:param variable: Variable from measurement to retrieve values
:param start_date: Start time to retrieve values (format ISO 8601)
:param end_date: End time to retrieve values (format ISO 8601)
:return:
"""
variable_mapping = {
'measurement': measurement,
'variable': variable,
'start_time': start_date,
'end_time': end_date
}
url = f'/station?{self._quote_variables(variables=variable_mapping)}'
return self._request_get(url=url)
# -*- coding: utf-8 -*-
from __future__ import absolute_import
from .Connector import ABDApiClientConnector, ApiResponse
__version__ = '1.0'
__all__ = (
'ABDApiClientConnector',
'ApiResponse'
)
requests>=2.26
\ No newline at end of file
setup.py 0 → 100644
from distutils.core import setup
setup(
name='abd-api-connector',
version='1.0',
description='Client connection to Aeroporto di Bolzano (ABD) API',
license='BSD',
author='Aaron Estrada Poggio',
author_email='aaron.estrada@eurac.edu',
url='https://gitlab.inf.unibz.it/URS/abd/abd-api-connector',
include_package_data=True,
packages=['abd_api_connector'],
python_requires='>=3.6',
install_requires=[
'requests>=2.26.0'
]
)
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment