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

Add Dacia Spring Support #459

Closed
wants to merge 2 commits into from

Conversation

f3dora19
Copy link
Contributor

@f3dora19 f3dora19 commented Jan 3, 2022

  • Add Dacia Spring Support
  • Add Charge Pause/Resume endpoint
  • Add fixtures
  • Add tests

@f3dora19 f3dora19 force-pushed the feat/dacia-spring-support branch from e888e30 to 15caeeb Compare January 3, 2022 10:56
@f3dora19
Copy link
Contributor Author

f3dora19 commented Jan 3, 2022

Hello everybody,

I made some changes on the api to be able to pause/resume dacia spring charge, but on the MyDacia application the only endpoint available to start the charge was totally different as the renault endpoint.
So I have to make some changes, and the only way I have to make the difference between one endpoint or another was the brand label "RENAULT" vs "DACIA".

@epenet
Copy link
Collaborator

epenet commented Jan 3, 2022

I don't think using the brand label is the best way to differentiate between available endpoints.
I think we should be using either the model code (XBG1VE) or the carGateway ("GDC" on Zoe40 / "AVN" on Zoe50 and Twingo)

@epenet
Copy link
Collaborator

epenet commented Jan 3, 2022

Also, in order to make it easier to review, could you please make at least two separate PRs?

  • One PR for the new fixtures and corresponding minor adjustments.
  • And a separate PR for the new charge-pause-resume endpoint.

@f3dora19
Copy link
Contributor Author

f3dora19 commented Jan 3, 2022

I don't think using the brand label is the best way to differentiate between available endpoints. I think we should be using either the model code (XBG1VE) or the carGateway ("GDC" on Zoe40 / "AVN" on Zoe50 and Twingo)

Ok, differentiation is now pointing to the model code.

But I do not understand the carGateway attribute, I don't find it in any code except for the duster fixtures, can you tell me more about it ?

@epenet
Copy link
Collaborator

epenet commented Jan 3, 2022

See #404 for carGateway. It is still work in progress...

@epenet
Copy link
Collaborator

epenet commented Jan 5, 2022

You should be able to run pre-commit run --all-files to fix the format issues.

@f3dora19 f3dora19 force-pushed the feat/dacia-spring-support branch from 9f60fa0 to 3c11575 Compare January 5, 2022 09:54
@f3dora19
Copy link
Contributor Author

f3dora19 commented Jan 5, 2022

@epenet, yes, you've right I runned nox --session=pre-commit, but there was a conflicts with my git pre-commit hook.

Just to inform you, I work on separate PRs like asked !

@f3dora19 f3dora19 force-pushed the feat/dacia-spring-support branch from 3c11575 to 6cad42d Compare January 5, 2022 10:33
@f3dora19
Copy link
Contributor Author

f3dora19 commented Jan 5, 2022

@epenet, this PR is rebased on #460 PR, please ensure that PR #460 be merged before, and you will review this one with the only new charge-pause-resume features.

* Add Dacia Spring charge pause/resume endpoint

* Add tests
@f3dora19 f3dora19 force-pushed the feat/dacia-spring-support branch from 6cad42d to 3eeb09e Compare January 5, 2022 11:58
Copy link
Collaborator

@epenet epenet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that #480 is merged, you should be able to access the carGateway property of the car adapter.

I suggest that you add a fixture for the carGateway of your dacia...

Comment on lines 50 to 54
await vehicle.get_details()
if (
vehicle._vehicle_details
and vehicle._vehicle_details.get_model_code() == "XBG1VE"
):

This comment was marked as outdated.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the carGateway cannot be uses (it shows AVN also for the dacia spring), I suggest this:

Suggested change
await vehicle.get_details()
if (
vehicle._vehicle_details
and vehicle._vehicle_details.get_model_code() == "XBG1VE"
):
details = await vehicle.get_details()
if details.get_model_code() == "XBG1VE":

src/renault_api/cli/charge/control.py Outdated Show resolved Hide resolved
@epenet
Copy link
Collaborator

epenet commented Jan 28, 2022

@afaucogney added the gateway details, and it seems that the dacia spring uses the same AVN gateway as the recent renault vehicles so I don't think we can use the carGateway to distinguish.

@epenet
Copy link
Collaborator

epenet commented Jan 28, 2022

Also, I have thought more about it and I think that you should move the logic to the VEHICLE_SPECIFICATIONS (in kamereon\model.py), something like this:

VEHICLE_SPECIFICATIONS: Dict[str, Dict[str, Any]] = {
    ...
    "XBG1VE": {  # Dacia Spring
        "charging-start-via-kcm": True,
    },
}

Then in KamereonVehicleDetails you can add a method uses_endpoint_via_kcm:

    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", True
            )
        return False  # pragma: no cover

* Modify tests

* Modify Kamereon model

Signed-off-by: Luc Viala <[email protected]>
@epenet
Copy link
Collaborator

epenet commented Jan 29, 2022

There are some conflicts that need resolving.
I think also that you shouldn't create a new method on the RenaultVehicle class.
You should move the logic for kcm out of the CLI and into the RenaultVehicle class which should have a start and a stop method.

@f3dora19
Copy link
Contributor Author

f3dora19 commented Jan 30, 2022

Hey @epenet, it will be very helpful if I can get a carGateway for the Spring, it could resolve lot of issues I get.
How can we determine which model uses a gateway ?

@epenet
Copy link
Collaborator

epenet commented Jan 30, 2022

To get the car gateway, you need to run this command:
renault-api --json http get "/commerce/v1/accounts/{account_id}/kamereon/kca/car-adapter/v1/cars/{vin}"

Comment on lines +50 to +54
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()
Copy link
Collaborator

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.

Suggested change
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()
response = await vehicle.set_charge_start()

Comment on lines +70 to +77
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)
Copy link
Collaborator

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 simply create a new function against the vehicle, and make the check there (you can raise NotImplementedException for the other vehicles)

Suggested change
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)
response = await vehicle.set_charge_stop()
click.echo(response.raw_data)

return VEHICLE_SPECIFICATIONS.get(self.model.code, {}).get(
f"{endpoint}-via-kcm", False
)
return False # pragma: no cover
Copy link
Collaborator

Choose a reason for hiding this comment

The 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
return False # pragma: no cover
return False

@@ -311,17 +320,28 @@ async def set_vehicle_action(
vin: str,
endpoint: str,
attributes: Dict[str, Any],
actions: str = "actions",
Copy link
Collaborator

Choose a reason for hiding this comment

The 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.
You have to add it at the bottom of the list to make it non-breaking (even with a default value).

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",

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":
Copy link
Collaborator

Choose a reason for hiding this comment

The 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(...

Comment on lines +505 to +507
async def set_charge_pause_resume(
self, action: str
) -> models.KamereonVehicleChargingStartActionData:
Copy link
Collaborator

Choose a reason for hiding this comment

The 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 uses_endpoint_via_kcm, and send the correct request (pause or raise NotImplemented).

Suggested change
async def set_charge_pause_resume(
self, action: str
) -> models.KamereonVehicleChargingStartActionData:
async def set_charge_stop(self) -> models.KamereonVehicleChargingStartActionData:

You can do the same in set_charge_start, which should check if uses_endpoint_via_kcm, and send the correct request (kca start, or kcm resume).

@epenet
Copy link
Collaborator

epenet commented Feb 1, 2022

Hi @lucviala
I have created and merged #500 which was partially based on your work, and implements the base functionnality for Renault.
Can you please rebase this branch on top of it?

@epenet epenet added the enhancement New feature or request label Feb 1, 2022
@epenet epenet closed this Feb 4, 2022
@jumpjack
Copy link

To get the car gateway, you need to run this command:
renault-api --json http get "/commerce/v1/accounts/{account_id}/kamereon/kca/car-adapter/v1/cars/{vin}"

Is this command correct? I get this with both my Renault vehicles and using both accounts (SFDC and MYRENAULT):

C:\>renault-api --json http get "/commerce/v1/accounts/xxxxxxxxxxxxxxxxxxxxx/kamereon/kca/car-adapter/v1/cars/VF1xxxxxxxxxxxxxxxx"

Error: ('err.func.404', '{"timestamp":"2022-04-28T08:54:18.320+0000","status":404,"error":"Not Found","message":"No message available","path":"/car-adapter/v1/cars/VF1xxxxxxxxxxxxxxxx"}')

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants