TA2k/ioBroker.polestar

No Informations can be fetched

Opened this issue · 7 comments

Adapter turns green, but can not fetch informations from polestar. there is an error in the log:

{"errors":[{"message":"Cannot query field \"consumerId\" on type \"MyStarCar\".","locations":[{"line":70,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"engine\" on type \"MyStarCar\".","locations":[{"line":71,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"exterior\" on type \"MyStarCar\". Did you mean \"exteriorImageUrl\"?","locations":[{"line":72,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"exteriorCode\" on type \"MyStarCar\". Did you mean \"exteriorImageUrl\"?","locations":[{"line":73,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"gearbox\" on type \"MyStarCar\".","locations":[{"line":75,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"interior\" on type \"MyStarCar\".","locations":[{"line":76,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"interiorCode\" on type \"MyStarCar\".","locations":[{"line":77,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"interiorImageUrl\" on type \"MyStarCar\". Did you mean \"exteriorImageUrl\"?","locations":[{"line":78,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"packageCode\" on type \"MyStarCar\". Did you mean \"package\"?","locations":[{"line":82,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"pdfUrl\" on type \"MyStarCar\".","locations":[{"line":83,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"status\" on type \"MyStarCar\".","locations":[{"line":84,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"steering\" on type \"MyStarCar\".","locations":[{"line":85,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"wheels\" on type \"MyStarCar\".","locations":[{"line":87,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"Cannot query field \"wheelsCode\" on type \"MyStarCar\". Did you mean \"modelCode\"?","locations":[{"line":88,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}]}

TA2k commented

This correct the adapter can only show general data of the car but no actual data. The connection via mqtt to get actual values is not done

Yes I know, but there are no data fetched.
image

TA2k commented

Yes only in the log so far

@TA2k It seems the messages are serialised in protobuf format. I found a whole bunch of .proto files depicting all kinds of requests and responses while decoding the Polestar Android APK. They are part of the Volvo vocmo SDK, where the app seems to be built upon. The app's actual Java files also seem to consume parts of these files, matching feature parity. It's all pretty heavily obfuscated though, so not easy to find out what's exactly done and how.

Would you happen to still have some of the messages you received? My car doesn't arrive until 24 feb this month, but I'd already like to take a look to see what we can find out. Does the rest of the connection process work? Do you own a Polestar yourself?

I think the first thing to do is to figure out how they define which message is received. Probably utilising an enveloping/wrapper message. I think at least reading events would be easy if we found that part out. Requesting updates may be a bit harder.

It seems it's a lot more complex than just protobuf decoding the strings. It seems the mobile device first needs to be enrolled with the API for each car it has access to. It will in turn get a private key/cert pair (per car). With this cert/key pair it can sign encrypted envelope messages which contain said protobuf structures as a payload.

I suppose the signing certs are also the way the MQTT communication is authenticated for each message sent; it will take the car identifier from the cert ID that has been used to encrypt and encode with.

At least.. That's what I'm guessing based on the decompiled app source.

My 2$ct's: this is going to be one hell of a ride. First imma get my car and see if I can get the MITM stuff going. Then I'll revisit.

Fun fact: the internals of the SDK actually supports using both MQTT and BLE as a data channel. This tells me the module on the car is able to communicate directly with the same message format by using the same key pair that are provisioned inside the app.

TA2k commented

Yes you are right this is also my assumption
here you can see a mqtt connection

image

There also two files in the android shared keystore
(CACERT_xxxxdevicePairingKey and CACERT_xxxxcatalogKey.
I think this files are used to encrypt the mqtt traffic

Unfortunately I cannot see the de and encryption in Frida it looks like they are doing his own stuff in libvocmo-lib.so
Because of the complexity I don't think this is good way to pursuit. I saw you can connect your polestar with the tibber app it would be interesting how this looks like or waiting for an api like Volvo offers.

I've done some more digging. I've found the lib they use for those message crypto bindings (libvocmo-lib.so). It is indeed compiled C/C++ code, and bundled with the APK for all supported platforms (including x86_64).

It seems they use a project called 'djinni' (https://djinni.xlcpp.dev/) for interfacing from the apps with the lib. Conveniently, they kept the 'bindings' unobfuscated inside the APK;

Screenshot 2023-03-03 at 15 12 50

So in theory, one could take libvocmo-lib.so and implement those Djinni bindings directly, use their official library for decoding/encoding the messages. This would remove the need to reverse engineer the lib file which seems to be hard.

Screenshot 2023-03-03 at 15 24 11

Some more references; https://www.dropbox.com/s/k1b214bsqgpx4e6/Djinni%20Talk%20-%20CppCon%202015.pdf?dl=0.

We can use the private key/cert from the device store against the bindings/functions inside the lib and attempt to figure out the embedded data format of the messages sent by the app. In this case we don't actually need much from the app source itself and can probably get a long way already. But as it also contains all protobuf definitions, it would definitely help to look at the source for more.

The only obvious problem is that this project seems to use node.js, and there's no bindings available for that. :-)

Still not really sure if it's worth it to spend considerable amounts of time to reverse engineer the 'real' api. But on the flip side, I also have no real confidence Polestar is going to release a public API anytime soon. Some have been waiting for 3 years already.. Tibber also does not really seem to be an option right now as they do not seem to support Polestars out of Sweden yet.

I think IEC15118-3 is the safest bet, at least for communicating with the vehicle to get its batteries' state of charge while it's connected to the charger. As I really only need SoC (and hopefully also a way to uniquely 'identify' the car once it connects to my charger), I guess this is the way to go for me (in combination with the SmartEVSE charge controller project).