-
Notifications
You must be signed in to change notification settings - Fork 40
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
Add Dacia Spring Support #459
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
charge/pause-resume | ||
'''''''''''''''''''''' | ||
|
||
.. rst-class:: endpoint | ||
|
||
Base url: | ||
``/commerce/v1/accounts/{account_id}/kamereon/kcm/v1/vehicles/{vin}/charge/pause-resume`` | ||
|
||
Sample return: | ||
.. literalinclude:: /../tests/fixtures/kamereon/vehicle_action/charge-pause-resume.resume.json | ||
:language: JSON | ||
|
||
.. literalinclude:: /../tests/fixtures/kamereon/vehicle_action/charge-pause-resume.pause.json | ||
:language: JSON |
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -47,5 +47,31 @@ async def start( | |||||||||||||||||||||
vehicle = await renault_vehicle.get_vehicle( | ||||||||||||||||||||||
websession=websession, ctx_data=ctx_data | ||||||||||||||||||||||
) | ||||||||||||||||||||||
response = await vehicle.set_charge_start() | ||||||||||||||||||||||
details = await vehicle.get_details() | ||||||||||||||||||||||
if details.get_model_code() == "XBG1VE": | ||||||||||||||||||||||
response = await vehicle.set_charge_pause_resume("resume") | ||||||||||||||||||||||
else: | ||||||||||||||||||||||
response = await vehicle.set_charge_start() | ||||||||||||||||||||||
click.echo(response.raw_data) | ||||||||||||||||||||||
|
||||||||||||||||||||||
|
||||||||||||||||||||||
@click.command() | ||||||||||||||||||||||
@click.pass_obj | ||||||||||||||||||||||
@helpers.coro_with_websession | ||||||||||||||||||||||
async def stop( | ||||||||||||||||||||||
ctx_data: Dict[str, Any], | ||||||||||||||||||||||
*, | ||||||||||||||||||||||
websession: aiohttp.ClientSession, | ||||||||||||||||||||||
) -> None: | ||||||||||||||||||||||
"""Stop charge.""" | ||||||||||||||||||||||
vehicle = await renault_vehicle.get_vehicle( | ||||||||||||||||||||||
websession=websession, ctx_data=ctx_data | ||||||||||||||||||||||
) | ||||||||||||||||||||||
details = await vehicle.get_details() | ||||||||||||||||||||||
if details.get_model_code() == "XBG1VE": | ||||||||||||||||||||||
response = await vehicle.set_charge_pause_resume("pause") | ||||||||||||||||||||||
click.echo(response.raw_data) | ||||||||||||||||||||||
else: | ||||||||||||||||||||||
response = None | ||||||||||||||||||||||
click.echo("Function unavailable") | ||||||||||||||||||||||
exit(1) | ||||||||||||||||||||||
Comment on lines
+70
to
+77
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it is better to simply create a new function against the vehicle, and make the check there (you can raise NotImplementedException for the other vehicles)
Suggested change
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,7 @@ | |
"charging-start": {"version": 1, "type": "ChargingStart"}, | ||
"hvac-schedule": {"version": 2, "type": "HvacSchedule"}, | ||
"hvac-start": {"version": 1, "type": "HvacStart"}, | ||
"pause-resume": {"version": 1, "type": "ChargePauseResume"}, | ||
} | ||
|
||
|
||
|
@@ -62,6 +63,14 @@ def get_car_adapter_url(root_url: str, account_id: str, version: int, vin: str) | |
return f"{account_url}/kamereon/kca/car-adapter/v{version}/cars/{vin}" | ||
|
||
|
||
def get_kcm_car_adapter_url( | ||
root_url: str, account_id: str, version: int, vin: str | ||
) -> str: | ||
"""Get the url to the kcm car adapter.""" | ||
account_url = get_account_url(root_url, account_id) | ||
return f"{account_url}/kamereon/kcm/v{version}/vehicles/{vin}" | ||
|
||
|
||
def get_contracts_url(root_url: str, account_id: str, vin: str) -> str: | ||
"""Get the url to the car contracts.""" | ||
account_url = get_account_url(root_url, account_id) | ||
|
@@ -311,17 +320,28 @@ async def set_vehicle_action( | |
vin: str, | ||
endpoint: str, | ||
attributes: Dict[str, Any], | ||
actions: str = "actions", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you add an argument in the middle of the list, it becomes a breaking change. I suggest: attributes: Dict[str, Any],
endpoint_version: Optional[int] = None,
data_type: Optional[Dict[str, Any]] = None,
*,
car_adapter_type: str = "kca"
actions: str = "actions", |
||
endpoint_version: Optional[int] = None, | ||
data_type: Optional[Dict[str, Any]] = None, | ||
) -> models.KamereonVehicleDataResponse: | ||
"""POST to /v{endpoint_version}/cars/{vin}/actions/{endpoint}.""" | ||
"""POST to /v{endpoint_version}/cars/{vin}/{actions}/{endpoint}.""" | ||
car_adapter_url = get_car_adapter_url( | ||
root_url=root_url, | ||
account_id=account_id, | ||
version=endpoint_version or _get_endpoint_version(ACTION_ENDPOINTS[endpoint]), | ||
vin=vin, | ||
) | ||
url = f"{car_adapter_url}/actions/{endpoint}" | ||
|
||
if actions == "charge": | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it would be better to use a separate (new) argument to decide on the car_adapter_url: if car_adapter_type == "kcm":
car_adapter_url = get_kcm_car_adapter_url(...
else:
car_adapter_url = get_car_adapter_url(... |
||
car_adapter_url = get_kcm_car_adapter_url( | ||
root_url=root_url, | ||
account_id=account_id, | ||
version=endpoint_version | ||
or _get_endpoint_version(ACTION_ENDPOINTS[endpoint]), | ||
vin=vin, | ||
) | ||
|
||
url = f"{car_adapter_url}/{actions}/{endpoint}" | ||
params = {"country": country} | ||
json = { | ||
"data": { | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -62,6 +62,7 @@ | |||||
}, | ||||||
"XBG1VE": { # DACIA SPRING | ||||||
"support-endpoint-hvac-status": True, | ||||||
"pause-resume-via-kcm": True, # Pause/Resume is for charging actions | ||||||
}, | ||||||
} | ||||||
|
||||||
|
@@ -219,6 +220,15 @@ def warns_on_method(self, method: str) -> Optional[str]: | |||||
) | ||||||
return None # pragma: no cover | ||||||
|
||||||
def uses_endpoint_via_kcm(self, endpoint: str) -> bool: | ||||||
"""Return True if model uses endpoint via kcm.""" | ||||||
# Default to False for unknown vehicles | ||||||
if self.model and self.model.code: | ||||||
return VEHICLE_SPECIFICATIONS.get(self.model.code, {}).get( | ||||||
f"{endpoint}-via-kcm", False | ||||||
) | ||||||
return False # pragma: no cover | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think you are adding tests for this, so no need to exclude coverage:
Suggested change
|
||||||
|
||||||
|
||||||
@dataclass | ||||||
class KamereonVehiclesLink(BaseModel): | ||||||
|
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -489,13 +489,30 @@ async def set_charge_mode( | |||||||||
async def set_charge_start(self) -> models.KamereonVehicleChargingStartActionData: | ||||||||||
"""Start vehicle charge.""" | ||||||||||
# await self.warn_on_method("set_charge_start") | ||||||||||
attributes = {"action": "start"} | ||||||||||
|
||||||||||
response = await self.session.set_vehicle_action( | ||||||||||
account_id=self.account_id, | ||||||||||
vin=self.vin, | ||||||||||
endpoint="charging-start", | ||||||||||
attributes=attributes, | ||||||||||
attributes={"action": "start"}, | ||||||||||
) | ||||||||||
return cast( | ||||||||||
models.KamereonVehicleChargingStartActionData, | ||||||||||
response.get_attributes( | ||||||||||
schemas.KamereonVehicleChargingStartActionDataSchema | ||||||||||
), | ||||||||||
) | ||||||||||
|
||||||||||
async def set_charge_pause_resume( | ||||||||||
self, action: str | ||||||||||
) -> models.KamereonVehicleChargingStartActionData: | ||||||||||
Comment on lines
+505
to
+507
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please rename to set_charge_stop. Then inside the function you check if
Suggested change
You can do the same in set_charge_start, which should check if |
||||||||||
"""Start vehicle charge.""" | ||||||||||
# await self.warn_on_method("set_charge_start") | ||||||||||
response = await self.session.set_vehicle_action( | ||||||||||
account_id=self.account_id, | ||||||||||
vin=self.vin, | ||||||||||
endpoint="pause-resume", | ||||||||||
attributes={"action": action}, | ||||||||||
actions="charge", | ||||||||||
) | ||||||||||
return cast( | ||||||||||
models.KamereonVehicleChargingStartActionData, | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"data": { | ||
"type": "ChargePauseResume", | ||
"id": "guid", | ||
"attributes": { "action": "pause" } | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
{ | ||
"data": { | ||
"type": "ChargePauseResume", | ||
"id": "guid", | ||
"attributes": { "action": "resume" } | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is better to keep the original method (simply set_charge_start) and move the logic there.