renault-api icon indicating copy to clipboard operation
renault-api copied to clipboard

SRP is not implemented (required for Remote Engine Start / HVAC)

Open FRSTR opened this issue 3 years ago • 52 comments

Originally this issue was posted to Home Assistant integration, but it is also reproduced via renault-api CLI.

On an attempt to start AC in the NEW DUSTER car, the 403 error is returned. At the same time it works ok via MyRenault android app. At the same time renault-api CLI provides the car status correctly (mileage, fuel, GPS).

Debug log:

DEBUG:renault_api.kamereon:Received Kamereon response 403 on POST to https://api-wired-prod-1-euw1.wrd-aws.com/commerce/v1/accounts/.../kamereon/kca/car-adapter/v1/cars/..../actions/hvac-start?country=RU: {"type":"FUNCTIONAL","messages":[{"code":"err.func.403","message":"{\"errors\":[{\"status\":\"403\",\"code\":\"security.access\",\"detail\":\"Access is denied for this resource\"}]}"}],"errors":[{"errorCode":"err.func.403","errorMessage":"{\"errors\":[{\"status\":\"403\",\"code\":\"security.access\",\"detail\":\"Access is denied for this resource\"}]}"}],"error_reference":"FUNCTIONAL"}
Error: ('err.func.403', 'Access is denied for this resource')

Note: MyRenault app requires a PIN code set in the app to start AC, could it be required in the API and thus not working there?

FRSTR avatar Nov 03 '21 11:11 FRSTR

After numerous fails I've finally sniffed the traffic from the official MyRenault app on android, and I see that there is POST to ../actions/engine-start endpoint instead of hvac-start, and the payload is also different from hvac-start. It does not have a temperature in it (in my car the temp is always defaulted to 21, that's probably the reason it is not passed to this endpoint) but has some srp hash or smth like that.

There is also POST to ../actions/srp-sets before that, and a number of GET requests, mostly for notifications around that time.

If I got it right from the source code fragments of the app, the SRP also somehow includes the pin code set during pairing of the app/account to the car.

FRSTR avatar Nov 04 '21 14:11 FRSTR

The joys of the Renault API It's going to be very difficult for me to replicate and test, but I will accept a PR

May I suggest that you first look at #48 to add some fixtures for the Duster? If you have a chance, please post also the result of the carGateway (see #157 - I need to create a fixture folder for these) as I am pretty sure that carGateway will be needed to differentiate between Renault and Dacia.

epenet avatar Nov 07 '21 19:11 epenet

Here is the carGateway response for the new duster car with certain felds obfuscated:

{
  "data": {
    "type": "Car",
    "id": "db5c1177-1c3d-46ec-8717-31746d0b3266",
    "attributes": {
      "vin": "VF1AAAA1234567876",
      "vehicleId": 12345,
      "batteryCode": "SANBAT",
      "bin": null,
      "brand": "RENAULT",
      "canGeneration": "C1A",
      "carGateway": "AVN",
      "color": null,
      "dealerId": null,
      "deliveryCountry": "RU ",
      "deliveryDate": null,
      "deviceSerialNumber": null,
      "electricityUnitCost": null,
      "energy": "gasoline",
      "engineType": "H5H",
      "familyCode": "XJD",
      "firstRegistrationDate": null,
      "fuelUnitCost": null,
      "gearbox": "MANUAL",
      "modelCode": "HJD",
      "modelCodeDetail": "XJD1SU",
      "modelName": "NEW DUSTER",
      "modelYear": null,
      "navigAssistCode": null,
      "nickname": null,
      "packId": null,
      "packManufacturingDate": null,
      "packNominalCapacity": null,
      "packType": null,
      "pictureUrl": null,
      "radioType": "RA41A",
      "region": "RU",
      "registrationCountry": "RU ",
      "registrationNumber": "",
      "sourceReferenceId": null,
      "tcuCode": "AIVCT",
      "temperatureUnit": null,
      "upholstery": null,
      "vehicleSourceReference": null,
      "vehicleSourceType": null,
      "vehicleType": null,
      "versionCode": "B2 4 M3M 5C",
      "versionName": null,
      "privacyMode": "off",
      "privacyModeUpdateDate": null,
      "svtFlag": false,
      "svtLastUpdateTime": null,
      "svtBlockFlag": false,
      "svtBlockLastUpdateTime": null
    }
  }
}

FRSTR avatar Nov 17 '21 20:11 FRSTR

Here is the vehicle fixture:

{
  "accountId": "account-id-7",
  "country": "RU",
  "vehicleLinks": [
    {
      "brand": "RENAULT",
      "vin": "VF1AAAA1234567876",
      "status": "ACTIVE",
      "linkType": "USER",
      "garageBrand": "renault",
      "mileage": 500,
      "mileageUnit": "km",
      "mileageDate": "2021-10-29",
      "startDate": "2021-03-01",
      "createdDate": "2021-04-01T11:00:00.648452Z",
      "lastModifiedDate": "2021-10-29T08:26:03.648452Z",
      "cancellationReason": {},
      "preferredDealer": {
        "dealerId": "51214321_001",
        "brand": "RENAULT",
        "createdDate": "2018-01-01T19:27:14.798452",
        "lastModifiedDate": "8-01-1:27:14.798452"
      },
      "connectedDriver": {
        "role": "MAIN_DRIVER",
        "createdDate": "2021-03-03T00:01:02.648452Z",
        "lastModifiedDate": "2021-03-03T00:01:02.648452Z"
      },
      "vehicleDetails": {
        "vin": "VF1AAAA1234567876",
        "engineType": "H5H",
        "engineRatio": "460",
        "modelSCR": "JD1",
        "deliveryCountry": {
          "code": "RU",
          "label": "RUSSIA"
        },
        "family": {
          "code": "XJD",
          "label": "XJD FAMILY",
          "group": "007"
        },
        "tcu": {
          "code": "AIVCT",
          "label": "WITH AIVC CONNECTION UNIT",
          "group": "E70"
        },
        "navigationAssistanceLevel": {
          "code": "",
          "label": "",
          "group": ""
        },
        "battery": {
          "code": "SANBAT",
          "label": "",
          "group": "968"
        },
        "radioType": {
          "code": "RA41A",
          "label": "ENDAFFM (SCREEN ATTACH), AUDIO 7 (2 BO + 2 BI + 2 TWEETER, DOUBLE-MICRO",
          "group": "425"
        },
        "registrationCountry": {
          "code": "RU"
        },
        "brand": {
          "label": "RENAULT"
        },
        "model": {
          "code": "XJD1SU",
          "label": "NEW DUSTER",
          "group": "971"
        },
        "gearbox": {
          "code": "BVM6",
          "label": "6-SPEED MANUAL GEARBOX",
          "group": "427"
        },
        "version": {
          "code": "B2 4 M3M 5C"
        },
        "energy": {
          "code": "ESS",
          "label": "PETROL",
          "group": "019"
        },
        "registrationNumber": "REG-NUMBER",
        "vcd": "STANDA/XJD/HJD/EA2/M3/ESS/DG/GDFROI/TR4X4/AFURGE/RV/ABS/BARLO2/CA02/PBCH/LAC/VT/CPE/RET03/1RVLG/PROJAB/RALU16/CEAVFX/ADAC/AIRBA2/SERIE/DRA/DRAP07/HARM02/ATAR02/SGAV05/SGAR02/TECNW/BANAL/KM/PTCAV2/TPRM3/AVREPL/SSDECA/ABLAV/ESPDES/ALEVA/SOPC2C/SPRGAZ/STHPLG/KITGRV/VLCUIR/TRGAS/REPNTC/LVCIPE/LVAREL/SASURV/RSEC01/SGACHA/RUS01/APL03/AIRAR/VOLRHP/FSTPO/ALOUCC/CMAR3P/RA41A/BVM6/RDIF03/ISOFIX/ENPB01/HRGM01/SANFLT/CSRBA2/SANACF/SCHSTA/TLRP21/PRODIS/SAN613/SSFAP/AIRBDE/CHC03/E05C/ADFR/SSPTLP/SANCML/SSFLEX/SEXTIN/PE2017/PHAS1/SAN913/THABT1/SSTYAD/SSHYB/SSCABA/SANBAT/VEC654/XJD1SU/SSNBT/H5H/SDLIGM/SOUVCF/RMEGS/KITPOU/KITPGR/DPSEC/SSPREM/FDIU1/SSMAP/RCALL/PROCBO/SDANGM/ECOMOD/AIVCT/AVGSI/ITPK1/PERN02/VOLCHA/R134A/SFSSAC/SSVOLP/TCHA0/SPMIR/RRCAM/TCHC0/HTNZA",
        "assets": [
          {
            "assetType": "PICTURE",
            "renditions": [
              {
                "resolutionType": "ONE_MYRENAULT_LARGE",
                "url": "https://3dv.renault.com/ImageFromBookmark?configuration=HJD%2FEA2%2FDG%2FTR4X4%2FRV%2FABS%2FBARLO2%2FCA02%2FPBCH%2FRET03%2FPROJAB%2FRALU16%2FDRA%2FDRAP07%2FHARM02%2FATAR02%2FSGAV05%2FTECNW%2FKM%2FABLAV%2FESPDES%2FALEVA%2FSOPC2C%2FVLCUIR%2FLVCIPE%2FLVAREL%2FSGACHA%2FAPL03%2FVOLRHP%2FCMAR3P%2FRA41A%2FBVM6%2FRDIF03%2FENPB01%2FCSRBA2%2FSANACF%2FSAN913%2FH5H%2FRCALL%2FSDANGM%2FECOMOD%2FITPK1%2FPERN02%2FVOLCHA%2FRRCAM&databaseId=42b2c477-c47a-40c9-8ed2-a6966c244777&bookmarkSet=RSITE&bookmark=EXT_34_DESSUS&profile=HELIOS_OWNERSERVICES_LARGE"
              },
              {
                "resolutionType": "ONE_MYRENAULT_SMALL",
                "url": "https://3dv.renault.com/ImageFromBookmark?configuration=HJD%2FEA2%2FDG%2FTR4X4%2FRV%2FABS%2FBARLO2%2FCA02%2FPBCH%2FRET03%2FPROJAB%2FRALU16%2FDRA%2FDRAP07%2FHARM02%2FATAR02%2FSGAV05%2FTECNW%2FKM%2FABLAV%2FESPDES%2FALEVA%2FSOPC2C%2FVLCUIR%2FLVCIPE%2FLVAREL%2FSGACHA%2FAPL03%2FVOLRHP%2FCMAR3P%2FRA41A%2FBVM6%2FRDIF03%2FENPB01%2FCSRBA2%2FSANACF%2FSAN913%2FH5H%2FRCALL%2FSDANGM%2FECOMOD%2FITPK1%2FPERN02%2FVOLCHA%2FRRCAM&databaseId=42b2c477-c47a-40c9-8ed2-a6966c244777&bookmarkSet=RSITE&bookmark=EXT_34_DESSUS&profile=HELIOS_OWNERSERVICES_SMALL_V2"
              }
            ]
          }
        ],
        "yearsOfMaintenance": 12,
        "connectivityTechnology": "NONE",
        "easyConnectStore": false,
        "electrical": false,
        "rlinkStore": false,
        "deliveryDate": "2021-03-01",
        "retrievedFromDhs": false,
        "engineEnergyType": "OTHER",
        "radioCode": "1234"
      }
    }
  ]
}

FRSTR avatar Nov 17 '21 20:11 FRSTR

Hi @epenet , sorry for late response, but I'm back now. I've shared the carGateway response above, and also the fixture for my car. You mentioned a PR for fixture, but I'm not sure I can create it via github UI, and it probably requires usage of the git client. I'm not really a developer and I'm not familiar with git, so not really sure how to create a PR without spending a week for it. I also not sure if those fixtures are for requests or responses, as sometimes there is a valuable info in the request, and then valuable info could be in another endpoint's response.

Also to add details on the communications to start the engine:

  1. At first there is a request to /actions/srp-sets where SRP is generated and sent to servers.
  2. Then using the notifications endpoint is polled several times, until there is a response with server-generated response to SRP request
  3. After that the client sends POST to /actions/engine-start endpoint with its calculated SRP result.

These 3 steps happen every time. I also found that SRP support exists in https://github.com/mitchellrj/kamereon-python/blob/146904802301aa0b0008e2bdb3a88ed10ff50acf/kamereon/kamereon.py though not sure if it is finilized.

FRSTR avatar Nov 17 '21 20:11 FRSTR

Hi @FRSTR did you manage to work out how SRP works?

epenet avatar Dec 21 '21 08:12 epenet

Hi @epenet Yes, kinda. The SRP is a special standard protocol that is used to authenticate when the communication channel is not trusted. There are also several implementations in python, e.g. here a random repo I just found - https://github.com/cocagne/pysrp Plus as mentioned above the SRP was somehow supported (not sure it is fully supported there) in another Renault python library at https://github.com/mitchellrj/kamereon-python/blob/146904802301aa0b0008e2bdb3a88ed10ff50acf/kamereon/kamereon.py

The overall idea of SRP communication is the following:

  1. The client side creates a cryptic SRP payload based on auth (mainly from pin code in our case as far as I understand) and sends it to the server
  2. The server responds with its SRP payload calculated from client's payload.
  3. The client calculates the new SRP payload based on received data and sends it back to the server as the final step of auth. This happens in /actions/engine-start endpoint

FRSTR avatar Dec 21 '21 12:12 FRSTR

How much effort are you willing to put into this? We can try to work on it together, and you can send me the full sniff on "dev at zeflip dot com" if you do not wish to publish them here?

epenet avatar Dec 22 '21 13:12 epenet

@epenet yeah, I can sniff the stuff and try to test builds on my side, I'm just not really a developer to write python code (at least I still don't really get the OOP structure of the code in this repo). Indeed there is some personal info in the sniffs so we better communicate somewhere else, e.g. email as you said.

I also opened the Android app code to try figure our how it works, but again a good architecture instead of spaghetti makes it hard for me to get what's going on there. Though I can share pages from there if you'd like.

So as the first step, you'd want the full communication with SRP for the engine start flow, right? The sniffer I used is not friendly so it will take some time to capture full flow, but I'll start work on that today.

FRSTR avatar Dec 22 '21 14:12 FRSTR

@epenet I've just sent you an email with the sniff

FRSTR avatar Dec 23 '21 11:12 FRSTR

@FRSTR offtopic: I read that you had an issue with your HVAC and you got "something" replaced in your car; can you please provide some more details by mail? jumpjack at libero dot it
My HVAC preconditioning is faulty since august 2021 and no dealer was yet able to fix it by updates, so I think they will have to replace"something" too.

jumpjack avatar Dec 28 '21 10:12 jumpjack

@jumpjack: as I have already requested, can you please stop spamming? If you want to share knowledge, then please do so. If not, then please refrain from comments such as "use my tool instead".

You can already run all debug commands within the renault api like this: GET: renault-api --debug http get /commerce/v1/accounts/{account_id}/kamereon/kca/car-adapter/v1/cars/{vin}/charging-settings POST: renault-api --debug http post /commerce/v1/accounts/{account_id}/kamereon/kca/car-adapter/v1/cars/{vin}/actions/charge-schedule '{"data": {"type": "ChargeSchedule", "attributes": {"schedules": []}}}'

epenet avatar Dec 28 '21 10:12 epenet

@jumpjack , I don't want to share those traces as they have personal info and it takes quite some time to clear them out. If you have a tool, you can also sniff it with your car as the faulty module in the car does not affect anything in the app communication except for the final result being failure. Also I don't really know what was that module/control block replaced in my car. This was replaced by writing an email to Renault support email of MyRenault app, they said they forwarded this to their tech team, and after couple months they wrote back that they know how to fix my issue and I should just go to the car dealer. The dealer had already some info from Renault about a fix required for my car and they just replaced what they were told to.

FRSTR avatar Dec 28 '21 11:12 FRSTR

Hi @epenet . Just wanted to double check with you if you plan any work there. I have a daily need to at least lock the car via API or app, and I'm thinking if we proceed here or it may be faster for me to invest time into android app automation on my own.

FRSTR avatar Jan 25 '22 07:01 FRSTR

I'll try to have a fresh look before the end of the month - but not sure when.

epenet avatar Jan 25 '22 07:01 epenet

btw, @epenet I found this library for SRP, and it seems that generating SRP requests could as simple as the example on the readme page - https://github.com/cocagne/pysrp

If the SRP part gets implemented, it can also be used to lock the car, from what I remember the process was very similar. So also I have a related question here: I notices that there is "get_lock_status" method already exists in the current implementation, and before I even found it I also was able to simply construct it via CLI and it returned the correct status. Do you plan to expose this status to Home Assistant? This would be a helpful sensor for a person like me who sometimes fail to lock the car.

FRSTR avatar Feb 02 '22 15:02 FRSTR

Before it can be added to HomeAssistant, it needs to be exposed by the RenaultVehicle class: https://github.com/hacf-fr/renault-api/blob/680cd5a3b40ac8f683abe0a9077efa4181ca14ba/src/renault_api/renault_vehicle.py#L28

Is that something you feel you could do?

I have been busy these past weeks inside HA, and this week I refactored a few chunks to make way for the Dacia Spring features that @lucviala created PRs for.

epenet avatar Feb 02 '22 16:02 epenet

Note: adding the lock status should be much easier than implementating adding SRP as the framework is already there...

epenet avatar Feb 02 '22 16:02 epenet

@epenet but it is already there in renault-api/src/renault_api/renault_vehicle.py : async def get_lock_status(self) -> models.KamereonVehicleLockStatusData:

Or by expose you mean there should be some other structures? I'm sorry, I'm not fully familiar with the way it works. However if there is an example of another function I can use and just do the same - I can try to replicate it for the lock status

FRSTR avatar Feb 02 '22 16:02 FRSTR

Ah... the fixture file is empty, and so is the corresponding model. https://github.com/hacf-fr/renault-api/blob/main/tests/fixtures/kamereon/vehicle_data/lock-status.json https://github.com/hacf-fr/renault-api/blob/680cd5a3b40ac8f683abe0a9077efa4181ca14ba/src/renault_api/kamereon/models.py#L379-L383

If you update the fixture file with real data, and adjust the KamereonVehicleLockStatusData data class it should be straightforward to then add to HA.

epenet avatar Feb 02 '22 16:02 epenet

Ok. let me see If I can figure this out.

FRSTR avatar Feb 02 '22 16:02 FRSTR

And one more file to adjust afterwards: the tests to ensure we parse the data correctly. https://github.com/hacf-fr/renault-api/blob/main/tests/kamereon/test_kamereon_vehicle_data.py

epenet avatar Feb 02 '22 16:02 epenet

@epenet I've created a draft PR at https://github.com/hacf-fr/renault-api/pull/506 I did not expect that would be that easy with github desktop app, but at the same time... I did not run it anywhere to test, hopefully those tests cover it. And of course please let me know if my updates make sense, or not.

FRSTR avatar Feb 02 '22 17:02 FRSTR

In my tests with my app I get the usual "403 forbidden" response.

status": "502", "code": "gateway.processing", "title": "VNEXT", "detail": "an internal error occured while processing request : 403 FORBIDDEN"

jumpjack avatar Feb 02 '22 18:02 jumpjack

@jumpjack you get this error for which request?

FRSTR avatar Feb 03 '22 15:02 FRSTR

for the last one you are talking about, lock-status.

jumpjack avatar Feb 03 '22 16:02 jumpjack

')


Note: MyRenault app requires a PIN code set in the app to start AC, 

Where? On android, version 4.26.0 has no pin request for hvac, just a button.

jumpjack avatar Feb 03 '22 16:02 jumpjack

Different cars apparently make it different. My car basically starts its gasoline engine to do the job, and I guess it requires some level of security. Presumably for e-cars, hvac is considered less severe thing and thus does not require anything like that. Though if I'm not mistaken, the PIN code was required at the step of pairing the app with the EasyLink media in car.

FRSTR avatar Feb 03 '22 16:02 FRSTR

when I brought my plugin captur to the dealer last week, because preconditioning is no more working since 6 months, during the diagnosis he detected a "missing pin" error, but he was surprises and not able to explain it... so he just ignored it.

jumpjack avatar Feb 03 '22 16:02 jumpjack

Out of interest, does the hvac-status endpoint work on the Captur? It seems to now be available on the other vehicles, so I wonder if these lines can now be removed: https://github.com/hacf-fr/renault-api/blob/933b200cb5aa4a1ccfc93f012763bf52242875c3/src/renault_api/kamereon/models.py#L57-L59

epenet avatar Feb 07 '22 11:02 epenet