alexmohr / sonyapilib

Contains a python api to control sony devices.
MIT License
20 stars 11 forks source link

2011 device - HTTP headers required for commands to work after authentication #53

Closed PaulWebster closed 4 years ago

PaulWebster commented 4 years ago

After authentication/registration on the TV the commands are still not being accepted (403 response). I think that this is because these old devices (reg mode 2) need to have 2 headers included that allow the TV to determine that this is an allowed controller.

In KHerron/SonyAPILib code there are hard-coded values that are always inserted in the HTTP requests. For this Python app it should use the values that it provided during the registration phase. The HTTP headers are: X-CERS-DEVICE-ID: X-CERS-DEVICE-INFO:

I suspect that newer devices ignore those fields if they are present so it is probably safe to ensure that they are present and set in _send_http

I am attempting to make a hard-coded version to verify the principle.

PaulWebster commented 4 years ago

Update - I hacked this in and now I have basic IR-like controls working for Mute/VolUp/VolDown (and I expect other would as well if they were exposed in UI). My hack is not releasable because I hard-coded the client info.

alexmohr commented 4 years ago

I'm going to add the headers for every device. It may take a bit until I get arround to do it.

PaulWebster commented 4 years ago

What I did was to add the following into _send_http

After params.update(kwargs) add params['headers']['X-CERS-DEVICE-ID'] = 'hack' params['headers']['X-CERS-DEVICE-INFO'] = 'hack'

Rather than 'hack' it should be the real client info.

PaulWebster commented 4 years ago

I tried the code from the Bug/auth branch. Registration now works but calls to change volume (for instance) did not work.

I think that your change for sending the headers on all calls does not work because the send_authentication call that sets up the headers is made during initial configuration only. So a subsequent restart of HA would mean that there are no headers in self.headers

alexmohr commented 4 years ago

The media player implementation did not call init_device that makes a call to recreate authentication which restores all headers. It should be working with the latest PR on the home assistant media player repo.

PaulWebster commented 4 years ago

I just tried with the new media_player.py - but still not seeing the headers in the request. I modified the LOGGER call in _send_http to show the names of the headers and they are not present

"Calling http url %s method %s headers %s ", url, method, '\n'.join(map(str, params.get("headers"))))

e.g. one of the SOAP calls logs like this:

2020-06-08 13:30:54 DEBUG (SyncWorker_8) [sonyapilib.device] Calling http url http://192.168.2.162:52323/upnp/control/AVTransport method post headers SOAPACTION
Content-Type

Those headers are the ones explicitly added for the SOAP call but the X-CERS ones are not present.

Strictly speaking - the X-CERS header is not need for the SOAP call (I think) but that was to show that the modified LOGGER call works. Here is a log entry for one that fails

2020-06-08 13:30:54 DEBUG (SyncWorker_8) [sonyapilib.device] Calling http url http://192.168.2.162:80/cers/api/getRemoteCommandList method get headers
2020-06-08 13:30:54 ERROR (SyncWorker_8) [sonyapilib.device] HTTPError: 403 Client Error: Forbidden for url: http://192.168.2.162:80/cers/api/getRemoteCommandList

Nothing after "headers".

alexmohr commented 4 years ago

That is totaly valid because I forgot to that you are using a device without pin and headers where only added with a pin. I've added a method _add_headers which is called in init and before authentication. The corresponding unit test is missing. I'll add this in a few days.

PaulWebster commented 4 years ago

Ok - that resolved the headers - thanks. I can now change volume via HA UI.

Next thing for me to look at is the IRCC_PORT because I am still hard-coding it into media_player.py as it does not seem to be picking it up from config.