Skip to content

Commit

Permalink
Add new endpoint for tyre pressure (#1411)
Browse files Browse the repository at this point in the history
* feat: Type pressure

* Lint

* Fix tests

* One more

---------

Co-authored-by: epenet <[email protected]>
  • Loading branch information
kelyaenn and epenet authored Jan 6, 2025
1 parent 22e4b13 commit 0c9589d
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 63 deletions.
30 changes: 30 additions & 0 deletions src/renault_api/cli/renault_vehicle.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ async def display_status(
await update_lock_status(vehicle, status_table, ctx_data)
await update_res_state(vehicle, status_table, ctx_data)
await update_hvac_status(vehicle, status_table, ctx_data)
await update_tyre_pressure(vehicle, status_table, ctx_data)
if ctx_data["json"]:
click.echo(json.dumps(status_table))
return
Expand Down Expand Up @@ -222,6 +223,35 @@ async def update_battery_status(
update_status_table(status_table, key, value, unit)


async def update_tyre_pressure(
vehicle: RenaultVehicle, status_table: Dict[str, Any], ctx_data: Dict[str, Any]
) -> None:
"""Update status table from get_tyre_pressure."""
try:
if not await vehicle.supports_endpoint("pressure"): # pragma: no cover
return
response = await vehicle.get_tyre_pressure()
except QuotaLimitException as exc: # pragma: no cover
raise click.ClickException(repr(exc)) from exc
except KamereonResponseException as exc: # pragma: no cover
click.echo(f"pressure: {exc.error_details}", err=True)
return

if ctx_data["json"]:
status_table["pressure"] = response.raw_data
return

items = [
("Front left pressure", response.flPressure, "bar"),
("Front right pressure", response.frPressure, "bar"),
("Rear left pressure", response.rlPressure, "bar"),
("Rear right pressure", response.rrPressure, "bar"),
]

for key, value, unit in items:
update_status_table(status_table, key, value, unit)


async def update_charge_mode(
vehicle: RenaultVehicle, status_table: Dict[str, Any], ctx_data: Dict[str, Any]
) -> None:
Expand Down
1 change: 1 addition & 0 deletions src/renault_api/kamereon/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"location": {"version": 1},
"lock-status": {"version": 1},
"notification-settings": {"version": 1},
"pressure": {"version": 1},
"res-state": {"version": 1},
}
_KCA_POST_ENDPOINTS: Dict[str, Any] = {
Expand Down
14 changes: 14 additions & 0 deletions src/renault_api/kamereon/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,20 @@ def get_charging_status(self) -> Optional[enums.ChargeState]:
) from err


@dataclass
class KamereonVehicleTyrePressureData(KamereonVehicleDataAttributes):
"""Kamereon vehicle tyre-pressure data."""

flPressure: Optional[int]
frPressure: Optional[int]
rlPressure: Optional[int]
rrPressure: Optional[int]
flStatus: Optional[int]
frStatus: Optional[int]
rlStatus: Optional[int]
rrStatus: Optional[int]


@dataclass
class KamereonVehicleLocationData(KamereonVehicleDataAttributes):
"""Kamereon vehicle data location attributes."""
Expand Down
3 changes: 3 additions & 0 deletions src/renault_api/kamereon/schemas.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
models.KamereonVehicleBatteryStatusData, base_schema=BaseSchema
)()

KamereonVehicleTyrePressureDataSchema = marshmallow_dataclass.class_schema(
models.KamereonVehicleTyrePressureData, base_schema=BaseSchema
)()

KamereonVehicleLocationDataSchema = marshmallow_dataclass.class_schema(
models.KamereonVehicleLocationData, base_schema=BaseSchema
Expand Down
12 changes: 12 additions & 0 deletions src/renault_api/renault_vehicle.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,18 @@ async def get_battery_status(self) -> models.KamereonVehicleBatteryStatusData:
response.get_attributes(schemas.KamereonVehicleBatteryStatusDataSchema),
)

async def get_tyre_pressure(self) -> models.KamereonVehicleTyrePressureData:
"""Get vehicle tyre pressure."""
response = await self.session.get_vehicle_data(
account_id=self.account_id,
vin=self.vin,
endpoint="pressure",
)
return cast(
models.KamereonVehicleTyrePressureData,
response.get_attributes(schemas.KamereonVehicleTyrePressureDataSchema),
)

async def get_location(self) -> models.KamereonVehicleLocationData:
"""Get vehicle location."""
response = await self.session.get_vehicle_data(
Expand Down
154 changes: 91 additions & 63 deletions tests/cli/test_vehicle.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,54 +35,66 @@

EXPECTED_STATUS = {
"captur_ii.1.json": (
"----------------- ----------------------\n"
"Total mileage 5566.78 km\n"
"Fuel autonomy 35.0 km\n"
"Fuel quantity 3.0 L\n"
"GPS Latitude 48.1234567\n"
"GPS Longitude 11.1234567\n"
"GPS last updated 2020-02-18 17:58:38\n"
"Lock status locked\n"
"Lock last updated 2022-02-02 14:51:13\n"
"Engine state Stopped, ready for RES\n"
"----------------- ----------------------\n"
"-------------------- ----------------------\n"
"Total mileage 5566.78 km\n"
"Fuel autonomy 35.0 km\n"
"Fuel quantity 3.0 L\n"
"GPS Latitude 48.1234567\n"
"GPS Longitude 11.1234567\n"
"GPS last updated 2020-02-18 17:58:38\n"
"Lock status locked\n"
"Lock last updated 2022-02-02 14:51:13\n"
"Engine state Stopped, ready for RES\n"
"Front left pressure 2460 bar\n"
"Front right pressure 2730 bar\n"
"Rear left pressure 2790 bar\n"
"Rear right pressure 2790 bar\n"
"-------------------- ----------------------\n"
),
"captur_ii.2.json": (
"----------------- -------------------------\n"
"Battery level 50 %\n"
"Last updated 2020-11-17 09:06:48\n"
"Range estimate 128 km\n"
"Plug state PlugState.UNPLUGGED\n"
"Charging state ChargeState.NOT_IN_CHARGE\n"
"Charge mode always\n"
"Total mileage 5566.78 km\n"
"Fuel autonomy 35.0 km\n"
"Fuel quantity 3.0 L\n"
"GPS Latitude 48.1234567\n"
"GPS Longitude 11.1234567\n"
"GPS last updated 2020-02-18 17:58:38\n"
"Lock status locked\n"
"Lock last updated 2022-02-02 14:51:13\n"
"Engine state Stopped, ready for RES\n"
"----------------- -------------------------\n"
"-------------------- -------------------------\n"
"Battery level 50 %\n"
"Last updated 2020-11-17 09:06:48\n"
"Range estimate 128 km\n"
"Plug state PlugState.UNPLUGGED\n"
"Charging state ChargeState.NOT_IN_CHARGE\n"
"Charge mode always\n"
"Total mileage 5566.78 km\n"
"Fuel autonomy 35.0 km\n"
"Fuel quantity 3.0 L\n"
"GPS Latitude 48.1234567\n"
"GPS Longitude 11.1234567\n"
"GPS last updated 2020-02-18 17:58:38\n"
"Lock status locked\n"
"Lock last updated 2022-02-02 14:51:13\n"
"Engine state Stopped, ready for RES\n"
"Front left pressure 2460 bar\n"
"Front right pressure 2730 bar\n"
"Rear left pressure 2790 bar\n"
"Rear right pressure 2790 bar\n"
"-------------------- -------------------------\n"
),
"twingo_ze.1.json": (
"----------------- -------------------------\n"
"Battery level 50 %\n"
"Last updated 2020-11-17 09:06:48\n"
"Range estimate 128 km\n"
"Plug state PlugState.UNPLUGGED\n"
"Charging state ChargeState.NOT_IN_CHARGE\n"
"Charge mode always\n"
"Total mileage 49114.27 km\n"
"GPS Latitude 48.1234567\n"
"GPS Longitude 11.1234567\n"
"GPS last updated 2020-02-18 17:58:38\n"
"Lock status locked\n"
"Lock last updated 2022-02-02 14:51:13\n"
"Engine state Stopped, ready for RES\n"
"HVAC status on\n"
"----------------- -------------------------\n"
"-------------------- -------------------------\n"
"Battery level 50 %\n"
"Last updated 2020-11-17 09:06:48\n"
"Range estimate 128 km\n"
"Plug state PlugState.UNPLUGGED\n"
"Charging state ChargeState.NOT_IN_CHARGE\n"
"Charge mode always\n"
"Total mileage 49114.27 km\n"
"GPS Latitude 48.1234567\n"
"GPS Longitude 11.1234567\n"
"GPS last updated 2020-02-18 17:58:38\n"
"Lock status locked\n"
"Lock last updated 2022-02-02 14:51:13\n"
"Engine state Stopped, ready for RES\n"
"HVAC status on\n"
"Front left pressure 2460 bar\n"
"Front right pressure 2730 bar\n"
"Rear left pressure 2790 bar\n"
"Rear right pressure 2790 bar\n"
"-------------------- -------------------------\n"
),
"zoe_40.1.json": (
"-------------------- -------------------------\n"
Expand All @@ -96,6 +108,10 @@
"Engine state Stopped, ready for RES\n"
"HVAC status off\n"
"External temperature 8.0 °C\n"
"Front left pressure 2460 bar\n"
"Front right pressure 2730 bar\n"
"Rear left pressure 2790 bar\n"
"Rear right pressure 2790 bar\n"
"-------------------- -------------------------\n"
),
"zoe_40.2.json": (
Expand All @@ -110,27 +126,35 @@
"Engine state Stopped, ready for RES\n"
"HVAC status off\n"
"External temperature 8.0 °C\n"
"Front left pressure 2460 bar\n"
"Front right pressure 2730 bar\n"
"Rear left pressure 2790 bar\n"
"Rear right pressure 2790 bar\n"
"-------------------- -------------------------\n"
),
"zoe_50.1.json": (
"----------------- -------------------------\n"
"Battery level 50 %\n"
"Last updated 2020-11-17 09:06:48\n"
"Range estimate 128 km\n"
"Plug state PlugState.UNPLUGGED\n"
"Charging state ChargeState.NOT_IN_CHARGE\n"
"Charge mode always\n"
"Total mileage 5785.75 km\n"
"Fuel autonomy 0.0 km\n"
"Fuel quantity 0.0 L\n"
"GPS Latitude 48.1234567\n"
"GPS Longitude 11.1234567\n"
"GPS last updated 2020-02-18 17:58:38\n"
"Lock status locked\n"
"Lock last updated 2022-02-02 14:51:13\n"
"Engine state Stopped, ready for RES\n"
"HVAC status on\n"
"----------------- -------------------------\n"
"-------------------- -------------------------\n"
"Battery level 50 %\n"
"Last updated 2020-11-17 09:06:48\n"
"Range estimate 128 km\n"
"Plug state PlugState.UNPLUGGED\n"
"Charging state ChargeState.NOT_IN_CHARGE\n"
"Charge mode always\n"
"Total mileage 5785.75 km\n"
"Fuel autonomy 0.0 km\n"
"Fuel quantity 0.0 L\n"
"GPS Latitude 48.1234567\n"
"GPS Longitude 11.1234567\n"
"GPS last updated 2020-02-18 17:58:38\n"
"Lock status locked\n"
"Lock last updated 2022-02-02 14:51:13\n"
"Engine state Stopped, ready for RES\n"
"HVAC status on\n"
"Front left pressure 2460 bar\n"
"Front right pressure 2730 bar\n"
"Rear left pressure 2790 bar\n"
"Rear right pressure 2790 bar\n"
"-------------------- -------------------------\n"
),
"zoe_40.1_json.json": (
'{"battery-status": {"timestamp": "2020-11-17T09:06:48+01:00", '
Expand All @@ -139,7 +163,11 @@
'"charge-mode": {"chargeMode": "always"}, '
'"cockpit": {"totalMileage": 49114.27}, '
'"res-state": {"details": "Stopped, ready for RES", "code": "10"}, '
'"hvac-status": {"externalTemperature": 8.0, "hvacStatus": "off"}}\n'
'"hvac-status": {"externalTemperature": 8.0, "hvacStatus": "off"}, '
'"pressure": {"flPressure": 2460, "frPressure": 2730, '
'"rlPressure": 2790, "rrPressure": 2790, '
'"flStatus": 0, "frStatus": 0, '
'"rlStatus": 0, "rrStatus": 0}}\n'
),
}

Expand Down
13 changes: 13 additions & 0 deletions tests/fixtures.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,6 +277,18 @@ def inject_get_battery_status(
)


def inject_get_tyre_pressure(
mocked_responses: aioresponses, filename: str = "vehicle_data/tyre-pressure.json"
) -> str:
"""Inject sample tyre-pressure."""
urlpath = f"{ADAPTER_PATH}/pressure?{DEFAULT_QUERY_STRING}"
return inject_data(
mocked_responses,
urlpath,
filename,
)


def inject_get_location(mocked_responses: aioresponses) -> str:
"""Inject sample location."""
urlpath = f"{ADAPTER_PATH}/location?{DEFAULT_QUERY_STRING}"
Expand Down Expand Up @@ -501,6 +513,7 @@ def inject_vehicle_status(mocked_responses: aioresponses, vehicle: str) -> None:
inject_get_hvac_status(mocked_responses, vehicle)
inject_get_charge_mode(mocked_responses)
inject_get_cockpit(mocked_responses, vehicle)
inject_get_tyre_pressure(mocked_responses)


def ensure_redacted(data: Mapping[str, Any], to_redact: list[str] = TO_REDACT) -> None:
Expand Down
16 changes: 16 additions & 0 deletions tests/fixtures/kamereon/vehicle_data/tyre-pressure.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
{
"data": {
"type": "Car",
"id": "VF1AAAAA555777999",
"attributes": {
"flPressure": 2460,
"frPressure": 2730,
"rlPressure": 2790,
"rrPressure": 2790,
"flStatus": 0,
"frStatus": 0,
"rlStatus": 0,
"rrStatus": 0
}
}
}
20 changes: 20 additions & 0 deletions tests/kamereon/test_kamereon_vehicle_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,26 @@ def test_battery_status_2() -> None:
assert vehicle_data.get_charging_status() == enums.ChargeState.CHARGE_IN_PROGRESS


def test_tyre_pressure() -> None:
"""Test vehicle data for tyre-pressure.json."""
response: models.KamereonVehicleDataResponse = fixtures.get_file_content_as_schema(
f"{fixtures.KAMEREON_FIXTURE_PATH}/vehicle_data/tyre-pressure.json",
schemas.KamereonVehicleDataResponseSchema,
)
response.raise_for_error_code()
assert response.data is not None
assert response.data.raw_data["attributes"] == {
"flPressure": 2460,
"frPressure": 2730,
"rlPressure": 2790,
"rrPressure": 2790,
"flStatus": 0,
"frStatus": 0,
"rlStatus": 0,
"rrStatus": 0,
}


def test_cockpit_zoe() -> None:
"""Test vehicle data for cockpit.zoe.json."""
response: models.KamereonVehicleDataResponse = fixtures.get_file_content_as_schema(
Expand Down
9 changes: 9 additions & 0 deletions tests/test_renault_vehicle.py
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,15 @@ async def test_get_battery_status(
assert await vehicle.get_battery_status()


@pytest.mark.asyncio
async def test_get_tyre_pressure(
vehicle: RenaultVehicle, mocked_responses: aioresponses
) -> None:
"""Test get_tyre_pressure."""
fixtures.inject_get_tyre_pressure(mocked_responses)
assert await vehicle.get_tyre_pressure()


@pytest.mark.asyncio
async def test_get_location(
vehicle: RenaultVehicle, mocked_responses: aioresponses
Expand Down

0 comments on commit 0c9589d

Please sign in to comment.