From 39e8a704eade8b5f0e9132a78cf894aa00282826 Mon Sep 17 00:00:00 2001 From: Stefan Schorn Date: Sun, 1 Mar 2020 13:18:53 +0100 Subject: [PATCH 1/3] media player --- .../samsungtv_custom/media_player.py | 39 ++++++++++++++++--- 1 file changed, 33 insertions(+), 6 deletions(-) diff --git a/custom_components/samsungtv_custom/media_player.py b/custom_components/samsungtv_custom/media_player.py index 2f4fe02..598ea51 100644 --- a/custom_components/samsungtv_custom/media_player.py +++ b/custom_components/samsungtv_custom/media_player.py @@ -81,6 +81,8 @@ vol.Optional(CONF_SOURCELIST): cv.string, vol.Optional(CONF_APPLIST): cv.string, vol.Optional(CONF_PROTOCOL): cv.string, + vol.Optional(CONF_ID): cv.string, + vol.Optional(CONF_TOKEN): cv.string, } ) @@ -116,6 +118,8 @@ def setup_platform(hass, config, add_entities, discovery_info=None): name = config.get(CONF_NAME) mac = config.get(CONF_MAC) timeout = config.get(CONF_TIMEOUT) + uuid = config.get(CONF_ID) + token = config.get(CONF_TOKEN) elif discovery_info is not None: tv_name = discovery_info.get("name") model = discovery_info.get("model_name") @@ -142,7 +146,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): elif protocol == "ws": add_entities([SamsungTVDeviceWS(host, port, name, timeout, mac, uuid, sourcelist)]) else: - add_entities([SamsungTVDevice(host, port, name, timeout, mac, uuid, sourcelist, protocol)]) + add_entities([SamsungTVDevice(host, port, name, timeout, mac, uuid, sourcelist, protocol, token)]) _LOGGER.info("Samsung TV %s:%d added as '%s'", host, port, name) else: @@ -152,7 +156,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None): class SamsungTVDevice(MediaPlayerDevice): """Representation of a Samsung TV.""" - def __init__(self, host, port, name, timeout, mac, uuid, sourcelist, protocol): + def __init__(self, host, port, name, timeout, mac, uuid, sourcelist, protocol, token): """Initialize the Samsung device.""" if protocol == "ctl_beta": from .samsungctl_080b import exceptions @@ -167,6 +171,7 @@ def __init__(self, host, port, name, timeout, mac, uuid, sourcelist, protocol): self._name = name self._mac = mac self._uuid = uuid + self._token = token self._wol = wakeonlan # Assume that the TV is not muted self._muted = False @@ -185,17 +190,34 @@ def __init__(self, host, port, name, timeout, mac, uuid, sourcelist, protocol): "port": port, "host": host, "timeout": timeout, + "token": token, } self._sourcelist = sourcelist - if self._config["port"] in (8001, 8002): + if self._token != "": + self._config["method"] = "encrypted" + elif self._config["port"] in (8001, 8002): self._config["method"] = "websocket" else: self._config["method"] = "legacy" def update(self): """Update state of device.""" - self.send_key("KEY") + if self._config["method"] == "encrypted" and self._config["port"] == 8001: + try: + r = requests.get( + "http://{}:8001/api/v2/".format(self._config["host"]), timeout=2 + ) + self._state = STATE_ON + _LOGGER.debug("State is on %s", repr(r)) + # break + except: + e = sys.exc_info()[0] + _LOGGER.debug("State is off %s", repr(e)) + self._state = STATE_OFF + + else: + self.send_key("KEY") def get_remote(self): """Create or return a remote control instance.""" @@ -207,6 +229,7 @@ def get_remote(self): def send_key(self, key): """Send a key to the tv and handles exceptions.""" + _LOGGER.debug("Send key %s", key) if self._power_off_in_progress() and key not in ("KEY_POWER", "KEY_POWEROFF"): _LOGGER.info("TV is powering off, not sending command: %s", key) return @@ -215,7 +238,12 @@ def send_key(self, key): retry_count = 1 for _ in range(retry_count + 1): try: - self.get_remote().control(key) + control_result = self.get_remote().control(key) + if not control_result: + _LOGGER.debug("Failed sending command %s. Retry!", key) + self._remote.close() + self._remote = None + self.get_remote().control(key) break except (self._exceptions_class.ConnectionClosed, BrokenPipeError): # BrokenPipe can occur when the commands is sent to fast @@ -284,7 +312,6 @@ def turn_off(self): self.send_key("KEY_POWEROFF") # Force closing of remote session to provide instant UI feedback try: - self.get_remote().close() self._remote = None except OSError: _LOGGER.debug("Could not establish connection.") From e064e72c3451e215fe9654828ee8f9b04dcc6778 Mon Sep 17 00:00:00 2001 From: Stefan Schorn Date: Sun, 1 Mar 2020 13:36:25 +0100 Subject: [PATCH 2/3] More corrections --- custom_components/samsungtv_custom/media_player.py | 3 +-- .../samsungctl_080b/remote_encrypted/__init__.py | 2 +- .../samsungtv_custom/samsungctl_080b/websocket_base.py | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/custom_components/samsungtv_custom/media_player.py b/custom_components/samsungtv_custom/media_player.py index 598ea51..bdbccce 100644 --- a/custom_components/samsungtv_custom/media_player.py +++ b/custom_components/samsungtv_custom/media_player.py @@ -212,8 +212,7 @@ def update(self): _LOGGER.debug("State is on %s", repr(r)) # break except: - e = sys.exc_info()[0] - _LOGGER.debug("State is off %s", repr(e)) + _LOGGER.debug("State is off") self._state = STATE_OFF else: diff --git a/custom_components/samsungtv_custom/samsungctl_080b/remote_encrypted/__init__.py b/custom_components/samsungtv_custom/samsungctl_080b/remote_encrypted/__init__.py index 2775dd1..fff0bd9 100644 --- a/custom_components/samsungtv_custom/samsungctl_080b/remote_encrypted/__init__.py +++ b/custom_components/samsungtv_custom/samsungctl_080b/remote_encrypted/__init__.py @@ -25,7 +25,7 @@ from ..upnp.UPNP_Device.xmlns import strip_xmlns # NOQA from ..utils import LogIt, LogItWithReturn # NOQA -logger = logging.getLogger('samsungctl') +logger = logging.getLogger(__name__) class URL(object): diff --git a/custom_components/samsungtv_custom/samsungctl_080b/websocket_base.py b/custom_components/samsungtv_custom/samsungctl_080b/websocket_base.py index 4373963..dc12753 100644 --- a/custom_components/samsungtv_custom/samsungctl_080b/websocket_base.py +++ b/custom_components/samsungtv_custom/samsungctl_080b/websocket_base.py @@ -257,7 +257,7 @@ def control(self, key, *args, **kwargs): elif self.sock is None: logger.info( - self.config.model + + self.config.host + ' -- is the TV on?!?' ) return False From a762fdea4e2565913ef1da1e9a46eb124f366063 Mon Sep 17 00:00:00 2001 From: Stefan Schorn Date: Sun, 1 Mar 2020 13:45:15 +0100 Subject: [PATCH 3/3] Added Docu --- README.md | 14 ++++++++++++++ info.md | 14 ++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/README.md b/README.md index 6bf71a4..e75efb5 100644 --- a/README.md +++ b/README.md @@ -85,6 +85,20 @@ Edit it by adding the following lines: sourcelist: '{"RaspberryPi": "KEY_HDMI2", "Chromecast": "KEY_HDMI3"}' protocol: ctl_beta ``` + ### Example configuration.yaml for ctl_beta protocol for H/J Models + ``` + media_player: + - platform: samsungtv_custom + host: IP_ADDRESS + port: (8001 or 8002) + mac: MAC_ADDRESS + sourcelist: '{"RaspberryPi": "KEY_HDMI2", "Chromecast": "KEY_HDMI3"}' + protocol: ctl_beta + token: kdsjfbsdkjbsdkjfskdjf:2 + id: 07270e01-0078-1000-8cd0-c4576e9dxxxxx + ``` + The token get be fetched via https://github.com/eclair4151/SmartCrypto + The id can be fetched vie http://IP_ADDRESS:8001/api/v2/ ### Example configuration.yaml for ctl_qled protocol ``` media_player: diff --git a/info.md b/info.md index 41eb2a5..1dca4fa 100644 --- a/info.md +++ b/info.md @@ -82,6 +82,20 @@ Edit it by adding the following lines: sourcelist: '{"RaspberryPi": "KEY_HDMI2", "Chromecast": "KEY_HDMI3"}' protocol: ctl_beta ``` + ### Example configuration.yaml for ctl_beta protocol for H/J Models + ``` + media_player: + - platform: samsungtv_custom + host: IP_ADDRESS + port: (8001 or 8002) + mac: MAC_ADDRESS + sourcelist: '{"RaspberryPi": "KEY_HDMI2", "Chromecast": "KEY_HDMI3"}' + protocol: ctl_beta + token: kdsjfbsdkjbsdkjfskdjf:2 + id: 07270e01-0078-1000-8cd0-c4576e9dxxxxx + ``` + The token get be fetched via https://github.com/eclair4151/SmartCrypto + The id can be fetched vie http://IP_ADDRESS:8001/api/v2/ ### Example configuration.yaml for ctl_qled protocol ``` media_player: