openhab / openhab-addons

Add-ons for openHAB
https://www.openhab.org/
Eclipse Public License 2.0
1.86k stars 3.57k forks source link

[VolvoOnCall] Cars after 2021 are not supported #13607

Open Duc opened 1 year ago

Duc commented 1 year ago

New vehicles aren't supported, we need to use the new API.

The Volvo API (called connected vehicle) does not support vehicles after 2021 : https://developer.volvocars.com/apis/connected-vehicle/overview/. I think it is the one we currently use.

There are two others API which we can use :

We need to "wrap" this new API in the add-on. I'm not able to do it on my own, but I'm ready to help and test.

openhab-bot commented 1 year ago

This issue has been mentioned on openHAB Community. There might be relevant details there:

https://community.openhab.org/t/volvo-oncall-binding/59605/115

alexmuetze commented 1 year ago

Yes, indeed! Would be great to integrate it for future Volvo Cars. I am not sure, but you need to authenticate your app with an open URL in order to get permanent access to the API. Did someone try it with success?

jofland commented 1 year ago

I think there is some progress in using the new API. Someone developed an adapter for io broker. Maybe this information could help developing an addon for openhab as well?

https://forum.iobroker.net/topic/29172/tester-adapter-volvo-on-call-und-android-automotive

nikagersonlohman commented 1 year ago

Yes, this works. I have tested this in javascript and python. Getting the access token to use in the Bearer Authentication works fine when using the following URL, Headers and post-data:

                "https://volvoid.eu.volvocars.com/as/token.oauth2",
                headers = {
                    'authorization': 'Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=',
                    'content-type': 'application/x-www-form-urlencoded',
                    'user-agent': 'okhttp/4.10.0'
                },
                data = {  
                    'username': username,
                    'password': password,
                    'access_token_manager_id': 'JWTh4Yf0b',
                    'grant_type': 'password',
                    'scope': 'openid email profile care_by_volvo:financial_information:invoice:read care_by_volvo:financial_information:payment_method care_by_volvo:subscription:read customer:attributes customer:attributes:write order:attributes vehicle:attributes tsp_customer_api:all conve:brake_status conve:climatization_start_stop conve:command_accessibility conve:commands conve:diagnostics_engine_status conve:diagnostics_workshop conve:doors_status conve:engine_status conve:environment conve:fuel_status conve:honk_flash conve:lock conve:lock_status conve:navigation conve:odometer_status conve:trip_statistics conve:tyre_status conve:unlock conve:vehicle_relation conve:warnings conve:windows_status energy:battery_charge_level energy:charging_connection_status energy:charging_system_status energy:electric_range energy:estimated_charging_time energy:recharge_status vehicle:attributes'
                }

After authentication, the following API can be used: https://developer.volvocars.com/apis/connected-vehicle/specification/

The other APIs seem to not work. Note that I have succesfully tested the following calls on my Volvo XC40 Pure-electric (P8):

https://api.volvocars.com/connected-vehicle/v1/vehicles
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/commands
https://api.volvocars.com/connected-vehicle/v2/vehicles/{{VIN}}/commands/climatization-start
https://api.volvocars.com/connected-vehicle/v2/vehicles/{{VIN}}/commands/climatization-stop
        "vin": "XXX",
        "statusCode": 200,
        "invokeStatus": "COMPLETED",
        "message": ""
https://api.volvocars.com/connected-vehicle/v2/vehicles/{{VIN}}/commands/lock
https://api.volvocars.com/connected-vehicle/v2/vehicles/{{VIN}}/commands/unlock
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/commands/navi-point-of-interest
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/engine
engineCoolantLevel
oilLevel
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/diagnostics
engineHoursToService
serviceStatus
washerFluidLevel
serviceTrigger
kmToService
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/fuel
fuelAmount
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/battery-charge-level
batteryChargeLevel
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/odometer
odometer
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/statistics
tripMeter1
tripMeter2
averageFuelConsumption
distanceToEmpty
averageSpeed
        "tripMeter1": {
            "value": "49",
            "unit": "kilometers",
            "timestamp": "2023-02-04T16:01:17Z"
        },
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/windows
rearLeft
rearRight
frontLeft
frontRight
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/doors
carLocked
frontLeft
frontRight
rearLeft
rearRight
hood
tailGate
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/brakes
brakeFluid
        "brakeFluid": {
            "value": "FLUID_LEVEL_HIGH",
            "timestamp": "2023-02-04T16:01:17Z"
        }
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/tyres
rearRight
rearLeft
frontLeft
frontRight
https://api.volvocars.com/connected-vehicle/v1/vehicles/{{VIN}}/warnings

A lot needs to be changed to use this other API. I think it would be better to create a new binding (for instance volvoconnectedvehicle), though probably much can be reused from the previous volvooncall binding...

If needed I can test and help with the development. I just do not have much Java experience...

I have also posted some details in the following repo (as I originally helped with the original volvooncall code in that repo many years ago): https://github.com/molobrakos/volvooncall/issues/84

Regards,

Nika.

nikagersonlohman commented 1 year ago

Posting my rules here: https://github.com/nikagl/volvo/tree/main/openhab

Gonna try to make the items file as well (created them manually now)...

lyncker commented 1 year ago

Hi ... I am trying to use your statement with curl but no success... maybe you can help here?

curl -v -X POST 'https://volvoid.eu.volvocars.com/as/token.oauth2' \
-H 'content-type: application/x-www-form-urlencoded' \
-H 'authorization: Basic ZmlsaXAdghdfghdfghfdghsdeklluQTQgzezMz' \
-H 'user-agent: okhttp/4.10.0' \
-d 'username=myemail%40domain&password=myPW&grant_type=password&scope=openid email profile care_by_volvo:financial_information:invoice:read care_by_volvo:financial_information:payment_method care_by_volvo:subscription:read customer:attributes customer:attributes:write order:attributes vehicle:attributes tsp_customer_api:all conve:brake_status conve:climatization_start_stop conve:command_accessibility conve:commands conve:diagnostics_engine_status conve:diagnostics_workshop conve:doors_status conve:engine_status conve:environment conve:fuel_status conve:honk_flash conve:lock conve:lock_status conve:navigation conve:odometer_status conve:trip_statistics conve:tyre_status conve:unlock conve:vehicle_relation conve:warnings conve:windows_status energy:battery_charge_level energy:charging_connection_status energy:charging_system_status energy:electric_range energy:estimated_charging_time energy:recharge_status vehicle:attributes'

Im unsure about the Bae64 encoding... I encoded: myEmail@domain:myPW Do I have to respect URLfriendly encoding? because nothing works I tried to insert (in encoding ans also the -H string myemail%40Domain instead of @ but this also did not work ...

thanks a lot for you help!

nikagersonlohman commented 1 year ago

This works in curl:

curl --location 'https://volvoid.eu.volvocars.com/as/token.oauth2' \
--header 'Authorization: Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=' \
--header 'Content-Type: application/x-www-form-urlencoded' \
--header 'User-Agent: okhttp/4.10.0' \
--data-urlencode 'grant_type=password' \
--data-urlencode 'username=USERNAME@DOMAINNAME.COM' \
--data-urlencode 'password=PASSWORD' \
--data-urlencode 'scope=openid email profile care_by_volvo:financial_information:invoice:read care_by_volvo:financial_information:payment_method care_by_volvo:subscription:read customer:attributes customer:attributes:write order:attributes vehicle:attributes tsp_customer_api:all conve:brake_status conve:climatization_start_stop conve:command_accessibility conve:commands conve:diagnostics_engine_status conve:diagnostics_workshop conve:doors_status conve:engine_status conve:environment conve:fuel_status conve:honk_flash conve:lock conve:lock_status conve:navigation conve:odometer_status conve:trip_statistics conve:tyre_status conve:unlock conve:vehicle_relation conve:warnings conve:windows_status energy:battery_charge_level energy:charging_connection_status energy:charging_system_status energy:electric_range energy:estimated_charging_time energy:recharge_status vehicle:attributes'

Or in Windows:

curl --location "https://volvoid.eu.volvocars.com/as/token.oauth2" --header "Authorization: Basic aDRZZjBiOlU4WWtTYlZsNnh3c2c1WVFxWmZyZ1ZtSWFEcGhPc3kxUENhVXNpY1F0bzNUUjVrd2FKc2U0QVpkZ2ZJZmNMeXc=" --header "Content-Type: application/x-www-form-urlencoded" --header "User-Agent: okhttp/4.10.0" --data-urlencode "grant_type=password" --data-urlencode "username=USERNAME@DOMAIN.COM" --data-urlencode "password=PASSWORD" --data-urlencode "scope=openid email profile care_by_volvo:financial_information:invoice:read care_by_volvo:financial_information:payment_method care_by_volvo:subscription:read customer:attributes customer:attributes:write order:attributes vehicle:attributes tsp_customer_api:all conve:brake_status conve:climatization_start_stop conve:command_accessibility conve:commands conve:diagnostics_engine_status conve:diagnostics_workshop conve:doors_status conve:engine_status conve:environment conve:fuel_status conve:honk_flash conve:lock conve:lock_status conve:navigation conve:odometer_status conve:trip_statistics conve:tyre_status conve:unlock conve:vehicle_relation conve:warnings conve:windows_status energy:battery_charge_level energy:charging_connection_status energy:charging_system_status energy:electric_range energy:estimated_charging_time energy:recharge_status vehicle:attributes"
lyncker commented 1 year ago

yeah thanks a lot.. I just got it working adapting your python code... but I dont understand what you encoded in the Bas64 ... I thought it must be my credentials ... but now Im just using your code... what is that?!

nikagersonlohman commented 1 year ago

data-urlencode just changes spaces to %20 and adds ampersant to multiple parameters... there's no base64 of that part. The Authorization key is a key that was "found" elsewere to perform that oauth2 authentication as required by Volvo

lyncker commented 1 year ago

ok anyway "elsewere" is good so far ;) Now , if I try to use the Code, I get an 401 unauthorized ... I tried to authorize the code in the volvo frontend using the authorize button, were I have to connect it with the APP-ID , but without succes... I tried the following Call : curl -v -X GET 'https://api.volvocars.com/connected-vehicle/v1/vehicles/MYVIM/engine-status' \ -H 'accept: application/vnd.volvocars.api.connected-vehicle.vehicledata.v1+json' \ -H 'authorization: Bearer MYBEARERCODE' \ -H 'vcc-api-key: MYAPPKEY'

This works fine with a code generated from the sandbox (and the real car)

lyncker commented 1 year ago

ok seems to be the scope the call is not in there.. with AC start it worked !

lyncker commented 1 year ago

one last thing: did you manage to get the recharge or SOC information of your car? all the calls I tried give me an empty data field :

{
  "status" : 200,
  "operationId" : "a78368d9-e52e-4edd-9c44-ee41b18c1a61",
  "data" : { }
* Connection #0 to host api.volvocars.com left intact
}

I tried : recharge-status and battery-charge-level

nikagersonlohman commented 1 year ago

Yes, battery-charge-level works for me... recharge-status does not (different api's btw) image

curl --location 'https://api.volvocars.com/connected-vehicle/v1/vehicles/MYVIN/battery-charge-level' \
--header 'Accept: application/vnd.volvocars.api.connected-vehicle.vehicledata.v1+json'

Usimg the Authorization with the Bearer access_code (from the previous script) and my vcc-api-key

lyncker commented 1 year ago

I just tested the API Calls with another VolvoID and another XC90 Car.. there also the Battery Charge Level Endpoints ( and the whole EnergyAPI) returns empty data fields ... is it possible that it has something to do with the "found" base64 encoded key??

nikagersonlohman commented 1 year ago

I don't think so as the same problem exists when using the hourly key you can generate for each API from your developer account.

Technically though, all of the things passed to the APIs (oauth2 authorization key, username/password provided in the oauth2 call and vcc-api-key provided in the API-calls) could influence the scope of the calls returned by the APIs. For username/password we know it restrict what vins are returned. vcc-api-key just authorizes as far as we can see from the API, but you never know.

Only Volvo developers could shed a light on this, maybe someone should try and log a ticket? I would not specifically mention the use of the oauth2 authorization key though, as they might then start to ask questions where we got it...

lyncker commented 1 year ago

you're right, with the hourly key its the same... so it might nothing to do with the your key ... I already wrote to the developers email using the GUID in the call as they mentioned ... but up to now , no answer ... we'll see ...

tobelix87 commented 1 year ago

I assume that the empty fields depends on this base64 encoded clientID/pw. If you try to send a publishing request for your application in the https://developer.volvocars.com/ Portal, you need to select the scopes that your application is using. There are all API endpoints listed.

When I generate a test token for my own car via https://developer.volvocars.com/apis/docs/test-access-tokens/, I get a value back for Battery Charge Level. When I try it with a requested access token via the "found" key, the value is empty