alexmohr / sonyapilib

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

KeyError: 'Power' on first power-on #10

Closed dilruacs closed 5 years ago

dilruacs commented 5 years ago

Turning on the device is done with SonyDevice.power(true):

    def power(self, on):
        if (on):
            self.wakeonlan()
            # Try using the power on command incase the WOL doesn't work
            if not self.get_power_status():
                self.send_command('Power')
        else:
            self.send_command('Power')

The function send_command tries to fetch a list of available commands from the device:

    def send_command(self, name):
        if len(self.commands) == 0:
            self.update_commands()

        self.send_req_ircc(self.commands[name].value)

When the device is powered off (in this case a BDP-S3200), this will fail because the call to /getRemoteCommandList is denied:

2019-04-01 11:21:03 ERROR (Thread-17) [sonyapilib.device] Exception: HTTPConnectionPool(host='192.168.240.4', port=50002): Max retries exceeded with url: /getRemoteCommandList (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fcc66435eb8>: Failed to establish a new connection: [Errno 111] Connection refused',))

This will cause the commands array to remain empty, in turn causing a KeyError: 'Power' if a power on is tried through send_command("Power")

Once the device has been turned on and the commands array is populated, the problem is solved.

Following solutions are available:

  1. do not try to send commands if the function update_commands() did not return a populated array (should be checked in all circumstances, there could be other causes we didn't think of yet)
  2. store the array in the json configuration as soon as it has been fetched from the device, so it will persist (otherwise if one starts Home Assistant with the device turned off, this will always throw an error the first time)
alexmohr commented 5 years ago

Fixed in https://github.com/alexmohr/sonyapilib/pull/12

dilruacs commented 5 years ago

The submitted PR contained the error checking mentioned in part 1 of the solution. I did not implement part 2 yet. Apparently the stored json contains a placeholder for the commands array, but the json is stored at a point in time where the array isn't populated yet.

I am still pondering on the right place in the code to make sure this is populated.

alexmohr commented 5 years ago

The right point would be something after send_authentication

alexmohr commented 5 years ago

I'm going to solve this issue together with the v4 implementation because I'm going to refactor quite some things anyway

dilruacs commented 5 years ago

This issue is a bit annoying, as it causes a problem for every first buttonpress after the start of home assistant. If the device happens to be turned on, the first "play" command will fail too, because the commands array isn't populated.

I propose populating the array in the register() function at the end, if registration_result == AuthenicationResult.SUCCESS, so the SonyDevice object is complete right from the start and can be stored as a whole directly

dilruacs commented 5 years ago

See: https://github.com/alexmohr/sonyapilib/pull/16

alexmohr commented 5 years ago

Fixed in #16