konradknitter / homebridge-philips-android-tv

Homebridge module for the Philips Android TV
Apache License 2.0
48 stars 6 forks source link

WoWifi only works for a short amount of time after turning TV off #42

Closed neonish closed 3 years ago

neonish commented 3 years ago

Describe Your Problem:

Has anyone else discovered, that turning on the TV via Homebridge works only like right after it was turned off? Once the TV is turned off for a longer period (like over night), the turning on command just keeps timing out. Also the turning on control disappears in my home app when restarting Homebridge while the TV is off. Turning the TV off works flawlessly though.

Is there a way to wake up the WiFi controller from deep sleep? I'm using a Philips Ambilight 50PUS8505/12.

Plugin Config:

{
            "platform": "PhilipsAndroidTV",
            "debug": true,
            "configVersion": 1,
            "tvs": [
                {
                    "name": "Phillips TV",
                    "ip": "###.###.###.###",
                    "macAddress": "ABCDEFGHIJKL",
                    "apiUser": "###",
                    "apiPass": "###",
                    "apiVersion": 6,
                    "wakeUntilAPIReadyCounter": 250,
                    "alternativePlayPause": true,
                    "dedicatedMuteSwitch": true,
                    "dedicatedVolumeLightbulb": true,
                    "channels": {
                        "useFavorites": false,
                        "favoriteListId": "1",
                        "includeAll": false
                    }
                }
            ]
        },

Environment:

konradknitter commented 3 years ago

Looks like Wake over LAN is not working in your scenario.

Wake over Lan is implemented in this plugin, and works with my TVs. Check if Wake over LAN is enabled in TV Network settings, and if you provided proper Mac address for TV. Try Wireless card address or Wired one - depending how TV is connected.

If still doesn't work - find a tool for Wake over Lan

  1. While TV is on: access https://yourIP:1926/6/system
  2. Turn off the TV, wait until https://yourIP:1926/6/system is not accessable
  3. Try to use Wake over Lan tool to make https://yourIP:1926/6/system accessible.

If you successful with other tool, but not my plug-in, please provide me data after successful with other tools.

neonish commented 3 years ago

Thanks for the pointers.

Unfortunately the web interface under http://yourIP:1926/6/system isn't available at any time …

I activated WoL on my TV, as well as WoL & port access in my routers settings. With these settings I managed to wake my TV, using the Philips TV Remote app on my iPhone: https://apps.apple.com/de/app/philips-tv-remote/id1479155903

I captured the corresponding network communication in wireshark:

Bildschirmfoto 2021-07-21 um 12 56 09

It seems like the app broadcasts out a bunch of MagicPackets, dedicated to my TV's MAC address to wake it up. While the SRC Port is changing throughout the messages, the DST port is always 9.

I can't see any MagicPacket or WOL communication though, while turning on/off the TV via your plugin.

neonish commented 3 years ago

I did some further digging:

When the TV is on, I am able to use philips_android_tv (which communicates with https://yourIP:1926/6/system/*) to get all kinds of TV statuses and turn standby mode on/off.

Also, I am able to use pywakeonlan to send a WOL MagicPacket to the TV (just like the ones in my screenshot before), which turns it on in standby mode. Afterwards I can use philips_android_tv to turn on the screen. Works like a charm.

Any chance you wanna integrate this in your plugin?

konradknitter commented 3 years ago

Hi,

okay, so it's possible to do. Still unclear what exactly has to be changed. Maybe glance at code will help.

Module used by me is: https://www.npmjs.com/package/wake_on_lan - pywakeonlan is Python module.

Homekit when turning on TV calls this function:


 async setOn(value: CharacteristicValue, callback: CharacteristicSetCallback) {
        try {
            callback(null);
            this.log.info('Turn on TV:' + value);
            if (value as boolean) {
                **await this.tv.turnOn();**
            } else {
                await this.tv.setPowerState(value as boolean);
            }
        } catch (err) {
            if (this.config.debug) {
                this.log.debug('setOn:' + err);
            }
        }
    }

Turn On tries to send PowerState enable, if fails (timeout as example) it calls wakeOnLan()

    async turnOn(counter = 0) {
        while (counter < this.config.wakeUntilAPIReadyCounter) {
            counter++;
            if ((counter % 10) === 0) {
                console.log('turnOn: try ' + counter);
            }
            try {
                await this.setPowerState(true);
                return;
            } catch {
                **await this.wakeOnLan();**
            }
        }
    }

and Wake on LAN function is following.


        async wakeOnLan() {
        if (this.mac) {
            wol.wake(this.mac, { address: '255.255.255.255' }, function (this, error) {
                if (error) {
                    console.log('wakeOnLan: error: ' + error);
                }
            }.bind(this));
            return await new Promise(resolve => setTimeout(resolve, 1000));
        }
    }

My only guess now is that: { address: '255.255.255.255' }

can't be hard-coded in your scenario. What address do you use for WoL?

neonish commented 3 years ago

pywakeonlan also uses 255.255.255.255 as a standard broadcast ip, which didn't work for me. In my screenshot above you can see that the Philips TV Remote iPhone App uses 192.168.178.255 as a broadcast ip, which eventually also worked for pywakeonlan.

Making this broadcast ip accessible from your plugin's config could be a solution. I tried changing the hard-coded ip in <plugin_path>/node_modules/@konradknitter/philipsandroidtv/dist/philipstv.js, but the Power On/Off accessory in Homebridge still keeps timing out ("updating"), so I'm unable to test it … I assume this happens because https://yourIP:1926/6/powerstate sends no reply while being in deep sleep. The accessory needs to be available in homebridge, even if the device is not responding.

Also I thought it was weird that the Philips TV Remote iPhone App sends out a whole bunch of MagicPackets. But while trying out pywakeonlan I found that sometimes just one packet indeed does not suffice to wake the TV from deep sleep. I ended up sending at least 3 packets, which works every time.

konradknitter commented 3 years ago

I've added to config "broadcastIP" where you can specify IP you want to be used.

neonish commented 3 years ago

Thanks for your help konrad. Although I still can't see any WOL packets or any communication at all with my broadcast ip, it works now!

There's just one final issue:

[23/07/2021, 08:23:39] [PhilipsAndroidTV] Turn on TV:1
turnOn: try 10
turnOn: try 20
turnOn: try 30
turnOn: try 40
turnOn: try 50
turnOn: try 60
turnOn: try 70
[23/07/2021, 08:27:40] [PhilipsAndroidTV] [Phillips TV] Start responding again.
[23/07/2021, 08:27:40] [PhilipsAndroidTV] [Phillips TV] TV has been turn on.
[23/07/2021, 08:27:44] [PhilipsAndroidTV] [Phillips TV] TV volume has been changed to 30%.

As I saw earlier, the TV needs multiple MagicPackets to be sent before it starts communicating. With your plugin it needs 7-8 "turnOn" attempts. With the currently hard-coded timeouts this takes about 4-5 minutes. Is there any way to lower the delay times? When using pywakeonlan, I'm sending 3 MagicPackets with a delay of half a second in between (before sending the powerstate command) and it works fast and reliable.

neonish commented 3 years ago

Also, when rebooting homebridge while the TV is in deep sleep, the accessory says "No Response". So I'm still unable to trigger anything in this case.

konradknitter commented 3 years ago

hey, added two modifiers:

wakeOnLanTimeout - how much milliseconds between sending packets, wakeOnLanRequests - how many packets should be send in one interval (burst)

neonish commented 3 years ago

thanks for your help konrad! cheers