ollo69 / ha-samsungtv-smart

📺 Home Assistant SamsungTV Smart Component with simplified SmartThings API Support configurable from User Interface.
Apache License 2.0
459 stars 59 forks source link

Component status not reflecting reality (the status is on off continuely) #61

Closed sunsgs closed 2 years ago

sunsgs commented 3 years ago

Describe the bug tv is going off and on continuing. I have a led connected on the tv and from HA I read the status of the tv. It happens always that the tv is going on and off (only as status on HA but not in the reality). The same is not happening if the tv is really off.(on HA it stays off)

Expected behavior The status on HA is the same as the current real status of tv (always on)

Screenshots N/A

Environment details:

ancientm74 commented 3 years ago

i have same problem with QE55Q7FAM

Olen commented 3 years ago

Same here. I have a debug automation that reports the state, and here is an example:

TV debug. State from on to off - Changed: 2021-03-12 20:26:49.035638 00:00 │ TV debug. State from off to on - Changed: 2021-03-12 20:28:49.066905 00:00

I have enabled debugging of the compnent, but nothing in the HA-logs indicates that the TV was switched off during that period.

Olen commented 3 years ago

After a night's sleep I realize that this was not the right tree to bark up, but I will add some debugging locally to see where the status is wrongly set.

d-edge82 commented 3 years ago

Same here on Q70

Olen commented 3 years ago

I added a bunch of extra debugging. what is failing is the check

            result = difference < MAX_WS_PING_INTERVAL

around line 644 in custom_components/samsungtv_smart/api/samsungws.py

[custom_components.samsungtv_smart.api.samsungws] Ping ws_remote result: False, call_time 2021-03-14 18:16:54.173839, last_ping: 2021-03-14 18:15:54.340483, MAX_WS: 10

This again happens becuase the Thread SamsungRemote is terminating.

So the thread terminates, but is restarted automatically. However, that takes more than 10 seconds, so in the mean time, the ping_device is called, and since it is more than 10 seonds since the last ping, this check fails, and returns False, and hence, the state is set to off

18:15:54 - The device is fine, and responds to ping, but then the SamsungRemote fails 18:16:09 - The thread is restarted, and at the same time a new ping is run, which works fine 18:16:24 - When the next ping is run, the timestmp is compared to 18:15:54, which is more than 10 seconds ago, so it returns false

2021-03-14 18:15:54 DEBUG (MainThread) [custom_components.samsungtv_smart.media_player] Current state is on                                                                                   
2021-03-14 18:15:54 DEBUG (SamsungRemote) [custom_components.samsungtv_smart.api.samsungws] {'event': 'ms.channel.timeOut'}                                                                   
2021-03-14 18:15:54 DEBUG (SamsungRemote) [custom_components.samsungtv_smart.api.samsungws] Thread SamsungRemote terminated        

2021-03-14 18:16:09 DEBUG (SamsungRemote) [custom_components.samsungtv_smart.api.samsungws] Thread SamsungRemote started                                                                      
2021-03-14 18:16:09 DEBUG (SyncWorker_28) [custom_components.samsungtv_smart.media_player] Samsung TV - Ping-device returned: True                                                            
2021-03-14 18:16:09 DEBUG (MainThread) [custom_components.samsungtv_smart.media_player] Current state is on                                                                                   

2021-03-14 18:16:24 DEBUG (SyncWorker_0) [custom_components.samsungtv_smart.api.samsungws] Output is (b'PING 10.20.0.100 (10.20.0.100): 56 data bytes\n\n--- 10.20.0.100 ping statistics ---\n
1 packets transmitted, 1 packets received, 0% packet loss\nround-trip min/avg/max = 2.304/2.304/2.304 ms\n', b'')                                                                             
2021-03-14 18:16:24 DEBUG (SyncWorker_0) [custom_components.samsungtv_smart.api.samsungws] Ping ping result: True                                                                             
2021-03-14 18:16:24 DEBUG (SyncWorker_0) [custom_components.samsungtv_smart.api.samsungws] Ping ws_remote result: False, call_time 2021-03-14 18:16:24.368928, last_ping: 2021-03-14 18:15:54.
340483, MAX_WS: 10                                                                                                                                                                            
2021-03-14 18:16:24 DEBUG (SyncWorker_0) [custom_components.samsungtv_smart.media_player] Samsung TV - WS Ping-device returned: False                                                         
2021-03-14 18:16:24 DEBUG (SyncWorker_0) [custom_components.samsungtv_smart.media_player] Samsung TV - Ping-device returned: False                                                            
2021-03-14 18:16:24 DEBUG (MainThread) [custom_components.samsungtv_smart.media_player] Current state is off                             
Olen commented 3 years ago

And even more debugging...

This is what seems to be happening, at least here. When HA starts up, a websocket connection is established, and it retrieves some info. After a few messages, it receives a 'ms.channel.timeOut' message, and the websocket-connection is closed.

2021-03-14 19:33:34 DEBUG (SamsungRemote) [custom_components.samsungtv_smart.api.samsungws] {'event': 'ms.channel.timeOut'}
2021-03-14 19:33:34 DEBUG (SamsungRemote) [custom_components.samsungtv_smart.api.samsungws] Thread SamsungRemote terminated

Then, about 15 seconds later, another connection is opened, which immedately receives the same 'ms.channel.timeOut' message, and is disconnected again. This goes on for a while. And it works fine, because the code checks if there is an active connection, and ignores the comparison with the ping-timestamp if the connection is down. So the TV state stays "On".

Until, for some reason, a websocket connection is established that does NOT disconnect immediately. But we don't receive any messages over the socket either, so the "last_ping" timestamp is not updated. THEN the check above fails, because now we have an active websocket-connection, but last_ping is getting old. And the TV states goes to "Off"

And then, after aobout 2 minutes, the websocket connection dies again, TV state goes back to "On" and the dance with 'ms.channel.timeOut' starts again for a while until the whole thing repeats...

ollo69 commented 3 years ago

Real problem is that ping return True. Device status is based in ping result and not ws connection, because when TV is off ping normally fail. But seems that your TV behavior is different. Can you try to ping your TV from any PC when it is off and see what happen? May be you change some TV config parameters that cause this?

Olen commented 3 years ago

No, the problem is the opposite. The TV is On, and it responds to ping (as it should). But the status in HA intermittently changes to "Off" for ~2 minutes.

The reason is that this function returns False: https://github.com/ollo69/ha-samsungtv-smart/blob/d7ed847f0197a3ac5e68c396b92c8e136dededb1/custom_components/samsungtv_smart/media_player.py#L427

And the reason for that again is that this test returns False: https://github.com/ollo69/ha-samsungtv-smart/blob/d7ed847f0197a3ac5e68c396b92c8e136dededb1/custom_components/samsungtv_smart/api/samsungws.py#L643

And the reason that test returns False is that the ICMP-ping (self._ping.ping()) returns True AND we have a ws-connection AND self._last_ping is a timestamp from more than 10 seconds ago, so the difference is > 10 (MAX_WS_PING_INTERVAL): https://github.com/ollo69/ha-samsungtv-smart/blob/d7ed847f0197a3ac5e68c396b92c8e136dededb1/custom_components/samsungtv_smart/api/samsungws.py#L637-L643

self._last_ping is only updated if we either receive a websocket ping https://github.com/ollo69/ha-samsungtv-smart/blob/d7ed847f0197a3ac5e68c396b92c8e136dededb1/custom_components/samsungtv_smart/api/samsungws.py#L357-L359

or a websocket-message: https://github.com/ollo69/ha-samsungtv-smart/blob/d7ed847f0197a3ac5e68c396b92c8e136dededb1/custom_components/samsungtv_smart/api/samsungws.py#L366-L374

or of we send a websocket-command: https://github.com/ollo69/ha-samsungtv-smart/blob/d7ed847f0197a3ac5e68c396b92c8e136dededb1/custom_components/samsungtv_smart/api/samsungws.py#L269-L271

So at least in my case, and I guess for some of the others in this thread as well, there is an open Websocket-connection, it is just not sending or receiving any data over the connection, which means that self._last_ping is never updated, and the test on line 643 in samsungws.py returns false until the websocket connection is termintated, which happens after about 2 minutes.

I have been able to shorten this period from ~2 minutes to ~15 seconds by adding a

            self._ws_remote = None

after this line:

https://github.com/ollo69/ha-samsungtv-smart/blob/d7ed847f0197a3ac5e68c396b92c8e136dededb1/custom_components/samsungtv_smart/api/samsungws.py#L727

That will at least remove the websocket-connection properly after the first timeout, but it still does not really remove the root cause, which seems to be a problem with the websocket connection in the first place.

ollo69 commented 3 years ago

Sorry, my mistake, I understand that the problem was when the TV is off. Very great analysis, I will take some time on next days to make some checks.

Olen commented 3 years ago

Hi and thanks.

Just to verify. When I actually turn the TV off, it both stops responding to the ICMP pings, and the state from Smartthings goes to offline almost immdeliately:

At 22:14:11 I turned the TV off, and recieved this from the smartthings-api just after that:

2021-03-14 23:14:14 DEBUG (MainThread) [custom_components.samsungtv_smart.api.smartthings] {'deviceId': 'bd785386-988e-4126-b151-0abb651c938d', 'state': 'OFFLINE', 'lastUpdatedDate': '2021-03-14T22:14:11.613Z'}

It still sent a last ping-reply:

2021-03-14 23:14:14 DEBUG (SyncWorker_30) [custom_components.samsungtv_smart.api.samsungws] Output is (b'PING 10.20.0.100 (10.20.0.100): 56 data bytes\n\n--- 10.20.0.100 ping statistics ---\n1 packets transmitted, 1 packets received, 0% packet loss\nround-trip min/avg/max = 2.369/2.369/2.369 ms\n', b'')

But then the function _ping_device() in meda_player.py returns False since it also checks the state from the smartthings-api.

And a few seconds later, it also stops responding to ICMP pings:

2021-03-14 23:14:31 DEBUG (SyncWorker_6) [custom_components.samsungtv_smart.api.samsungws] Output is (b'PING 10.20.0.100 (10.20.0.100): 56 data bytes\n\n--- 10.20.0.100 ping statistics ---\n1 packets transmitted, 0 packets received, 100% packet loss\n', b'')

So it is pretty good at detecting if the TV is off based on the icmp responses and the smartthings API. But the local websocket is not reliable, at least here.

ollo69 commented 3 years ago

The real problem here is that the ws connection is not working, and this is required to send command to TV. We should understand why this happen. Is your HA in a docker configuration? Are HA and TV in the same subnet?

Olen commented 3 years ago

I am not sure why the ws connection is not working as expected. However, I wonder if it is correct to consider the TV to be off just because the ws connection has not sent or received any data in 10 seconds, if the TV still replies to ping, and smartthings report it as On....

I made a small change to the code here: https://github.com/ollo69/ha-samsungtv-smart/blob/d7ed847f0197a3ac5e68c396b92c8e136dededb1/custom_components/samsungtv_smart/api/samsungws.py#L641-L644

So instead of declaring the status to be Off, I just close the ws connection, and let it reestablish itself next time.

            difference = (call_time - self._last_ping).total_seconds()
            # result = difference < MAX_WS_PING_INTERVAL
            if difference > MAX_WS_PING_INTERVAL:
                self.stop_client()

It seems to work, and HA did not report the TV to be off for a single time for the last 4 hours while the TV was on. And as soon as I turned the TV off, HA reported it as off.

ollo69 commented 3 years ago

But are you able to control the TV from HA? Without ws it should not be possible. Web Socket implement a keep-alive message called ping-pong, and this normally work, so when the connection is open a ping is always received (and a pong is sent back). But in your case you receive a message-timeout that means that TV is closing the connection.

Olen commented 3 years ago

I am at least able to change input source on the TV and turn it off from HA. Turn on does not seem to work from HA.

I mainly use the integration to control other entities (e.g. lights, blinds etc) based on the state of the TV, not really control the TV from HA, so the main concern for me is when the state is incorrectly reported, as the lights starts blinking and the blinds go up and down seemingly at random...

Today, it seems like there are three checks that are done, and if one of them fails, the TV is reported as off.

To make it more reliable, maybe it should be implemented as a "best of three" - so if at least two of them reports "On" and maximum one reports "Off", then the state should be "On". And if (at least) two reports "Off" and no more than one reports "On", the state should be "Off"?

Yesterday, I had a case of the smartthings API reported the TV as OFFLINE, while it was still on. It came back as ONLINE on the next check, so maybe we should even have each test reported a state change twice before changing the state in HA...

And maybe also up the number of ICMP pings to at least two packets?

It will delay the state changes in HA somewhat, but should be much more reliable.

ollo69 commented 3 years ago

Does not make sense report the TV on if websocket connection is not working properly, you will have a not working media-player control for 90% percent of implemented features. The status control using SmartThings can be disabled from integration options, but the ws connection must be operative. You should check your network configuration, because Samsung TV normally do no allow control from different LAN and I think this is the reason that the ws is continually closed. Delay status change check as you suggested will generate a lot of issue because most users that want to control the TV with integration complain about long delay in status change detection. I did a lot of work to be able to detect right status as fast as possible and I don't want to introduce additional delay. At this moment the only think that make sense for me is to add a warning message when the TV report the "timeout message", suggesting to check the LAN configuration. As as I said before, websocket is a restfull protocol by implementation and client-server communication must be kept alive.
If you just need a sensor to check the TV status, you should probably configure a binary sensor based on ping platform that implement the same logic used inside the integration.

GeorgyErm commented 3 years ago

Same problem here. I have UE65MU6100 and UE45... with the same issue of constant on off status. Other libraries which work through websocket also not working properly. I suppose it began with latest TV software update (currently I have T-KTMDEUC-1290.3, BT-s). I have not changed anything in my network for months.
I noted that when TV is on (but HA shows that is off) I still have sound mode picker, but when TV is actually off sound mode picker is hidden. I hope that it can help somehow.

mmatus1112 commented 3 years ago

I have two Samsung TVs. A 55" and a 35". The 35" works like a charm! The 55" CAN be turned ON and OFF with no issue, however, the HA status of the TV is ALWAYS off (regardless of being turned ON from HA). May 4th is the last day it showed ON. HELP!

ollo69 commented 2 years ago

Closing this very old issue. Please open new one if you have specific problems, if possible adding debug log to help analyze the root cause.