renault-api 0.6.1__tar.gz → 0.6.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. {renault_api-0.6.1 → renault_api-0.6.2}/PKG-INFO +1 -1
  2. {renault_api-0.6.1 → renault_api-0.6.2}/pyproject.toml +8 -8
  3. {renault_api-0.6.1 → renault_api-0.6.2}/pyproject.toml.orig +8 -8
  4. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/kamereon/exceptions.py +6 -0
  5. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/kamereon/models.py +51 -3
  6. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/models.py +1 -1
  7. {renault_api-0.6.1 → renault_api-0.6.2}/LICENSE.rst +0 -0
  8. {renault_api-0.6.1 → renault_api-0.6.2}/README.rst +0 -0
  9. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/__init__.py +0 -0
  10. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/__init__.py +0 -0
  11. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/__main__.py +0 -0
  12. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/charge/__init__.py +0 -0
  13. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/charge/commands.py +0 -0
  14. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/charge/control.py +0 -0
  15. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/charge/history.py +0 -0
  16. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/charge/schedule.py +0 -0
  17. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/charge/soc_levels.py +0 -0
  18. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/helpers.py +0 -0
  19. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/hvac/__init__.py +0 -0
  20. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/hvac/commands.py +0 -0
  21. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/hvac/control.py +0 -0
  22. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/hvac/history.py +0 -0
  23. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/renault_account.py +0 -0
  24. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/renault_client.py +0 -0
  25. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/renault_settings.py +0 -0
  26. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/cli/renault_vehicle.py +0 -0
  27. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/const.py +0 -0
  28. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/credential.py +0 -0
  29. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/credential_store.py +0 -0
  30. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/exceptions.py +0 -0
  31. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/gigya/__init__.py +0 -0
  32. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/gigya/enums.py +0 -0
  33. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/gigya/exceptions.py +0 -0
  34. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/gigya/models.py +0 -0
  35. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/gigya/schemas.py +0 -0
  36. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/helpers.py +0 -0
  37. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/kamereon/__init__.py +0 -0
  38. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/kamereon/enums.py +0 -0
  39. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/kamereon/helpers.py +0 -0
  40. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/kamereon/schemas.py +0 -0
  41. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/py.typed +0 -0
  42. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/renault_account.py +0 -0
  43. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/renault_client.py +0 -0
  44. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/renault_session.py +0 -0
  45. {renault_api-0.6.1 → renault_api-0.6.2}/src/renault_api/renault_vehicle.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: renault-api
3
- Version: 0.6.1
3
+ Version: 0.6.2
4
4
  Summary: Renault API
5
5
  Author: epenet
6
6
  License-Expression: MIT
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "renault-api"
3
- version = "0.6.1"
3
+ version = "0.6.2"
4
4
  description = "Renault API"
5
5
  license = "MIT"
6
6
  license-files = ["LICENSE.rst"]
@@ -43,22 +43,22 @@ dev = [
43
43
  "aiointercept==1.0.0",
44
44
  "codespell==2.4.3",
45
45
  "covdefaults==2.3.0",
46
- "coverage[toml]==7.16.2",
46
+ "coverage[toml]==7.17.0",
47
47
  "pre-commit-hooks==6.0.0",
48
- "prek==0.5.5",
48
+ "prek==0.5.7",
49
49
  "pytest==9.1.1",
50
- "pytest-asyncio==1.4.0",
50
+ "pytest-asyncio==1.4.1",
51
51
  "pytest-cov==7.1.0",
52
- "ruff==0.17.0",
52
+ "ruff==0.17.2",
53
53
  "syrupy==6.1.1",
54
- "ty==0.0.85",
54
+ "ty==0.0.92",
55
55
  "yamllint==1.38.0",
56
- "zizmor==1.30.1",
56
+ "zizmor==1.31.1",
57
57
  ]
58
58
  docs = [
59
59
  "furo==2025.12.19; python_version >= '3.14'",
60
60
  "myst-parser==5.1.0; python_version >= '3.14'",
61
- "sphinx==9.1.0; python_version >= '3.14'",
61
+ "sphinx==9.2.0; python_version >= '3.14'",
62
62
  "sphinx-autobuild==2025.8.25; python_version >= '3.14'",
63
63
  "sphinx-click==6.2.0; python_version >= '3.14'",
64
64
  ]
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "renault-api"
3
- version = "0.6.1"
3
+ version = "0.6.2"
4
4
  description = "Renault API"
5
5
  authors = [{ name = "epenet" }]
6
6
  license = "MIT"
@@ -43,23 +43,23 @@ dev = [
43
43
  "aiointercept==1.0.0",
44
44
  "codespell==2.4.3",
45
45
  "covdefaults==2.3.0",
46
- "coverage[toml]==7.16.2",
46
+ "coverage[toml]==7.17.0",
47
47
  "pre-commit-hooks==6.0.0",
48
- "prek==0.5.5",
48
+ "prek==0.5.7",
49
49
  "pytest==9.1.1",
50
- "pytest-asyncio==1.4.0",
50
+ "pytest-asyncio==1.4.1",
51
51
  "pytest-cov==7.1.0",
52
- "ruff==0.17.0",
52
+ "ruff==0.17.2",
53
53
  "syrupy==6.1.1",
54
- "ty==0.0.85",
54
+ "ty==0.0.92",
55
55
  "yamllint==1.38.0",
56
- "zizmor==1.30.1",
56
+ "zizmor==1.31.1",
57
57
  ]
58
58
  # docs (Python >= 3.14)
59
59
  docs = [
60
60
  "furo==2025.12.19; python_version >= '3.14'",
61
61
  "myst-parser==5.1.0; python_version >= '3.14'",
62
- "sphinx==9.1.0; python_version >= '3.14'",
62
+ "sphinx==9.2.0; python_version >= '3.14'",
63
63
  "sphinx-autobuild==2025.8.25; python_version >= '3.14'",
64
64
  "sphinx-click==6.2.0; python_version >= '3.14'",
65
65
  ]
@@ -82,3 +82,9 @@ class ForbiddenException(KamereonResponseException):
82
82
  """The access is forbidden."""
83
83
 
84
84
  pass
85
+
86
+
87
+ class InsufficientBatteryLevelException(KamereonResponseException):
88
+ """The battery level is too low to perform this action."""
89
+
90
+ pass
@@ -63,6 +63,10 @@ COMMON_ERRRORS: list[dict[str, Any]] = [
63
63
  "errorCode": "409001",
64
64
  "error_type": exceptions.ChargeModeInProgressException,
65
65
  },
66
+ {
67
+ "errorCode": "err.func.wired.low.battery.level",
68
+ "error_type": exceptions.InsufficientBatteryLevelException,
69
+ },
66
70
  ]
67
71
 
68
72
  VEHICLE_SPECIFICATIONS: dict[str, dict[str, Any]] = {
@@ -390,6 +394,34 @@ _VEHICLE_ENDPOINTS: dict[str, dict[str, EndpointDefinition | None]] = {
390
394
  "res-state": None, # Reason: "err.func.wired.notFound"
391
395
  "soc-levels": None, # Reason: "err.func.wired.forbidden"
392
396
  },
397
+ "XBG2VE": { # DACIA SPRING MY25
398
+ "actions/charge-start": _KCM_ENDPOINTS["actions/charge-start-via-settings"],
399
+ "actions/charge-stop": None, # Reason: "err.func.wired.forbidden" (kcm pause-resume) / "err.func.wired.invalid-body-format" (default) # noqa: E501
400
+ "actions/horn-start": _DEFAULT_ENDPOINTS["actions/horn-start"],
401
+ "actions/hvac-start": _DEFAULT_ENDPOINTS["actions/hvac-start"],
402
+ # hvac-stop: "cancel" is accepted (200) but has no effect, "stop" works
403
+ "actions/hvac-stop": _KCA_ALTERNATIVE_ENDPOINTS["actions/hvac-stop"],
404
+ "actions/lights-start": _DEFAULT_ENDPOINTS["actions/lights-start"],
405
+ "actions/refresh-location": _DEFAULT_ENDPOINTS["actions/refresh-location"],
406
+ "alerts": None, # Reason: "err.func.wired.not-found"
407
+ "battery-status": _DEFAULT_ENDPOINTS["battery-status"],
408
+ "charge-history": None, # Reason: "err.func.wired.not-found"
409
+ "charge-mode": None, # Reason: "err.func.wired.forbidden"
410
+ "charge-schedule": _KCM_ENDPOINTS["charge-schedule-via-settings"],
411
+ "charges": _DEFAULT_ENDPOINTS["charges"],
412
+ "charging-settings": None, # Reason: "err.func.wired.forbidden"
413
+ "cockpit": _DEFAULT_ENDPOINTS["cockpit"],
414
+ "hvac-history": None, # Reason: "err.func.wired.not-found"
415
+ "hvac-sessions": None, # Reason: "err.func.wired.not-found"
416
+ "hvac-settings": _DEFAULT_ENDPOINTS["hvac-settings"],
417
+ "hvac-status": _DEFAULT_ENDPOINTS["hvac-status"],
418
+ "location": _DEFAULT_ENDPOINTS["location"],
419
+ "lock-status": None, # Reason: "There is no data for this vin and uid" (404)
420
+ "notification-settings": None, # Reason: "The vehicle does not have a GDC gateway" (400001) # noqa: E501
421
+ "pressure": None, # Reason: "There is no data for this vin and uid" (404)
422
+ "res-state": None, # Reason: "There is no data for this vin and uid" (404)
423
+ "soc-levels": _DEFAULT_ENDPOINTS["soc-levels"],
424
+ },
393
425
  "XCB1SE": { # SCENIC E-TECH
394
426
  "actions/charge-start": _KCM_ENDPOINTS["actions/charge-start-via-settings"],
395
427
  "actions/charge-stop": None, # Reason: "err.func.wired.forbidden" (kcm pause-resume) / "err.func.wired.invalid-body-format" (default) # noqa: E501
@@ -552,11 +584,11 @@ _VEHICLE_ENDPOINTS: dict[str, dict[str, EndpointDefinition | None]] = {
552
584
  "charge-mode": None, # Reason: "err.func.wired.forbidden"
553
585
  "charging-settings": None, # Reason: "err.func.wired.forbidden"
554
586
  "cockpit": _DEFAULT_ENDPOINTS["cockpit"], # confirmed
555
- "hvac-status": None,
587
+ "hvac-status": None, # Reason: "err.func.wired.notFound"
556
588
  "location": _DEFAULT_ENDPOINTS["location"],
557
- "lock-status": None,
589
+ "lock-status": _DEFAULT_ENDPOINTS["lock-status"], # confirmed
558
590
  "pressure": None, # Reason: 404
559
- "res-state": None,
591
+ "res-state": None, # Reason: "err.func.wired.notFound"
560
592
  "soc-levels": None, # Reason: "err.func.wired.forbidden"
561
593
  },
562
594
  "XJA1VP": { # CLIO V
@@ -1160,6 +1192,16 @@ class KamereonVehicleCockpitData(KamereonVehicleDataAttributes):
1160
1192
  totalMileage: float | None
1161
1193
 
1162
1194
 
1195
+ # Some vehicles (eg. XJB2SU, XHN1SU) report the door statuses as statusDoor*
1196
+ _LOCK_STATUS_ALIASES = {
1197
+ "doorStatusRearLeft": "statusDoorRearLeft",
1198
+ "doorStatusRearRight": "statusDoorRearRight",
1199
+ "doorStatusDriver": "statusDoorDriver",
1200
+ "doorStatusPassenger": "statusDoorPassenger",
1201
+ "hatchStatus": "statusDoorTailGate",
1202
+ }
1203
+
1204
+
1163
1205
  @dataclass
1164
1206
  class KamereonVehicleLockStatusData(KamereonVehicleDataAttributes):
1165
1207
  """Kamereon vehicle data lock-status attributes."""
@@ -1172,6 +1214,12 @@ class KamereonVehicleLockStatusData(KamereonVehicleDataAttributes):
1172
1214
  hatchStatus: str | None
1173
1215
  lastUpdateTime: str | None
1174
1216
 
1217
+ def __post_init__(self) -> None:
1218
+ """Fall back to the statusDoor* attributes used by newer vehicles."""
1219
+ for field, alias in _LOCK_STATUS_ALIASES.items():
1220
+ if getattr(self, field) is None:
1221
+ setattr(self, field, self.raw_data.get(alias))
1222
+
1175
1223
 
1176
1224
  @dataclass
1177
1225
  class KamereonVehicleResStateData(KamereonVehicleDataAttributes):
@@ -16,7 +16,7 @@ class BaseModel:
16
16
  class BaseSchema(marshmallow.Schema):
17
17
  """Base schema for Gigya and Kamereon models to exclude unknown fields."""
18
18
 
19
- class Meta:
19
+ class Meta: # ty: ignore[invalid-attribute-override] # astral-sh/ty#4711
20
20
  """Force unknown fields to 'exclude'."""
21
21
 
22
22
  unknown = marshmallow.EXCLUDE
File without changes
File without changes