Python client for the Lovens API.
Project description
pylovens
Python client for the Lovens API.
With pylovens
you can access the data that is available in the Lovens app for bikes with a GPS unit.
Usage
Using the client is as simple as:
from pylovens import LovensClient
client = LovensClient("your_username", "your_secret_password")
bikes = client.get_bikes()
Note: only authentication with email/password is supported.
Methods
The LovensClient
exposes the following methods:
User
get_user
- Get information on the user.
def get_user(self) -> dict
Returns
An extensive dictionary with details on the user, including the following keys and many more:
{
"id": 1234,
"name": "Your Name",
"creation_date": datetime(2023, 4, 30, 23, 59, 59, tzinfo=ZoneInfo(key='Europe/Amsterdam'),
"email": "your@mail.address",
"timezone": "Europe/Amsterdam",
...
}
Bikes
get_bikes
- Fetch all bikes accessible to your user.
def get_bikes(self) -> list[dict]
Returns
A list of dictionaries of the following form:
{
'id': 456,
'user_id': 1234,
'user_name': 'Your Name',
'active_state': 0,
'name': 'Your Bikes Name',
'last_location': { <most recent available result of the get_location method> },
'battery_percentage': 50,
'owning_user': { <result of get_user method> },
'geofences': [ <result of get_geofences method> ],
...
}
get_bike
- Fetch a bike by its ID.
def get_bike(self, bike_id: int) -> dict
Arguments
bike_id
: The ID of the bike.
Returns
A dictionaries of the following form:
{
'id': 456,
'user_id': 1234,
'user_name': 'Your Name',
'active_state': 0,
'name': 'Your Bikes Name',
'last_location': { <most recent available result of the get_location method> },
'battery_percentage': 50,
'owning_user': { <result of get_user method> },
'geofences': [ <result of get_geofences method> ],
...
}
get_state
- Get the state of a bike.
def get_state(self, bike_id: int) -> dict[str]
Arguments
bike_id
: The ID of the bike.
Returns
A dictionary of the following form:
{
'powered_on': False,
'ecu_locked': False,
'erl_locked': False,
'battery_percentage': 50,
'charging': False,
'last_full_charge': datetime(2023, 4, 1, 17, 10, 30, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
'odometer': 300,
'range': 30
}
get_health
- Get bike health status.
def get_health(self, bike_id: int) -> list[dict]
Arguments
bike_id
: The ID of the bike.
Returns
A list of four dictionaries:
[
{
'key': 'last_connection',
'status': True,
'value': datetime(2023, 4, 1, 17, 10, 30, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
'value_type': 'datetime'
},
{
'key': 'last_gps',
'status': False,
'value': datetime(2023, 3, 31, 16, 51, 22, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
'value_type': 'datetime'
},
{
'key': 'gps_battery',
'status': True,
'value': '75%',
'value_type': 'string'
},
{
'key': 'bike_system',
'status': True,
'value': 'true',
'value_type': 'bool'
}
]
Rides
iterate_rides
- Iterate through the rides of a bike.
def iterate_rides(
self, bike_id: int, newest_first: bool = True, batch_size: int = 50, _offset: int = 0
) -> Iterable[dict]
Arguments
bike_id
: The ID of the bike.newest_first
: If True, fetch the most recent ride first. Defaults toTrue
.batch_size
: The number of rides to fetch at once._offset
: Used in pagination.
Returns
An iterable of dictionaries describing the rides. Each dictionary contains, among others, the following keys:
{
"id": 123456,
"start_date": datetime(2023, 4, 1, 17, 1, 0, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
"end_date": datetime(2023, 4, 1, 17, 6, 30, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
"calories": 14,
"avg_speed": 21,
"distance_traveled": 1234,
"bike_id": 123,
"user_id": 1234,
"user": { <same as output of get_user()> },
"creation_date": datetime(2023, 4, 1, 17, 10, 30, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
"active_time": 330,
"timezone": "Europe/Amsterdam",
...
}
get_rides
- Fetch a list of rides of a bike.
def get_rides(self, bike_id: int, newest_first: bool = True, n: int = 50) -> list[dict]
If you are interested in fetching all rides of a bike, or are not sure how many you need,
consider using iterate_rides
.
Arguments
bike_id
: The ID of the bike.newest_first
: If True, fetch the most recent ride first. Defaults to True.n
: Number of rides to fetch. Defaults to 50.
Returns
An list of dictionaries describing the rides. Each dictionary contains, among others, the following keys:
{
"id": 123456,
"start_date": datetime(2023, 4, 1, 17, 1, 0, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
"end_date": datetime(2023, 4, 1, 17, 6, 30, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
"calories": 14,
"avg_speed": 21,
"distance_traveled": 1234,
"bike_id": 123,
"user_id": 1234,
"user": { <same as output of get_user()> },
"creation_date": datetime(2023, 4, 1, 17, 10, 30, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
"active_time": 330,
"timezone": "Europe/Amsterdam",
...
}
get_ride
- Fetch a ride by its ID.
def get_ride(self, ride_id: int) -> dict
Arguments
ride_id
: The ID of the ride.
Returns
A dictionary describing the ride. It contains, among others, the following keys:
{
"id": 123456,
"start_date": datetime(2023, 4, 1, 17, 1, 0, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
"end_date": datetime(2023, 4, 1, 17, 6, 30, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
"calories": 14,
"avg_speed": 21,
"distance_traveled": 1234,
"bike_id": 123,
"user_id": 1234,
"user": { <same as output of get_user()> },
"creation_date": datetime(2023, 4, 1, 17, 10, 30, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
"active_time": 330,
"timezone": "Europe/Amsterdam",
...
}
get_location
- Get location history in a time range.
def get_location(
self, bike_id: int, start_date: datetime | date, end_date: datetime | date
) -> list[dict, bool, datetime | int | float]
If start_date
and/or end_date
is a date object, they are interpreted as the start and end of the day
respectively. Timezone-naive datetime objects are converted to the user's timezone (see get_user
).
Arguments
bike_id
: The ID of the bike.start_date
: Start date of a timespan.end_date
: End date of a timespan.
Returns
A list of dictionaries of the following form:
{
"id": "123456b123",
'lat': 52.379189,
'lon': 4.899431,
"date": datetime(2023, 4, 1, 17, 1, 0, tzinfo=ZoneInfo(key='Europe/Amsterdam')),
"speed": 21,
"battery_percentage": 0, # Always 0 - never filled
"bike_id": 123,
"is_moving": True
}
Battery
get_battery_state
- Get the state of the battery of a bike.
def get_battery_state(self, bike_id: int) -> dict[str]
Arguments
bike_id
: The ID of the bike.
Returns
A dictionary of the following form:
{
'current': -450,
'battery_percentage': 69,
'last_battery_update': datetime(2023, 4, 30, 0, 0, 0, tzinfo=ZoneInfo(key='Europe/Amsterdam'),
'last_full_charge': datetime(2023, 4, 30, 0, 0, 0, tzinfo=ZoneInfo(key='Europe/Amsterdam'),
'charging': False,
'range': 30
}
get_battery_statistics
- Get historical state of the battery of a bike.
def get_battery_statistics(
self,
bike_id: int,
start_date: date | datetime | None = None,
end_date: date | datetime | None = None,
)
If start_date is not provided or None, it defaults to 24 hours ago. If end_date is not provided or None, it defaults to now.
If start_date
and/or end_date
is a date object, they are interpreted as the start and end of the day
respectively. Timezone-naive datetime objects are converted to the user's timezone (see get_user
).
Arguments
bike_id
: The ID of the bike.start_date
: Optional start date or datetime.end_date
: Optional end date or datetime (inclusive).
Returns
A list of dictionaries of the following form, in 15-minute intervals:
{
'date': datetime(2023, 4, 30, 0, 0, 0, tzinfo=ZoneInfo(key='Europe/Amsterdam'),
'battery_percentage': 69,
'charging': False,
'seconds_in_ride': 0,
'seconds_charging': 0,
}
Note that battery_percentage
is None
when the battery is removed.
Statistics
get_statistics
- Get ride statistics for a bike.
def get_statistics(
self,
bike_id: int,
start_date: date | datetime,
end_date: date | datetime,
type: str = "daily",
) -> list[dict]
If start_date
and/or end_date
is a date object, they are interpreted as the start and end of the day
respectively. Timezone-naive datetime objects are converted to the user's timezone (see get_user
).
Note that this endpoint expects the end_date
, if it is a datetime, to be one second before the start of the
next bin. E.g. daily statistics for the month of January 2023 can be obtained by calling
get_statistics(123, start_date=datetime(2023, 1, 1, 0, 0), end_date=datetime(2023, 1, 31, 23, 59, 59))
.
Passing datetime(2023, 2, 1, 0, 0)
as end_date
instead will return in an extra 0-second bin at the end.
Arguments
bike_id
: The ID of the bike.start_date
: Start date or datetime.end_date
: End date or datetime (inclusive).type
: Aggregation level. One of "hourly", "daily" or "monthly". Defaults to "daily".
Returns
A list of dictionaries of the following form:
{
'from': datetime(2023, 4, 30, 0, 0, 0, tzinfo=ZoneInfo(key='Europe/Amsterdam'),
'till': datetime(2023, 4, 30, 23, 59, 59, tzinfo=ZoneInfo(key='Europe/Amsterdam'),
'co2': 2584,
'calories': 156,
'avg_speed': 18,
'distance_traveled': 10379,
'avg_power_distribution': 83,
'shift_advice': 0,
'top_speed': 28,
'elevation_up': 238,
'elevation_down': 232
}
Geofences
get_geofences
- Fetch all geofences associated to a bike.
def get_geofences(self, bike_id: int) -> list[dict[str, datetime | dict[str, float] | int | str]]
Arguments
bike_id
: The ID of the bike.
Returns
A list of dictionaries of the following form:
{
'id': 456,
'bike_id': 123,
'user_id': 1234,
'name': 'Amsterdam City Center',
'center': {'lat': 52.379189, 'lon': 4.899431},
'radius': 200,
'active_state': 0,
'creation_date': datetime(2023, 4, 1, 17, 10, 30, tzinfo=ZoneInfo(key='Europe/Amsterdam'))
}
get_geofence
- Get a single geofence by its ID.
def get_geofence(self, geofence_id: int) -> dict[str, datetime | dict[str, float] | int | str]
Arguments
geofence_id
: The ID of the geofence.
Returns
A dictionary of the following form:
{
'id': 456,
'bike_id': 123,
'user_id': 1234,
'name': 'Amsterdam City Center',
'center': {'lat': 52.379189, 'lon': 4.899431},
'radius': 200,
'active_state': 0,
'creation_date': datetime(2023, 4, 1, 17, 10, 30, tzinfo=ZoneInfo(key='Europe/Amsterdam'))
}
get_geofence_stats
- Get statistics of a geofence.
def get_geofence_stats(
self,
geofence_id: int,
start_date: datetime | date | None = None,
end_date: datetime | date | None = None,
) -> dict[str, int]
Arguments
geofence_id
: The ID of the geofence.start_date
: Start date of a timespan. Optional, must be provided ifend_date
is provided.end_date
: End date of a timespan. Optional, must be provided ifstart_date
is provided.
Returns
A dictionary of the following form:
{
'entries_all_time': 1,
'entries_in_timespan': 0 # Only if start_date and end_date provided.
}
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file pylovens-0.3.1.tar.gz
.
File metadata
- Download URL: pylovens-0.3.1.tar.gz
- Upload date:
- Size: 17.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 11de316154d2bfb2a23d831ea4a70e2c846b1c371337a3f0d697ab688964553a |
|
MD5 | 46ea15eb3d83aadd7457cfed254ef060 |
|
BLAKE2b-256 | 4df2126c284e682b45e9b533f31b69e278adbbab43c5a587cdc30c2b2624fe89 |
File details
Details for the file pylovens-0.3.1-py3-none-any.whl
.
File metadata
- Download URL: pylovens-0.3.1-py3-none-any.whl
- Upload date:
- Size: 11.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/4.0.2 CPython/3.11.4
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | b74f2785af7e00de0a3c06b481c7c28b1b45df08c4d16bf0d20252a5ed6ee7dd |
|
MD5 | b960e1d4e35322fc4c58f3ee1a1a13f3 |
|
BLAKE2b-256 | 556369265aff4cdddb7d9546f59b9845e46e1eb2b57a7453178d2799ca00aa59 |