Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use new mytoyota api endpoints #198

Merged
merged 71 commits into from
Jan 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
71 commits
Select commit Hold shift + click to select a range
4ef5b3a
poetry update and use stub files in dev dependencies for better hints
CM000n Jan 1, 2024
139e057
update mytoyota dependency in manifest file
CM000n Jan 1, 2024
dae4a5b
fix implicit string concatenation
CM000n Jan 1, 2024
774e8d0
adapt config flow to new api
CM000n Jan 1, 2024
dd96fc7
adopt statistics gathering to upcoming mytoyota changes
CM000n Jan 2, 2024
9f5835a
adopt device tracker to new API
CM000n Jan 2, 2024
07eede1
update manifest file
CM000n Jan 2, 2024
60bac8c
add statistic to base entity
CM000n Jan 3, 2024
cd2af30
bump version
CM000n Jan 3, 2024
8086e1f
using brand from vehicle info
CM000n Jan 3, 2024
bebc384
simplify genrating of device tracker
CM000n Jan 3, 2024
6cc1fac
bump required minimum mytoyota version to 1.1.0
CM000n Jan 3, 2024
1f97c9e
remove unused binary sensors for now
CM000n Jan 3, 2024
c6ac342
simplify capability check
CM000n Jan 3, 2024
3576f64
adopt binary sensors to new api models
CM000n Jan 3, 2024
87e497c
fix import error
CM000n Jan 3, 2024
d9ad89c
use last_parked capability for generating device_tracker
CM000n Jan 3, 2024
310f7e4
make metric value choise a requirement
CM000n Jan 4, 2024
153d324
make metric value choise a requirement
CM000n Jan 4, 2024
50fd3b0
add translations
CM000n Jan 4, 2024
d8ca62c
bump minmum required mytoyota version
CM000n Jan 6, 2024
f2d7164
invert binary sensor logic
CM000n Jan 6, 2024
c6e5110
merge master
CM000n Jan 8, 2024
d0b2d31
only create trunk status binary_sensor if bonnet_status capability is…
CM000n Jan 8, 2024
758eb67
run pre-commit on all files
CM000n Jan 8, 2024
f27b42d
return None if try block fails
CM000n Jan 8, 2024
eeb1779
increase update_interval to 5 minutes
CM000n Jan 8, 2024
1eec460
adjust driver door lock icon
CM000n Jan 8, 2024
588d6a3
make metric value information available for further steps
CM000n Jan 8, 2024
241113c
adopt statistics sensors to new api
CM000n Jan 8, 2024
4fb4ee6
update statistics utils and delete unsused constants
CM000n Jan 8, 2024
c9cda60
add vin sensor
CM000n Jan 8, 2024
97de4bd
display all vehicle informations in vin sensor
CM000n Jan 9, 2024
30fad24
display ev summary also for pure electric vehicles
CM000n Jan 9, 2024
5ac3feb
return timdelta and date as string
CM000n Jan 9, 2024
e325833
add odometer and fuel sensors
CM000n Jan 9, 2024
6af3f53
clean up sensor translations
CM000n Jan 9, 2024
5c1f2d3
format vin sensor attributes
CM000n Jan 9, 2024
a7e1bba
use car_model_name
CM000n Jan 9, 2024
87f30c7
make battery_level sensor available for all ev vehicles
CM000n Jan 9, 2024
c20a4ae
use upper case for asi_code and imei
CM000n Jan 9, 2024
6c4438a
fix battery_level sensor
CM000n Jan 9, 2024
8d05180
return only true capabilities
CM000n Jan 9, 2024
aec7cda
add battery_range
CM000n Jan 9, 2024
90ded8d
add total_range
CM000n Jan 9, 2024
3c514bd
add battery_range_ac
CM000n Jan 9, 2024
e8fc10d
fix unpacking
CM000n Jan 9, 2024
d5cc6c5
reurn dict instead of list
CM000n Jan 9, 2024
fe5455d
mask pii data in attributes
CM000n Jan 9, 2024
119234e
round range and level values
CM000n Jan 9, 2024
8df5b43
bump minimum required mytoyota version to 1.1.3
CM000n Jan 9, 2024
fd03a97
reduce line-length
CM000n Jan 9, 2024
2780ab1
no need for masking Katashiki_code
CM000n Jan 10, 2024
e1919aa
add duration and distance to summary attributes
CM000n Jan 10, 2024
2d59460
remove redundant vin information in attributes
CM000n Jan 10, 2024
3d531ac
remove redundant information
CM000n Jan 10, 2024
c9427fd
rename fuel consumption
CM000n Jan 10, 2024
b41eb69
bump minimum required mytoyota version to 1.2.0
CM000n Jan 11, 2024
a8283c7
add average_fuel_consumed to vin sensor attributes
CM000n Jan 11, 2024
3619f37
use dictionary merging
CM000n Jan 11, 2024
0daba1d
Make use of new helper functions for statistics
CM000n Jan 11, 2024
279c9fe
Update readme
CM000n Jan 11, 2024
785aa47
generate battery sensors only for ev vehicles
CM000n Jan 11, 2024
8c53722
Merge branch 'enhancement/use_new_mytoyota_api' of github.com:DurgNom…
CM000n Jan 11, 2024
ec683f2
Use Mapping for brand names
CM000n Jan 11, 2024
69ad37f
create odometer only when telemetry capable
CM000n Jan 11, 2024
ad00a00
Update French translations (#203)
pierrebelloy Jan 11, 2024
ec2b3bc
Use same condition for ev vehicles like in mytoyota lib
CM000n Jan 11, 2024
37f1e5f
Merge branch 'enhancement/use_new_mytoyota_api' of github.com:DurgNom…
CM000n Jan 11, 2024
d08a2b1
use same condition for last_parked like in mytoyota lib
CM000n Jan 11, 2024
d661f35
create statistics sensors by default for now
CM000n Jan 11, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
107 changes: 47 additions & 60 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
## About

This is a custom integration the retrieves' data from the
Toyota EU MyT API and makes them available in Home Assistant as different types of sensors.
Toyota EU MyToyota ctpa-oneapi API and makes them available in Home Assistant as different types of sensors.
As there is no official API from Toyota, I will try my best to keep
it working, but there are no promises.

Expand All @@ -30,47 +30,42 @@ See [here](https://github.com/widewing/ha-toyota-na) for North America.

### Overview

- Numberplate and starter battery sensors
- VIN (Vehicle Identification Number) sensor
- Fuel, battery and odometer information
- Current week, month and year statistics.
- HVAC, Window and lights sensors
- Current day, week, month and year statistics.
- Door and door lock sensors, including hood and trunk sensor.
- Is key in car and over all status sensor.

### Binary sensor(s)

| <div style="width:250px">Name</div> | Description |
| --------------------------------------- | ----------------------------------------------------------------------------------- |
| `binary_sensor.corolla_hood` | If the hood is open of not. |
| `binary_sensor.corolla_*_defogger` | Defogger is on sensor, one is created for front and rear if available |
| `binary_sensor.corolla_*_door` | Door sensor, one is created for each door and trunk. |
| `binary_sensor.corolla_*_lock` | Lock sensor, one is created for each door and trunk. |
| `binary_sensor.corolla_*_lights` | Light sensor, one is created for front, back and hazard lights. |
| `binary_sensor.corolla_over_all_status` | Over all status of the vehicle, if warning is true for a sensor, this will show it. |
| `binary_sensor.corolla_key_in_car` | If key is in the car. |
| `binary_sensor.corolla_*_window` | Window sensor, one is created for window. |
| <div style="width:250px">Name</div> | Description |
| ---------------------------------------- | ----------------------------------------------------- |
| `binary_sensor.<you_car_alias>_hood` | If the hood is open of not. |
| `binary_sensor.<you_car_alias>_*_door` | Door sensors, one is created for each door and trunk. |
| `binary_sensor.<you_car_alias>_*_lock` | Lock sensors, one is created for each door and trunk. |
| `binary_sensor.<you_car_alias>_*_window` | Window sensors, one is created for window. |

### Device tracker(s)

| <div style="width:250px">Name</div> | Description |
| ----------------------------------- | ---------------------------------- |
| `device_tracker.corolla` | Shows you last parked information. |
| <div style="width:250px">Name</div> | Description |
| ----------------------------------- | ----------------------------------- |
| `device_tracker.<you_car_alias>` | Shows you last parking information. |

### Sensor(s)

| <div style="width:250px">Name</div> | Description |
| ------------------------------------ | ------------------------------------------------------------------------ |
| `sensor.corolla` | Static data about your car. |
| `sensor.corolla_ev_battery_status` | EV battery information |
| `sensor.corolla_ev_remaining_charge` | EV battery remaining charge (in per cent of full capacity) |
| `sensor.corolla_fuel_tank` | Fuel tank information. |
| `sensor.corolla_hvac` | HVAC sensor showing current and target temperature, including other data |
| `sensor.corolla_odometer` | Odometer information. |
| `sensor.corolla_range` | Remaining range sensor |
| `sensor.aygo_starter_battery` | Starter battery health. |
| `sensor.corolla_current_week_stats` | Statistics for current week. |
| `sensor.corolla_current_month_stats` | Statistics for current month. |
| `sensor.corolla_current_year_stats` | Statistics for current year. |
| <div style="width:250px">Name</div> | Description |
| -------------------------------------------- | -------------------------------------------------- |
| `sensor.<you_car_alias>_vin` | Static data about your car. |
| `sensor.<you_car_alias>_odometer` | Odometer information. |
| `sensor.<you_car_alias>_fuel_level` | Fuel level information. |
| `sensor.<you_car_alias>_fuel_range` | Fuel range information. |
| `sensor.<you_car_alias>_battery_level` | Battery level information. |
| `sensor.<you_car_alias>_battery_range` | Battery range information. |
| `sensor.<you_car_alias>_battery_range_ac` | Battery range information when AC is on. |
| `sensor.<you_car_alias>_total_range` | Information about combined fuel and battery range. |
| `sensor.<you_car_alias>_current_day_stats` | Statistics for current day. |
| `sensor.<you_car_alias>_current_week_stats` | Statistics for current week. |
| `sensor.<you_car_alias>_current_month_stats` | Statistics for current month. |
| `sensor.<you_car_alias>_current_year_stats` | Statistics for current year. |

### Statistics sensors

Expand All @@ -83,34 +78,26 @@ Due to this, this integration will list sensors as unavailable when no data is a

**Disclaimer: Attributes available depends on your car model and year.**

All values will show zero if no data is available for the periode.

| Attribute | Description |
| ------------------------------------ | --------------------------------------------------------------------------------------------------- |
| `Highway_distance` | Distance driven on Highway/Motorway. |
| `Highway_percentage` | Percentage driven on Highway/Motorway. |
| `Number_of_trips` | Number of trips performed. A trip is started when you start the engine. |
| `Number_of_night_trips` | Number of trips performed at night. |
| `Total_driving_time` | Total time driven. |
| `Average_speed` | Average speed. |
| `Max_speed` | Max speed achieved. |
| `Hard_acceleration_count` | Hard accelerations counter. Can be very sensitive. |
| `Hard_braking_count` | Hard braking counter. Can be very sensitive. |
| `Average_fuel_consumed` | Average fuel consumed. If car is in km then this will show L/100km. If in mi then it will show Mpg. |
| `Coaching_advice_most_occurrence` | Coaching advice most occurrence. |
| `Average_driver_score` | Average driver score. |
| `Average_driver_score_accelerations` | Average driver score for accelerations. |
| `Average_driver_score_braking` | Average driver score for braking. |
| `EV_distance` | Distance which have been driven on electric. |
| `EV_distance_percentage` | Percentage of the distance driven on electric. |
| `EV_driving_time` | Driving time on electric. |
| `EV_duration_percentage` | Percentage of the driving time on electric. |
All values will show `None` if no data is available for the periode.

| Attribute | Description |
| ----------------------- | ------------------------------------------------------------------------------- |
| `Distance` | Distance driven (Displayed as sensor value). |
| `Average_speed` | The average speed in the respective period (can be km/h or mph). |
| `Countries` | The countries travelled through in the respective period. |
| `Duration` | The total driving time in the respective period. |
| `Total_fuel_consumed` | The total fuel consumption in the respective period (can be litres or gallons). |
| `Average_fuel_consumed` | The average fuel consumption in the respective period (can be l/100km or mpg). |
| `EV_distance` | The driving distiance in EV mode in the respective period . |
| `EV_duration` | The driving time in EV mode in the respective period . |
| `From_date` | Start date of the calculation period. |
| `To_date` | End date of the calculation period. |

## Getting started

### Prerequisites

Use Home Assistant build 2021.4 or above.
Use Home Assistant build 2023.12 or above.

If you can confirm that it is working as advertised on older version please open a PR.

Expand Down Expand Up @@ -138,16 +125,16 @@ Now you can clone the repository somewhere else and symlink it to Home Assistant

1. Clone the repo.

```shell
git clone https://github.com/DurgNomis-drol/ha_toyota.git
```
```shell
git clone https://github.com/DurgNomis-drol/ha_toyota.git
```

2. Create the symlink to `toyota` in the configuration directory.
If you have non-standard directory for configuration, use it instead.

```shell
ln -s ha_toyota/custom_components/toyota ~/.homeassistant/custom_components/toyota
```
```shell
ln -s ha_toyota/custom_components/toyota ~/.homeassistant/custom_components/toyota
```

#### Copy method

Expand Down
96 changes: 38 additions & 58 deletions custom_components/toyota/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,49 +5,40 @@
import asyncio.exceptions as asyncioexceptions
import logging
from datetime import timedelta
from typing import Any, Optional, TypedDict
from typing import Optional, TypedDict

import httpcore
import httpx
from homeassistant.config_entries import ConfigEntry
from homeassistant.const import (
CONF_EMAIL,
CONF_PASSWORD,
CONF_UNIT_SYSTEM_IMPERIAL,
CONF_UNIT_SYSTEM_METRIC,
)
from homeassistant.const import CONF_EMAIL, CONF_PASSWORD
from homeassistant.core import HomeAssistant
from homeassistant.exceptions import ConfigEntryAuthFailed, ConfigEntryNotReady
from homeassistant.helpers.update_coordinator import DataUpdateCoordinator, UpdateFailed
from mytoyota import MyT
from mytoyota.exceptions import ToyotaApiError, ToyotaInternalError, ToyotaLoginError
from mytoyota.models.summary import Summary
from mytoyota.models.vehicle import Vehicle

from .const import (
CONF_UNIT_SYSTEM_IMPERIAL_LITERS,
CONF_USE_LITERS_PER_100_MILES,
DOMAIN,
PLATFORMS,
STARTUP_MESSAGE,
)
from .const import CONF_METRIC_VALUES, DOMAIN, PLATFORMS, STARTUP_MESSAGE

_LOGGER = logging.getLogger(__name__)


class StatisticsData(TypedDict):
"""Representing Statistics data."""

day: list[dict[str, Any]]
week: list[dict[str, Any]]
month: list[dict[str, Any]]
year: list[dict[str, Any]]
day: Optional[Summary]
week: Optional[Summary]
month: Optional[Summary]
year: Optional[Summary]


class VehicleData(TypedDict):
"""Representing Vehicle data."""

data: Vehicle
statistics: Optional[StatisticsData]
metric_values: bool


async def async_setup_entry( # pylint: disable=too-many-statements
Expand All @@ -60,12 +51,11 @@ async def async_setup_entry( # pylint: disable=too-many-statements

email = entry.data[CONF_EMAIL]
password = entry.data[CONF_PASSWORD]
use_liters = entry.options.get(CONF_USE_LITERS_PER_100_MILES, False)
use_metric_values = entry.data[CONF_METRIC_VALUES]

client = MyT(
username=email,
password=password,
disable_locale_check=True,
)

try:
Expand All @@ -75,49 +65,38 @@ async def async_setup_entry( # pylint: disable=too-many-statements
except (httpx.ConnectTimeout, httpcore.ConnectTimeout) as ex:
raise ConfigEntryNotReady("Unable to connect to Toyota Connected Services") from ex

async def async_get_vehicle_data() -> list[VehicleData]:
async def async_get_vehicle_data() -> Optional[list[VehicleData]]:
"""Fetch vehicle data from Toyota API."""
try:
vehicles = await asyncio.wait_for(client.get_vehicles(), 15)
vehicles = await asyncio.wait_for(client.get_vehicles(metric=use_metric_values), 15)
vehicle_informations: list[VehicleData] = []
for vehicle in vehicles:
vehicle_status = await client.get_vehicle_status(vehicle)
_LOGGER.debug(vars(vehicle_status))

vehicle_data = VehicleData(data=vehicle_status, statistics=None)

unit_system_map = {
False: CONF_UNIT_SYSTEM_IMPERIAL,
True: CONF_UNIT_SYSTEM_IMPERIAL_LITERS,
}
unit = CONF_UNIT_SYSTEM_METRIC if vehicle_status.dashboard.is_metric else unit_system_map[use_liters]

_LOGGER.debug(f"The car is reporting data in {unit}")
if use_liters and not vehicle_status.dashboard.is_metric:
_LOGGER.debug("Getting statistics in imperial and L/100 miles")
elif not vehicle_status.dashboard.is_metric:
_LOGGER.debug("Getting statistics in imperial and MPG")

if vehicle_status.is_connected_services_enabled and vehicle_status.vin is not None:
# Use parallel request to get car statistics.
driving_statistics = await asyncio.gather(
client.get_driving_statistics(vehicle_status.vin, interval="day", unit=unit),
client.get_driving_statistics(vehicle_status.vin, interval="isoweek", unit=unit),
client.get_driving_statistics(vehicle_status.vin, unit=unit),
client.get_driving_statistics(vehicle_status.vin, interval="year", unit=unit),
if vehicles is not None:
for vehicle in vehicles:
await vehicle.update()
vehicle_data = VehicleData(
data=vehicle, statistics=None, metric_values=use_metric_values
)

vehicle_data["statistics"] = StatisticsData(
day=driving_statistics[0],
week=driving_statistics[1],
month=driving_statistics[2],
year=driving_statistics[3],
)
if vehicle.vin is not None:
# Use parallel request to get car statistics.
driving_statistics = await asyncio.gather(
vehicle.get_current_day_summary(),
vehicle.get_current_week_summary(),
vehicle.get_current_month_summary(),
vehicle.get_current_year_summary(),
)

vehicle_data["statistics"] = StatisticsData(
day=driving_statistics[0],
week=driving_statistics[1],
month=driving_statistics[2],
year=driving_statistics[3],
)

vehicle_informations.append(vehicle_data)
vehicle_informations.append(vehicle_data)

_LOGGER.debug(vehicle_informations)
return vehicle_informations
_LOGGER.debug(vehicle_informations)
return vehicle_informations

except ToyotaLoginError as ex:
_LOGGER.error(ex)
Expand All @@ -133,15 +112,16 @@ async def async_get_vehicle_data() -> list[VehicleData]:
httpx.ReadTimeout,
) as ex:
raise UpdateFailed(
"Update canceled! Toyota's API was too slow to respond." " Will try again later..."
"Update canceled! Toyota's API was too slow to respond. Will try again later..."
) from ex
return None

coordinator = DataUpdateCoordinator(
hass,
_LOGGER,
name=DOMAIN,
update_method=async_get_vehicle_data,
update_interval=timedelta(seconds=120),
update_interval=timedelta(seconds=360),
)

await coordinator.async_config_entry_first_refresh()
Expand Down
Loading