eslavnov / pylips

Control Philips TVs (2015+) and Ambilight (+ Hue) through their reverse-engineered API (+ MQTT support!)
MIT License
334 stars 58 forks source link

[FEAT] Docs on pairing protocol #100

Closed elupus closed 3 years ago

elupus commented 3 years ago

Is your feature request related to a problem? Please describe. Having an unofficial doc on the pairing protocol would be nice

Describe the solution you'd like A description of the known things about the pairing protocol

Additional context I'm especially lacking:

elupus commented 3 years ago

Context for this is that i'm working on updating the home assistant plugin. And especially would be really nice to get the serial number to be used as a unique ID.

eslavnov commented 3 years ago

Hi @elupus,

As mentioned in the README, the pairing mechanism was taken from this repo: https://github.com/suborb/philips_android_tv. Perhaps its maintainer could provide some answers. I'll try to give you some context to the best of my understanding, but please take it with a grain of salt: I have not really researched it that deeply.

Check pair and pair_request in Pylips (lines 90 and 121), along with the methods used there to get some insights. The general flow is: 1) Generate a pairing request (see the code) and send it to the TV. This a) Displays the pairing code on the TV screen and b) sends back some data in the response. We need the auth_key (the password for the user) and the timestamp from this response. 2) You take the timestamp from the response, the displayed pin and also attach a signature, that is using the pin and the secret_key and construct a new object. (The key by itself does not seem to matter - I've randomly changed it and it still worked the same. It's also never required for any other commands, so I am not sure what's up with it). You send the resulting object to another endpoint to confirm the pairing and after that you can use the auth_key.

As for the _encrypted fields: I'm also curious about this but haven't really researched this since I did not have a real need for this. Please share any info if you figure it out!

elupus commented 3 years ago

Okey.. soo. not sure how, but https://github.com/suborb/philips_android_tv/blob/master/philips.py#L14 this is actuall a valid key. It can be used to decode the encrypted fields with AES/CBC/PKCS7Padding.

Saved me the trouble of figuring getting it out the android app.

RensMvP commented 2 years ago

@elupus did you figure out pairing protocol? I am trying to convert the pylips to a esp32 project, but i get a read timeout on the pair request.

elupus commented 2 years ago

Yes, it's here: https://github.com/danielperna84/ha-philipsjs/blob/16e363cde45b9f0c38fbd501560864c620606696/haphilipsjs/__init__.py#L607

RensMvP commented 2 years ago

Well seems like i send exactly that Json to the tv api (v6.4.0) but i get a read timeout back. { "scope": [ "read", "write", "control" ], "device": { "device_name": "heliotrope", "device_os": "Android", "app_name": "ESP32api", "type": "native", "app_id": "app.id", "id": "HWvAq8UdGxbGbsH7" } } I also posted this isue on the esp32 forum with my code, but no response yet https://www.esp32.com/viewtopic.php?f=19&t=26939#p94531. I did manage to control the ambilight on port 1925, but that is without paring.

Have you maybe an idea where the problem might be, theoretically it should work

elupus commented 2 years ago

You are doing a post request not a get?

RensMvP commented 2 years ago

Yes i'm using the post function. That is part of the httpclient library for the esp32. This Post command works for turning the ambilight on or off

elupus commented 2 years ago

You seem to try to auto detect api version. The tv will always respond to V1 system requests so maybe you are not trying on V6/v5 api as needed?

RensMvP commented 2 years ago

Yeah indeed, the autodetect will look for the http OK code and save the first api version that responds. This autodetects works on the http protocol 1925 and until now it always said v6. In the browsers is the same result when entering 'http://iptv:1925/api version/system', only api version 6 returns the json stream

RensMvP commented 2 years ago

I thought that v1 systems did not respond to https request, but i might be wrong

elupus commented 2 years ago

V6 systems respond to both https and http. They also respond to V1 requests for system info on both http and https.

RensMvP commented 2 years ago

Strange that i did not get any response on the get systeem info on api v1, when entering this in the browser. Not sure why, but only v6 response to the get systeem info.

But how would this relate to the read timeout on the post request to pair with the tv

elupus commented 2 years ago

The tvs are buggy, if you do a pair request against /1/ endpoints i don't know what it will do.

RensMvP commented 2 years ago

Yeah you can say that haha. 3 different TV's and the one running api 6.4 responded the best to the http ambilight on/off. But you advise to test sending the pair requests to api 1 (aka https://tvip:1926/1/pair/request)

elupus commented 2 years ago

I advise you send to the 6 endpoint. The code you linked for esp32 would end up wrongly sending to the v1 endpoint, if i reas the code correctly.

RensMvP commented 2 years ago

Hmm not sure if I understand you correctly and the code i linked send the pair request tot endpoint 6 since that is the only one that repsonds with the http OK code. But when I send the pair requests it just times out every time I send it

elupus commented 2 years ago

As I said, a tv with V6 support will most often ALSO respond with OK on V1 endpoint. Since you check V1 endpoint first, in the for loop, it will break out early in the loop. You want to change the loop iteration to be reversed apiVersion = {6, 5, 1} so you get the highest available version.

Or select API version based on the data on the system response.

RensMvP commented 2 years ago

Ah oke, I will try that then again.

RensMvP commented 2 years ago

Seems i found the issue, the api autodetect was not the problem. It was with the httpclient library, that needed to have the WifiClientSecure and set that to insecure to be able to connect. Now i get the pairing code. Thanks for your help in clearing some things up with the pairing proces @elupus .

RensMvP commented 2 years ago

I am curious do i get the password and timestamp back from the tv? The arduino library i am using, seems to respond only with the http code OK, but i the pylips code looks like it is reading from the response. Is it true that the TV sends back info for the pairing, when sending the pair/request?

elupus commented 2 years ago

Yes you get that from the pair request. This you use to calculate the signature that should be sent on the grant endpoint.