Closed kdschlosser closed 5 years ago
So, I turned on the TV from the media_player entity and it turned on, but the status inside HA quickly went back to off
. Here are the attributes of the media_player entity before it went to off
:
{
"volume_level": 0,
"is_volume_muted": false,
"source": "Unknown",
"source_list": [
"Source",
"Component 1",
"Component 2",
"AV 1",
"AV 2",
"AV 3",
"S Video 1",
"S Video 2",
"S Video 3",
"HDMI",
"HDMI 1",
"HDMI 2",
"HDMI 3",
"HDMI 4",
"FM-Radio",
"DVI",
"DVR",
"TV",
"Analog TV",
"Digital TV"
],
"friendly_name": "Living Room TV",
"supported_features": 20413
}
Also, when this happens, I see this in the logs (this is despite it turning on the TV):
2019-02-08 12:18:29 INFO (SyncWorker_2) [samsungctl] Is the TV on?!?
2019-02-08 12:18:29 ERROR ERROR (Thread-7) [samsungctl] Unable to power on the TV, check network connectivity
@gabrielcolceriu
your model TV may not support being turned on remotely. that is not what the error is about I am just letting you know ahead of time. I have fixed the code in the first post. to solve that error. let m know what the results are.
@arsaboo
this is what I am going to need you to do.
one thing at a time we need to test.. now we do know that how it is reporting power is not working properly. so I will add debug logging so we can see exactly what is going on.
this is what I want you to test for and tell me if it is working properly. and if it is not what is not working correctly about it and any errors
mute volume up volume down volume direct input source list changing source play pause fast forward rewind channel entry
the next 2 i do not care about what is reported. I do care if the feature is working turning on turning off
The problem is none of those functions are available when the media_player entity is off
:
I did also want to mention that the power on and power off sequence takes roughly 17 seconds for on and about 12 seconds for off.
do not pay attention to what the TV is doing. just because the screen is on or off is not what dictates when the TV is actually considered on or off. These TV's are Computers. so when you turn you computer on. just because the screen is on does it mean the computer is booted?? No it does not. so the same thing goes for the TV. it takes a while for the TV to boot up. as well as it takes a while for it to shutdown. so when the websocket service is finally started or stopped (which is one of the last things the TV does) then it is considered on or off.
so be patient when telling it to turn on or off. it may take 20 seconds for the state to change in HomeAssistant. and just like any computer. the newer the TV the faster it will be. and do remember that if you have a lot of applications on it. this can also impact the speed in which the TV boots. Also as a good rule of thumb. the more ding dongs and ho ho's (features) the TV has the longer it is going to take to boot. so the top of the line samsung TV of this year is probably going to take longer to turn on then say something middle of the road
I will force the script into an always on state so we can see what is happening. and also add the additional logging information...
@kdschlosser Volume up and down. Work fine The slider and mute don't do anything
I did try all sources and nothing happened
The tv was off for 30 mins, it's now been on for 20mins and HA still thinks it's off
Good post about the cycle on off time :+1:
OK I updated the code in the first post. the TV should always show up in Home Assistant as being on
I also added a bunch of debugging lines. this information is going to print out every 10 seconds I am guessing.
it will also tell us what the source is being set to when you try to change it.
You will need to put Home Assistant into debugging mode. I am not sure how to do this. if someone can explain how to do it that would be helpful
I am glad to see all of the upnp errors are gone with this version of samsungctl.
Use the following in configuration.yaml to obtain the logs
logger:
default: error
logs:
custom_components.media_player.samsungtv: info
samsungctl: info
OK i updated the code in the first post again.
I made a change to the power detection of the TV in samsungctl. the code in the first post is still going to lock thee TV in an always on state in Home Assistant.
I had to change all the _LOGGER.info
to LOGGER.debug
and here are the findings. Volume up and down worked reliably. Mute did not work for me. Also, not all sources worked for me. HDMI and TV
worked. But, I could not get it to switch back to HDMI4, for example.
Here are the logs: https://hastebin.com/inegowoguh.py
Just to clarify again, I am using a Sonos Playbar for sound and hence the Volume levels may be none
in the logs.
if you keep on using the source of HDMI does it rotate through the HDMI ports?
does your TV only have HDMI ports?
any way i can get you to change the setting in the TV back to internal for the sound? this way we can test the volume aspect of it
It also looks as tho I have solved the issue with the power state. I am going to change thee code in the first post so Home Assistant will set the state of the TV accordingly.
I am not at home otherwise would have tested that. I am testing remotely with my Arlo pointed towards my camera :wink:
LOL... if you have the ability to run samsungctl without HomeAssistant you could use the interactive mode to navigate to the menu setting and change it :smile:
Here are the ports on my TV. Let me know when you update the code and I can test it again for the power
BTW...you should seriously be on the HA discord server. It is a lot easier that way.
also. one other thing with the sources. if the TV does not have something plugged into a port it may not allow you to change to it. depends on the year and model of the TV i think.
I know my 2011 TV is like that
this is better because the history of what we have tried is easily visible for all to see.
I think something like that may be going on. I only have two HDMIs used. Apple TV on HDMI2 and Shield on HDMI4.
plus I am 45.. memory is slipping I do need to go back and see if i have tried something or not.. :wink:
code updated in first post
With the current code, I was not able to turn on the TV (which I could do earlier). HDMI is doing something, but not quite reliably. Like it changed to HDMI2 when I pressed it the first time, but it did not change to HDMI4 when I pressed it again. Here are the logs:
2019-02-08 13:32:08 ERROR (Thread-4) [samsungctl] Unable to power on the TV, check network connectivity this happens when it has an issue with sending the WOL packet.
try restarting Home Assistant and see if it starts working.
With the current code, I was not able to turn on the TV (which I could do earlier). HDMI is doing something, but not quite reliably. Like it changed to HDMI2 when I pressed it the first time, but it did not change to HDMI4 when I pressed it again. Here are the logs:
Likely that Home Assistant won't be sending through the second HDMI command as it already things it is on HDMI. Could add a second KEY_HDMI line so you can alternate between them to advance inputs (i.e. HDMI (Next)).
Also keep in mind Home Assistant's multi-threading can make things fun
from the logs it does appear the TV state is now working correctly. why exactly your TV is not turning on is the question. if the restart does not solve it then I will have to add some code to see what is going on.
@jnimmo No it is sending the command. When Home Assistant checks the source I am returning Unknown
okay with logger on i get the following
if the tv is off when HA is restarted, it stated the tv is unkown then about 30secs later it shows off here is what the logs captures
2019-02-08 18:39:30 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:39:31 ERROR (MainThread) [homeassistant.core] Error doing job: Exception in callback <bound method WebSocketResponse._send_heartbeat of <WebSocketResponse Switching Protocols GET /api/websocket >>
Traceback (most recent call last):
File "uvloop/cbhandles.pyx", line 245, in uvloop.loop.TimerHandle._run
File "/usr/local/lib/python3.6/site-packages/aiohttp/web_ws.py", line 101, in _send_heartbeat
self._loop.create_task(self._writer.ping()) # type: ignore
AttributeError: 'NoneType' object has no attribute 'ping'
2019-02-08 18:39:41 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:39:52 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:40:03 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:40:14 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:40:25 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:40:28 INFO (SyncWorker_18) [samsungctl] Is the TV on?!?
turned on manually HA doesn't change state (still off) turn on remotely HA state updates yet tv doesn't turn on (waited over 30 secs)
regarding sources nothing works
2019-02-08 18:46:33 INFO (SyncWorker_5) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_HDMI1', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:46:49 INFO (SyncWorker_8) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_HDMI3', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:46:59 INFO (SyncWorker_4) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_HDMI4', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:14 INFO (SyncWorker_14) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_COMPONENT1', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:17 INFO (SyncWorker_12) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_COMPONENT2', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:21 INFO (SyncWorker_18) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_AV1', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:23 INFO (SyncWorker_11) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_AV2', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:26 INFO (SyncWorker_6) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_AV3', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:30 INFO (SyncWorker_4) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_SVIDEO1', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:32 INFO (SyncWorker_10) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_SVIDEO2', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:35 INFO (SyncWorker_10) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_AV3', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:39 INFO (SyncWorker_15) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_DVI', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:44 INFO (SyncWorker_2) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_DVR', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:47 INFO (SyncWorker_4) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_TV', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:50 INFO (SyncWorker_5) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_ANTENA', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 18:47:53 INFO (SyncWorker_4) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_DTV', 'Option': 'false', 'TypeOfRemote':
Also keep in mind Home Assistant's multi-threading can make things fun
yeah I am finding that out. that coupled with some glitches n samsungctl it is hard to isolate the exact cause of a problem.
@phairplay
model number of your TV?
@phairplay
did you also use the latest code from the first post. you have been away for a bit. and the code has been updated several times since then.
the reason I ask this is because your logs show none of the new debugging information I added.
UE55MU6120
yes i've update the code every time you mention it 👍
ill try now to be 100 sure
it also appears that you have other issues with Home Assistant as well
2019-02-08 18:39:31 ERROR (MainThread) [homeassistant.core] Error doing job: Exception in callback <bound method WebSocketResponse._send_heartbeat of <WebSocketResponse Switching Protocols GET /api/websocket >>
Traceback (most recent call last):
File "uvloop/cbhandles.pyx", line 245, in uvloop.loop.TimerHandle._run
File "/usr/local/lib/python3.6/site-packages/aiohttp/web_ws.py", line 101, in _send_heartbeat
self._loop.create_task(self._writer.ping()) # type: ignore
AttributeError: 'NoneType' object has no attribute 'ping'
2019-02-08 18:39:41 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
i would really love to know what the timeeout period is on this thing. and if that Warning appears does that mean that it stopped trying to run the update for that interval. or is it simply hung?
also. you have to turn on debugging in Home Assistant @arsaboo posted instructions on how to do this a few posts back
019-02-08 19:00:07 INFO (SyncWorker_11) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_HDMI1
2019-02-08 19:00:20 INFO (SyncWorker_17) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_HDMI3', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:00:41 INFO (SyncWorker_11) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_HDMI4', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:00:45 INFO (SyncWorker_7) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_VOLUP', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:00:47 INFO (Thread-61) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWER', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:00:48 INFO (Thread-61) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWEROFF', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
now it appears off then appears on when i turn the tv on manually i can turn it off via HA
the duplicate ip is odd
2019-02-08 19:03:08 INFO (SyncWorker_13) [custom_components.media_player.samsungtv] Ignoring duplicate Samsung TV myip
2019-02-08 19:04:15 INFO (Thread-121) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWER', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:04:15 INFO (Thread-121) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWEROFF', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:04:26 INFO (Thread-121) [samsungctl] Unable to power off the TV
2019-02-08 19:05:13 INFO (Thread-136) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWER', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:05:13 INFO (Thread-136) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWEROFF', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:05:24 INFO (Thread-136) [samsungctl] Unable to power off the TV
updateed code in first post. i also found the problem when starting Home Assistant with the TV off.
@phairplay
I need to see the entire logs. not small chunks please attach them to a post as a text file
I am going to bail on you guys until early this evening. I have to replace the rear brake calipers on my Lincoln damned slider is frozen and causing issues. and now I have to go out in -4F : -20C temperatures and replace them.. YAY FUN IS!!! at least it's not snowing.
here is the logs starting from a restart
2019-02-08 18:56:17 WARNING (MainThread) [homeassistant.loader] You are using a custom component for media_player.samsungtv which has not been tested by Home Assistant. This component might cause stability problems, be sure to disable it if you do experience issues with Home Assistant.
2019-02-08 18:57:10 INFO (SyncWorker_6) [custom_components.media_player.samsungtv] Samsung TV 192.168.1.174 added as 'Samsung TV'
2019-02-08 18:57:40 WARNING (MainThread) [homeassistant.helpers.entity] Update of media_player.spare_room_samsung_ue55mu6120_2 is taking over 10 seconds
2019-02-08 18:57:41 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:57:51 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:58:06 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:58:17 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:58:28 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:58:39 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:58:50 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:59:01 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:59:12 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:59:23 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:59:34 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:59:45 WARNING (MainThread) [homeassistant.components.media_player] Updating samsungtv media_player took longer than the scheduled update interval 0:00:10
2019-02-08 18:59:45 INFO (SyncWorker_6) [samsungctl] Is the TV on?!?
2019-02-08 19:00:07 INFO (SyncWorker_11) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_HDMI1
2019-02-08 19:00:20 INFO (SyncWorker_17) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_HDMI3', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:00:41 INFO (SyncWorker_11) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_HDMI4', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:00:45 INFO (SyncWorker_7) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_VOLUP', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:00:47 INFO (Thread-61) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWER', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:00:48 INFO (Thread-61) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWEROFF', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:00:58 INFO (Thread-61) [samsungctl] Unable to power off the TV
2019-02-08 19:01:42 INFO (Thread-75) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWER', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:01:42 INFO (Thread-75) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWEROFF', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:01:53 INFO (Thread-75) [samsungctl] Unable to power off the TV
2019-02-08 19:02:31 INFO (Thread-95) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWER', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:02:32 INFO (Thread-95) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWEROFF', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:02:42 INFO (Thread-95) [samsungctl] Unable to power off the TV
2019-02-08 19:02:54 INFO (Thread-102) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWER', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:02:54 INFO (Thread-102) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWEROFF', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:03:04 INFO (Thread-102) [samsungctl] Unable to power off the TV
2019-02-08 19:03:08 INFO (SyncWorker_13) [custom_components.media_player.samsungtv] Ignoring duplicate Samsung TV 192.myip
2019-02-08 19:04:15 INFO (Thread-121) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWER', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:04:15 INFO (Thread-121) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWEROFF', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:04:26 INFO (Thread-121) [samsungctl] Unable to power off the TV
2019-02-08 19:05:13 INFO (Thread-136) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWER', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:05:13 INFO (Thread-136) [samsungctl] Sending control command: {'Cmd': 'Click', 'DataOfCmd': 'KEY_POWEROFF', 'Option': 'false', 'TypeOfRemote': 'SendRemoteKey'}
2019-02-08 19:05:24 INFO (Thread-136) [samsungctl] Unable to power off the TV
2019-02-08 19:06:54 INFO (Thread-49) [samsungctl] Websocket closed
2019-02-08 19:12:22 INFO (SyncWorker_15) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:12:22 INFO (SyncWorker_16) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:12:24 INFO (SyncWorker_19) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:12:26 INFO (SyncWorker_0) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:12:26 INFO (SyncWorker_12) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:12:34 ERROR (Thread-235) [samsungctl] Unable to power on the TV, check network connectivity
2019-02-08 19:12:47 INFO (SyncWorker_10) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:12:48 INFO (SyncWorker_9) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:12:49 INFO (SyncWorker_13) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:12:49 INFO (SyncWorker_0) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:12:49 INFO (SyncWorker_3) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:12:49 INFO (SyncWorker_2) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:12:51 INFO (SyncWorker_12) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLDOWN
2019-02-08 19:12:51 INFO (SyncWorker_11) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLDOWN
2019-02-08 19:12:52 INFO (SyncWorker_12) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLDOWN
2019-02-08 19:12:52 INFO (SyncWorker_5) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLDOWN
2019-02-08 19:13:02 INFO (SyncWorker_10) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:13:03 INFO (SyncWorker_11) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:13:06 ERROR (Thread-243) [samsungctl] Unable to power on the TV, check network connectivity
2019-02-08 19:13:44 ERROR (Thread-253) [samsungctl] Unable to power on the TV, check network connectivity
2019-02-08 19:16:44 INFO (SyncWorker_11) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:16:45 INFO (SyncWorker_18) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
2019-02-08 19:16:46 INFO (SyncWorker_9) [custom_components.media_player.samsungtv] TV is powering on, not sending command: KEY_VOLUP
Wow -20c I'm in the UK our country falls apart at -5c
So, some websocket errors with the most recent code: https://hastebin.com/qawosijiki.py
After those errors appeared, I was not able to turn off the TV.
OK so i see where some of the issue is.
from thee time the TV is actually powered off
2019-02-08 14:17:51 DEBUG (SyncWorker_2) [custom_components.media_player.samsungtv] Living Room TV TV: Power is Off
and when the websocket errors out and closes
2019-02-08 14:18:45 INFO (Thread-2) [samsungctl] Websocket closed
is 54 seconds. this is no good.
updated code in first post.
@phairplay
I am at 8500 feet (2590.8 meters) above sea level. in Colorado (Rocky Mountains) about an hour and a half away from the highest mountain in North America. Put it to ya this way. nearest gas station is a tad over 25 minutes away. (If i drove like the law says I should but since I don't it takes me about 15). In the last 3 weeks we have gotten 4 feet of snow.
and -20c is nothing. we call that "brisk" here.. now when it hits -30c (and it does and stays like that for a month sometimes) that is a might bit chilly. We get this really cool phenomenon that happens. we call it "Thunder Snow". That is when you have a lightning storm while it is snowing..
@phairplay
also I am starting to think you have a special-ed TV on your hands over there. the thing should be riding the little yellow short bus while wearing a helmet and licking the window. because it's slowwwww..... that is causing the time out problem in the async handler. I am going to move the construction of the remote to the __init__ method and see if that solves the problem . I know there is a 60 second timeout on that.
For me the current code works almost for my TV ue55mu6179 Mute does not work Power On not working (I think it is not possible with this model) Source change to HDMI works, but not back to TV. 2019-02-08 21:58:28 ERROR (MainThread) [custom_components.media_player.samsungtv] Samsung TV TV: Unsupported media type
@kdschlosser Wow that's insane! Haha! Doesnt surprise me my main tv is Sony android and the software it stupidly slow too, I had to buy a shield to watch plex and netflix
wait
is not allowed in HA code (it is fine for now). Once we get this working, we need to optimize the code so that it can be submitted.
@arsaboo
what do you mean??
@phairplay have a look at this...
I wrote a Sony TV Gen3+ API, I think it is still the most complete API made to date. I could be wrong in that tho. I have a develop branch that has a bunch more added to it. the develop branch is not in a working state and it actually has been a long time since I have put any work into it.
we have couple of wait(30)
in the code, which may not be allowed in the component.
*****UPDATED***** PLEASE READ ALL THE INFORMATION BELOW THERE ARE PARTS THAT HAVE CHANGED
I am moving the conversation that is taking place in #17802 as the current conversation really has nothing to do with the issue that was reported.
If this is not OK then delete this issue. I am the person that is currently updating the code to samsungctl. It has undergone a lot of additions which I do believe the users of Home Assistant will enjoy being able to use.
thee library also now supports ALL Samsung TV's that have the capability of being controlled over a network or WiFi Connection from 2008 to present. This includes the encrypted websocket connections (H (2014) and J (2015) TV's) as well as the SSL websocket connection (latest firmware release).
I have simplified the connection process so that the only things that are needed in thee Home Assistant config file is the host (ip) of the TV. nothing else is needed. the samsungctl library now handles hammering all of the connection specific details. I also added to it a a class that handles loading and saving of config data. I did this to handle the dynamically changing tokens that are used with the encrypted websockets and SSL websockets. the library now also does not stop running if the connection get severed.. (TV gets powered off). I also changed the handling of the power keys to make them function like they should. KEY_POWER = power toggle, KEY_POWERON = power on and KEY_POWEROFF = power off.
I am currently testing the replacement for /homeassistant/components/media_player/samsungtv.py, because I am not familiar with Home Assistant it is better to hammer these problems out in an issue where they can be tested then to open a PR for non functioning code and end up with a very messy commit history.
PLEASE READ
This is a replacement for the /homeassistant/components/media_player/samsungtv.py file please do not edit the code and then report an issue. only report problems relating to this code. also do not provide vague errors. like it says config error.. I am willing to bet the error stats more then "config error". I need a copy of the error message in it's entirety. not little bits and pieces. because of the nature of Home Assistant you may need to scroll back in the logs and read for a bit to make sure that you have grabbed all of the relevant log messages.
If you state anything about "custom_components" or if i see that in any of the errors I am not going to answer you. this is because you have modified the code. and it is a pretty good chance that your modification is what is causing the problem.
If you do not do the above then I have no way of helping to solve any issues.
config files for the TV are going to be saved in a directory called samsung_tv that is located in the Home Assistant config folder. the config files for the TVs are going to be named using the IP address you supply in the Home Assistant config yaml file.
HOME ASSISTANT CONFIG FILE This is the only thing that needs to be added to your hass configuration.yaml file. you will not need to specify any kind of a host. or mac or name. nothing. The whole system will dynamically add TV's as it finds them (of coarse with your permission). if a TV is found you will get a notification in the hass UI. when you open this notification you will be prompted to change the display name, the mac address and the description. if you do not wish to change them simply click on the accept button. You may need to refresh the page once the device is added for it to show up. If you have more then a single TV you DO NOT need to add multiple entries into the hass config file. You only need to add the below code a single time.
If you do not want to add a TV to hass (not sure why you wouldn't) simply ignore the notification. it will disappear after 60 seconds. if you change your mind afterwards or you simply miss the timeout you will need to go into thee samsung_tv config directory and delete the file that has an extension of
.noinclude
.the config file will only get saved once there is a successful connection to the TV made. I have changed about the detection mechanism for the 4 different types of connections. I am hoping this is going to be more of a dock solid mechanism of detecting the connection type. IF you have an issue detecting your TV let me know. There are some tasks I will have you do in order to get it to detect the TV properly. I do not own every Samsung TV made so there is no way to test it on my end. so it is up to you guys to follow the bug reporting directions as outline above.
Here is the updated code.
I WILL NOT MAKE CHANGES AND MAKE ANOTHER POST FOR IT. I WILL UPDATE THE CODE BELOW WITH ANY NEW CHANGES AND INFORM YOU THAT THE CODE HAS CHANGED
click to expand
```python """ Support for interface with an Samsung TV. For more details about this platform, please refer to the documentation at https://home-assistant.io/components/media_player.samsungtv/ """ import asyncio from datetime import timedelta import logging import threading import os import uuid import voluptuous as vol from homeassistant.components.media_player import ( MEDIA_TYPE_CHANNEL, PLATFORM_SCHEMA, SUPPORT_NEXT_TRACK, SUPPORT_PAUSE, SUPPORT_PLAY, SUPPORT_PLAY_MEDIA, SUPPORT_PREVIOUS_TRACK, SUPPORT_TURN_OFF, SUPPORT_TURN_ON, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, SUPPORT_VOLUME_SET, SUPPORT_SELECT_SOURCE, MediaPlayerDevice) from homeassistant.const import ( CONF_NAME, STATE_OFF, STATE_ON ) import homeassistant.helpers.config_validation as cv from homeassistant.util import dt as dt_util REQUIREMENTS = [ 'https://github.com/kdschlosser/' 'samsungctl/archive/develop.zip#samsungctl==0.8.64b' ] SAMSUNG_CONFIG_PATH = 'samsung_tv' ICON_TV = 'mdi:television' ICON_TV_OFF = 'mdi:television-off' ICON_COMPONENT = 'mdi:video-input-component' ICON_HDMI = 'mdi:video-input-hdmi' ICON_SVIDEO = 'mdi:video-input-svideo' ICON_USB = 'mdi:usb' ICON_PC = 'mdi:console' ICON_DLNA = 'mdi:dlna' ICON_AV = 'mdi:audio-video' ICON_YOUTUBE = 'mdi:youtube' ICON_HULU = 'mdi:hulu' ICON_NETFLIX = 'mdi:netflix' ICON_PLEX = 'mdi:plex' ICON_SPOTIFY = 'mdi:spotify' ICON_AMAZON = 'mdi:amazon' ICON_PLAYSTATION = 'mdi:playstation' ICON_UNKNOWN = 'mdi:help' _LOGGER = logging.getLogger(__name__) CONF_DESCRIPTION = 'description' CONF_ADD = 'add_tv' KEY_PRESS_TIMEOUT = 1.2 KNOWN_DEVICES_KEY = 'samsungtv_known_devices' SUPPORT_SAMSUNGTV = ( SUPPORT_PAUSE | SUPPORT_VOLUME_STEP | SUPPORT_VOLUME_MUTE | SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | SUPPORT_TURN_OFF | SUPPORT_PLAY | SUPPORT_PLAY_MEDIA | SUPPORT_VOLUME_SET | SUPPORT_SELECT_SOURCE ) SAMSUNG_TV_SCHEMA = vol.Schema({ vol.Optional(CONF_NAME): cv.string, vol.Optional(CONF_DESCRIPTION): cv.string, vol.Optional(CONF_ADD): cv.boolean, }) PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({}) _CONFIGURING = {} def setup_platform(hass, config, add_entities, _=None): """Set up the Samsung TV platform.""" config_path = hass.config.path(SAMSUNG_CONFIG_PATH) if not os.path.exists(config_path): os.mkdir(config_path) known_devices = hass.data.get(KNOWN_DEVICES_KEY, set()) hass.data[KNOWN_DEVICES_KEY] = known_devices import samsungctl from samsungctl.upnp.discover import auto_discover config_files = list( os.path.join(config_path, file) for file in os.listdir(config_path) if file.endswith('config') ) def callback(found_config): if found_config.uuid in known_devices: return _LOGGER.debug(str(found_config)) known_devices.add(found_config.uuid) no_include = os.path.join( config_path, found_config.uuid + '.noinclude' ) if os.path.exists(no_include): return if found_config.uuid not in _CONFIGURING: add_device(found_config, hass, config_path, add_entities) auto_discover.register_callback(callback) entities = [] configs = [] for config_file in config_files: _LOGGER.debug(config_file) samsung_config = samsungctl.Config.load(config_file) known_devices.add(samsung_config.uuid) configs += [samsung_config] auto_discover.start() for samsung_config in configs: entities += [SamsungTVDevice(samsung_config)] add_entities(entities) def add_device(samsung_config, hass, config_path, add_entities): model = samsung_config.model uuid = samsung_config.uuid event = threading.Event() def samsung_configuration_callback(data): """Handle the entry of user PIN.""" display_name = data.get('display_name') description = data.get('description') mac = data.get('mac') if display_name is None: display_name = samsung_config.display_name if description is None: description = samsung_config.description if mac is None: mac = samsung_config.mac samsung_config.display_name = display_name samsung_config.description = description samsung_config.mac = mac samsung_config.path = os.path.join( config_path, samsung_config.uuid + '.config' ) hass.components.configurator.request_done(_CONFIGURING.pop(uuid)) if samsung_config.method == 'encrypted': request_configuration(samsung_config, hass, add_entities) else: add_entities([SamsungTVDevice(samsung_config)]) event.set() def do(): event.wait(600.0) if not event.isSet(): path = os.path.join( config_path, samsung_config.uuid + '.noinclude' ) with open(path, 'w') as f: f.write('') hass.components.configurator.request_done(_CONFIGURING.pop(uuid)) t = threading.Thread(target=do) t.daemon = True t.start() _CONFIGURING[uuid] = hass.components.configurator.request_config( model, samsung_configuration_callback, description='New TV discovered, would you like to add the TV?', description_image="/static/images/smart-tv.png", submit_caption="Accept", fields=[ dict( id='display_name', name='Name: ' + samsung_config.display_name, type='' ), dict( id='description', name='Description: ' + samsung_config.description, type='' ), dict( id='mac', name='MAC Address : ' + str(samsung_config.mac), type='' ) ] ) def request_configuration(samsung_config, hass, add_entities): """Request configuration steps from the user.""" configurator = hass.components.configurator import samsungctl pin = [] count = 0 event = threading.Event() def samsung_configuration_callback(data): """Handle the entry of user PIN.""" pin.append(data.get('pin')) event.set() def get_pin(): global count if samsung_config.uuid in _CONFIGURING: count += 1 event.clear() del pin[:] configurator.notify_errors( _CONFIGURING[samsung_config.uuid], "Failed to register, please try again." ) else: _CONFIGURING[samsung_config.uuid] = configurator.request_config( samsung_config.display_name, samsung_configuration_callback, description='Enter the Pin shown on your Samsung TV.', description_image="/static/images/smart-tv.png", submit_caption="Confirm", fields=[{'id': 'pin', 'name': 'Enter the pin', 'type': ''}] ) event.wait(60.0) if count == 3: _LOGGER.error( samsung_config.display_name + " TV: Pin entry failed" ) return False elif not event.isSet(): return None return pin[0] samsung_config.get_pin = get_pin def do(): global count try: _ = samsungctl.Remote(samsung_config) add_entities([SamsungTVDevice(samsung_config)]) except: pass hass.components.configurator.request_done(_CONFIGURING.pop(uuid)) t = threading.Thread(target=do) t.daemon = True t.start() class SamsungTVDevice(MediaPlayerDevice): """Representation of a Samsung TV.""" def __init__(self, config): """Initialize the Samsung device.""" from samsungctl import exceptions from samsungctl import Remote # Save a reference to the imported classes self._exceptions_class = exceptions self._remote_class = Remote self._config = config self._mac = self._config.mac self._uuid = self._config.uuid self._playing = True self._state = None self._remote = None self._key_source = False self._mute = False self._sources = [] self._source = '' self._volume = 0.0 self._entity_image = None self._tv_image = None if self._config.method == 'websocket': self._has_apps = True else: self._has_apps = False self._icon = ICON_TV_OFF self._supported_features = SUPPORT_SAMSUNGTV if self._config.method != 'legacy': self._supported_features |= SUPPORT_TURN_ON # Mark the end of a shutdown command (need to wait 15 seconds before # sending the next command to avoid turning the TV back ON). self._end_of_power_off = None # Mark the end of the TV powering on.need to wait 20 seconds before # sending any commands. self._end_of_power_on = None # Generate a configuration for the Samsung library self._remote = self._remote_class(self._config) def update(self): """Update state of device.""" if self._power_off_in_progress(): _LOGGER.debug( self._config.display_name + ' TV: Powering Off' ) self._state = STATE_OFF self._icon = ICON_TV_OFF # self._entity_image = self._tv_image elif self._power_on_in_progress(): _LOGGER.debug( self._config.display_name + ' TV: Powering On' ) self._state = STATE_OFF self._icon = ICON_TV_OFF # self._entity_image = self._tv_image else: power = self._remote.power if power is True and self._remote.is_connected: self._config.save() if self._tv_image is None: tv_image = self._remote.icon if tv_image is not None: self._tv_image = tv_image.data sources = self._remote.sources entity_image = self._tv_image source = 'Unknown' if sources is None: if self._has_apps: sources = [ 'TV', 'HDMI' ] for app in self._remote.applications: if app.is_running and app.is_visible: source = 'APP: ' +app.name entity_image = app.icon sources += ['APP: ' + app.name] self._sources = sources self._source = source self._entity_image = entity_image else: self._sources = [ 'Source', 'Component 1', 'Component 2', 'AV 1', 'AV 2', 'AV 3', 'S Video 1', 'S Video 2', 'S Video 3', 'HDMI', 'HDMI 1', 'HDMI 2', 'HDMI 3', 'HDMI 4', 'FM-Radio', 'DVI', 'DVR', 'TV', 'Analog TV', 'Digital TV' ] self._key_source = True else: new_sources = [] for src in sources: if src.is_active: if src.label != src.name: source = src.label + ':' + src.name else: source = src.name if src.name != src.label: new_sources += [src.label + ':' + src.name] else: new_sources += [src.name] self._key_source = False self._sources = new_sources[:] self._source = source # self._entity_image = entity_image if self._source.upper().endswith('TV'): self._icon = ICON_TV elif self._source.upper().endswith('USB'): self._icon = ICON_USB elif self._source.upper().endswith('PC'): self._icon = ICON_PC elif self._source.upper().endswith('DLNA'): self._icon = ICON_DLNA elif 'S VIDEO' in self._source.upper(): self._icon = ICON_SVIDEO elif 'COMPONENT' in self._source.upper(): self._icon = ICON_COMPONENT elif 'AV' in self._source.upper(): self._icon = ICON_AV elif 'HDMI' in self._source.upper(): self._icon = ICON_HDMI elif 'YOUTUBE' in self._source.upper(): self._icon = ICON_YOUTUBE elif 'HULU' in self._source.upper(): self._icon = ICON_HULU elif 'NETFLIX' in self._source.upper(): self._icon = ICON_NETFLIX elif 'PLEX' in self._source.upper(): self._icon = ICON_PLEX elif 'SPOTIFY' in self._source.upper(): self._icon = ICON_SPOTIFY elif 'AMAZON' in self._source.upper(): self._icon = ICON_AMAZON elif 'PLAYSTATION' in self._source.upper(): self._icon = ICON_PLAYSTATION else: self._icon = ICON_UNKNOWN volume = self._remote.volume _LOGGER.debug( self._config.display_name + ' TV: Volume = ' + str(volume) ) if volume is not None: self._volume = volume / 100.0 mute = self._remote.mute _LOGGER.debug( self._config.display_name + ' TV: Mute = ' + str(mute) ) if mute is None: self._mute = False else: self._mute = mute _LOGGER.debug( self._config.display_name + ' TV: Power is On' ) self._state = STATE_ON else: _LOGGER.debug( self._config.display_name + ' TV: Power is Off' ) # self._entity_image = self._tv_image self._icon = ICON_TV_OFF self._state = STATE_OFF def send_key(self, key): """Send a key to the tv and handles exceptions.""" if self._power_off_in_progress(): _LOGGER.info( self._config.display_name + " TV: powering off, not sending command: %s", key ) return elif self._power_on_in_progress(): _LOGGER.info( self._config.display_name + " TV: powering on, not sending command: %s", key ) return if self._state == STATE_OFF: _LOGGER.info( self._config.display_name + " TV: powered off, not sending command: %s", key ) return self._remote.control(key) @property def icon(self): """Return the icon to use in the frontend, if any.""" return self._icon @property def entity_picture(self): """Return the entity picture to use in the frontend, if any.""" return self._entity_image @property def unique_id(self) -> str: """Return the unique ID of the device.""" return '{' + self._config.uuid + '}' @property def name(self): """Return the name of the device.""" return self._config.display_name @property def state(self): """Return the state of the device.""" return self._state @property def supported_features(self): """Flag media player features that are supported.""" return self._supported_features def select_source(self, source): """Select input source.""" if self._key_source: if source == 'Analog TV': source = 'ANTENA' elif source == 'Digital TV': source = 'DTV' source = source.upper().replace('-', '_').replace(' ', '') source = 'KEY_' + source _LOGGER.debug( self._config.display_name + ' TV: changing source to ' + source ) self.send_key(source) else: if 'APP' in source: app_name = source.rsplit(':', 1)[-1] app = self._remote.get_application(app_name) if app is not None: app.run() if ':' in source: source = source.rsplit(':', 1)[-1] _LOGGER.debug( self._config.display_name + ' TV: changing source to ' + source ) self._remote.source = source @property def source(self): """Name of the current input source.""" return self._source @property def source_list(self): """List of available input sources.""" return self._sources def volume_up(self): """Volume up the media player.""" self.send_key('KEY_VOLUP') def volume_down(self): """Volume down media player.""" self.send_key('KEY_VOLDOWN') @property def volume_level(self): """Volume level of the media player scalar volume. 0.0-1.0.""" return self._volume def set_volume_level(self, volume): """Set volume level, convert scalar volume. 0.0-1.0 to percent 0-100""" self._remote.volume = int(volume * 100) def mute_volume(self, mute): """Send mute command.""" self._remote.mute = mute @property def is_volume_muted(self): """Boolean if volume is currently muted.""" return self._mute def media_play_pause(self): """Simulate play pause media player.""" if self._playing: self.media_pause() else: self.media_play() def media_play(self): """Send play command.""" self._playing = True self.send_key('KEY_PLAY') def media_pause(self): """Send media pause command to media player.""" self._playing = False self.send_key('KEY_PAUSE') def media_next_track(self): """Send next track command.""" self.send_key('KEY_FF') def media_previous_track(self): """Send the previous track command.""" self.send_key('KEY_REWIND') async def async_play_media(self, media_type, media_id, **kwargs): """Support changing a channel.""" if media_type != MEDIA_TYPE_CHANNEL: _LOGGER.error( self._config.display_name + ' TV: Unsupported media type' ) return # media_id should only be a channel number try: cv.positive_int(media_id) except vol.Invalid: _LOGGER.error( self._config.display_name + ' TV: Media ID must be positive integer' ) return for digit in media_id: await self.hass.async_add_job(self.send_key, 'KEY_' + digit) await asyncio.sleep(KEY_PRESS_TIMEOUT, self.hass.loop) @property def app_id(self): """ID of the current running app.""" return None @property def app_name(self): """Name of the current running app.""" return None def turn_on(self): """Turn the media player on.""" if self._power_on_in_progress(): return if self._config.mac: self._end_of_power_on = dt_util.utcnow() + timedelta(seconds=20) if self._power_off_in_progress(): self._end_of_power_on += ( dt_util.utcnow() - self._end_of_power_off ) def do(): _LOGGER.debug( self._config.display_name + ' TV: Power on process started' ) event = threading.Event() while self._power_off_in_progress(): event.wait(0.5) self._remote.power = True t = threading.Thread(target=do) t.daemon = True t.start() elif self._config.method != 'legacy': _LOGGER.info( self._config.display_name + " TV: There was a problem detecting the TV's MAC address, " "you will have to update the MAC address in the Home " "Assistant config file manually." ) else: _LOGGER.info( self._config.display_name + " TV: Legacy TV's (2008 - 2013) do not support " "being powered on remotely." ) def _power_on_in_progress(self): return ( self._end_of_power_on is not None and self._end_of_power_on > dt_util.utcnow() ) def turn_off(self): """Turn off media player.""" if self._power_off_in_progress(): return self._end_of_power_off = dt_util.utcnow() + timedelta(seconds=15) if self._power_on_in_progress(): self._end_of_power_off += ( dt_util.utcnow() - self._end_of_power_on ) def do(): _LOGGER.debug( self._config.display_name + ' TV: Power off process started' ) event = threading.Event() while self._power_on_in_progress(): event.wait(0.5) self._remote.power = False t = threading.Thread(target=do) t.daemon = True t.start() def _power_off_in_progress(self): return ( self._end_of_power_off is not None and self._end_of_power_off > dt_util.utcnow() ) ```