Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Samsung TV's not working [Testing fix] #20795

Closed
kdschlosser opened this issue Feb 6, 2019 · 375 comments
Closed

Samsung TV's not working [Testing fix] #20795

kdschlosser opened this issue Feb 6, 2019 · 375 comments

Comments

@kdschlosser
Copy link

kdschlosser commented Feb 6, 2019

*****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.

media_player:
  - platform: samsungtv

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

"""
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()
        )

@arsaboo
Copy link
Contributor

arsaboo commented Feb 6, 2019

There is a missing , after the line vol.Optional(CONF_METHOD): cv.string. After adding the comma, I am getting the following error:

Log Details (ERROR)
Wed Feb 06 2019 15:01:28 GMT-0500 (Eastern Standard Time)
Error while setting up platform samsungtv
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity_platform.py", line 128, in _async_setup_platform
    SLOW_SETUP_MAX_WAIT, loop=hass.loop)
  File "/usr/local/lib/python3.6/asyncio/tasks.py", line 358, in wait_for
    return fut.result()
  File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/media_player/samsungtv.py", line 109, in setup_platform
    [SamsungTVDevice(host, name, description, method, uuid, config_path)]
  File "/config/custom_components/media_player/samsungtv.py", line 136, in __init__
    self._config = samsungctl.Config()
  File "/config/deps/lib/python3.6/site-packages/samsungctl/config.py", line 57, in __init__
    raise exceptions.ConfigHostError
samsungctl.exceptions.ConfigHostError: <unprintable ConfigHostError object>

My TV is UN75NU8000.

@kdschlosser
Copy link
Author

I updated the code in the first post to solve both problems.

@arsaboo
Copy link
Contributor

arsaboo commented Feb 6, 2019

UPNP errors now:

Log Details (ERROR)
Wed Feb 06 2019 15:13:35 GMT-0500 (Eastern Standard Time)
Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity_platform.py", line 352, in _async_add_entity
    await entity.async_update_ha_state()
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 239, in async_update_ha_state
    attr = self.state_attributes or {}
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in state_attributes
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in <dictcomp>
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/config/custom_components/media_player/samsungtv.py", line 302, in volume_level
    volume = self.get_remote().volume
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/__init__.py", line 1215, in volume
    if not self.connected:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/__init__.py", line 30, in connected
    self._connect_upnp()
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/__init__.py", line 37, in _connect_upnp
    if not self._connected and self.power:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 123, in __getattr__
    if item in self._devices:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 123, in __getattr__
    if item in self._devices:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 123, in __getattr__
    if item in self._devices:
  [Previous line repeated 322 more times]
RecursionError: maximum recursion depth exceeded

Are you on Home Assistant Discord?

@kdschlosser
Copy link
Author

Are you on Home Assistant Discord?

dunno what that is.

can you do me a favor. please attach this file to a post. samsungctl/upnp/__init__.py

@arsaboo
Copy link
Contributor

arsaboo commented Feb 6, 2019

Here it is https://hastebin.com/efuzucutiw.rb

@arsaboo
Copy link
Contributor

arsaboo commented Feb 6, 2019

Discord has Home Assistant chat server, easy to coordinate https://www.home-assistant.io/help/

Here's the Discord server link: https://discord.gg/6JJ3Rb

@kdschlosser
Copy link
Author

Nevermind on that last post.

I am not trying to be rude at all. but I can see you did not follow my directions.
This is the reason why I cannot stress enough to FOLLOW DIRECTIONS

it clearly states in the first post.

DO THIS FIRST

we are going to want to clean out any installed versions of the current samsungctl library. you can do this from a command prompt (shell)

pip uninstall samsungctl

I have updated some code of the code in samsungctl and the new code needs to be downloaded. and installed. I really would prefer if you also installed it from the command line using

pip install --no-cache-dir "https://github.com/kdschlosser/samsungctl/archive/develop.zip#samsungctl==0.8.0b"

this will make sure it gets installed without using a cached copy of it that may be on your system

You have an old copy of samsungctl that is being used. that is why you are getting the error.

@arsaboo
Copy link
Contributor

arsaboo commented Feb 6, 2019

Let me reinstall Hassio afresh and test it out again. Gimme 10 min.

@arsaboo
Copy link
Contributor

arsaboo commented Feb 6, 2019

Ok....started afresh and now I see the entity created 🎉

I have not tested anything yet. But I see the media_player entity, which is huge progress :)

@kdschlosser
Copy link
Author

I am going nutz over here trying to locate the problem. and i have not been able to come up with anything. I even coded up a replica of the process that is taking place and it runs fine.

you got me on this one. But it appears as tho you have has some progress. and there was possibly something latent kicking about somewhere causing the issue.

@arsaboo
Copy link
Contributor

arsaboo commented Feb 6, 2019

I think there is definitely something wrong here. After restarting I am getting the same UPNP errors.

Log Details (ERROR)
Wed Feb 06 2019 16:58:13 GMT-0500 (Eastern Standard Time)
Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity_platform.py", line 352, in _async_add_entity
    await entity.async_update_ha_state()
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 239, in async_update_ha_state
    attr = self.state_attributes or {}
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in state_attributes
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in <dictcomp>
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/config/custom_components/media_player/samsungtv.py", line 258, in source
    source = self.get_remote().source
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/__init__.py", line 950, in source
    if not self.connected:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/__init__.py", line 30, in connected
    self._connect_upnp()
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/__init__.py", line 37, in _connect_upnp
    if not self._connected and self.power:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 123, in __getattr__
    if item in self._devices:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 123, in __getattr__
    if item in self._devices:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 123, in __getattr__
    if item in self._devices:
  [Previous line repeated 322 more times]
RecursionError: maximum recursion depth exceeded

Not sure if this may be causing it, but I am using a Sonos Playbase for audio. I know it is frustrating

@kdschlosser
Copy link
Author

here is what I am going to do. I will bump the version on the develop branch and update the code in the first post to use the new version.

@kdschlosser
Copy link
Author

ok I did the version bump.

@arsaboo
Copy link
Contributor

arsaboo commented Feb 7, 2019

So, unfortunately, the same issue, it worked after I put the code in for the first time. But after restarting HA, I get the same UPNP errors:

Log Details (ERROR)
Wed Feb 06 2019 15:47:31 GMT-0500 (Eastern Standard Time)
Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 239, in async_update_ha_state
    attr = self.state_attributes or {}
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in state_attributes
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in <dictcomp>
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/config/custom_components/media_player/samsungtv.py", line 302, in volume_level
    volume = self.get_remote().volume
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/__init__.py", line 1215, in volume
    if not self.connected:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/__init__.py", line 30, in connected
    self._connect_upnp()
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/__init__.py", line 37, in _connect_upnp
    if not self._connected and self.power:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 123, in __getattr__
    if item in self._devices:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 123, in __getattr__
    if item in self._devices:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 123, in __getattr__
    if item in self._devices:
  [Previous line repeated 323 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object

@arsaboo
Copy link
Contributor

arsaboo commented Feb 7, 2019

If you are on Discord (https://discord.gg/6JJ3Rb) it will be easier to debug. I am at home and can work on it in real-time.

@kdschlosser
Copy link
Author

my question is what is happening when you restart.. the code that is getting loaded is changing somehow

I do not know anything about your setup. but is there a possibility of some old copy of samsungctl kicking about in some other python installations site-packags folder?.

as an example. with another project that i work on. it uses python 2.7 but it is all set up as an executable. so technically speaking there is no python installation when you install it. But. if you install python 2.7 my program will load the site-packages directory from that python installation.

Now the reason why it works right after installation is because the neew version gets plopped in the begining of the search order. once you restart the program it is no longer going to be at the beginning of that search order.

I have also run into issues because of mixes installation types. example.

if you run python setup.py install it will install the library but you get either a file or a folder name that ends with .egg but if you do the install using pip that is not the case. the wacky thing is if you install via pip after you have already installed using python setup.py install you will end up with 2 installations.. and pip gets all mucked up when removing it.

it's a strange thing.

@kdschlosser
Copy link
Author

I am going to add some information printouts. like the location of the library and the version.

@kdschlosser
Copy link
Author

OK i updated the code in the first post to give us a printout of what is going on.

@arsaboo
Copy link
Contributor

arsaboo commented Feb 7, 2019

Here you go (had to change to error as info is not logged by default):

2019-02-07 03:14:30 ERROR (SyncWorker_7) [custom_components.media_player.samsungtv] samsungctl version: 0.8.1b
2019-02-07 03:14:30 ERROR (SyncWorker_7) [custom_components.media_player.samsungtv] samsungctl location: /config/deps/lib/python3.6/site-packages/samsungctl
2019-02-07 03:14:30 ERROR (SyncWorker_7) [custom_components.media_player.samsungtv] Samsung TV 192.168.2.252 added as 'Living Room TV'
2019-02-07 03:14:31 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity_platform.py", line 352, in _async_add_entity
    await entity.async_update_ha_state()
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 239, in async_update_ha_state
    attr = self.state_attributes or {}
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in state_attributes
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in <dictcomp>
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/config/custom_components/media_player/samsungtv.py", line 305, in volume_level
    volume = self.get_remote().volume
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/__init__.py", line 1215, in volume
    if not self.connected:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/__init__.py", line 30, in connected
    self._connect_upnp()
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/__init__.py", line 37, in _connect_upnp
    if not self._connected and self.power:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 123, in __getattr__
    if item in self._devices:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 123, in __getattr__
    if item in self._devices:
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 123, in __getattr__
    if item in self._devices:
  [Previous line repeated 322 more times]
RecursionError: maximum recursion depth exceeded

@arsaboo
Copy link
Contributor

arsaboo commented Feb 7, 2019

That is the whole log - I did not modify anything. The custom_component is how you test stuff in HA when it is not officially implemented, which is the case here.

@arsaboo
Copy link
Contributor

arsaboo commented Feb 7, 2019

What are you looking for specifically? My guess is once the entity is added, it tries to get all the properties and that is where the error appears.

Is there a way to eliminate UPNP (for now) to make sure that the basic media player works?

@kdschlosser
Copy link
Author

give it a try again. delete samsungctl first. I updated the code in my repository

@arsaboo
Copy link
Contributor

arsaboo commented Feb 7, 2019

019-02-07 03:30:18 ERROR (SyncWorker_2) [custom_components.media_player.samsungtv] samsungctl version: 0.8.1b
2019-02-07 03:30:18 ERROR (SyncWorker_2) [custom_components.media_player.samsungtv] samsungctl location: /config/deps/lib/python3.6/site-packages/samsungctl
2019-02-07 03:30:18 ERROR (SyncWorker_2) [custom_components.media_player.samsungtv] Samsung TV 192.168.2.252 added as 'Living Room TV'
2019-02-07 03:30:19 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity_platform.py", line 352, in _async_add_entity
    await entity.async_update_ha_state()
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 239, in async_update_ha_state
    attr = self.state_attributes or {}
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in state_attributes
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in <dictcomp>
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/config/custom_components/media_player/samsungtv.py", line 305, in volume_level
    volume = self.get_remote().volume
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 133, in __getattr__
    raise AttributeError(item)
AttributeError: volume
2019-02-07 03:30:30 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 239, in async_update_ha_state
    attr = self.state_attributes or {}
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in state_attributes
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in <dictcomp>
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/config/custom_components/media_player/samsungtv.py", line 305, in volume_level
    volume = self.get_remote().volume
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 133, in __getattr__
    raise AttributeError(item)
AttributeError: volume
2019-02-07 03:30:41 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 239, in async_update_ha_state
    attr = self.state_attributes or {}
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in state_attributes
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in <dictcomp>
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/config/custom_components/media_player/samsungtv.py", line 305, in volume_level
    volume = self.get_remote().volume
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 133, in __getattr__
    raise AttributeError(item)
AttributeError: volume
2019-02-07 03:30:52 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 239, in async_update_ha_state
    attr = self.state_attributes or {}
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in state_attributes
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in <dictcomp>
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/config/custom_components/media_player/samsungtv.py", line 305, in volume_level
    volume = self.get_remote().volume
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 133, in __getattr__
    raise AttributeError(item)
AttributeError: volume
2019-02-07 03:31:03 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 239, in async_update_ha_state
    attr = self.state_attributes or {}
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in state_attributes
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in <dictcomp>
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/config/custom_components/media_player/samsungtv.py", line 305, in volume_level
    volume = self.get_remote().volume
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 133, in __getattr__
    raise AttributeError(item)
AttributeError: volume

@arsaboo
Copy link
Contributor

arsaboo commented Feb 7, 2019

Just for kicks, I removed all the volume and source related code from the component and it kinda works now. The state is still messed up, but no errors.

@kdschlosser
Copy link
Author

do me a favor. do not modify this one. try it first. so you ar going to have to return the changes you made back to the way they were.

I updated the develop branch of samsungctl. give it a go and see how you make out.

@arsaboo
Copy link
Contributor

arsaboo commented Feb 7, 2019

Slightly different error this time, but still not working.

2019-02-07 13:08:30 ERROR (MainThread) [homeassistant.core] Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity_platform.py", line 352, in _async_add_entity
    await entity.async_update_ha_state()
  File "/usr/local/lib/python3.6/site-packages/homeassistant/helpers/entity.py", line 239, in async_update_ha_state
    attr = self.state_attributes or {}
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in state_attributes
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/usr/local/lib/python3.6/site-packages/homeassistant/components/media_player/__init__.py", line 787, in <dictcomp>
    in ATTR_TO_PROPERTY if getattr(self, attr) is not None
  File "/config/custom_components/media_player/samsungtv.py", line 305, in volume_level
    volume = self.get_remote().volume
  File "/config/deps/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 133, in __getattr__
    raise AttributeError(item)
AttributeError: volume

Wondering if there is no value for volume = self.get_remote().volume when using a soundbar/receiver. Maybe guard against that.

@ThaStealth
Copy link
Contributor

Okay, just a minor thing and not important for now at all, but I was setting everything up and I noticed the error below, it is just something to beautify the code:

The TV is not connected to the network (not at home now so can't investigate why it isn't), but I was doing some preparation work for later today

So I got this error (which is correct):

Error doing job: Task exception was never retrieved
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/samsungctl/remote_legacy.py", line 84, in open
    self.sock.connect((self.config.host, self.config.port))
OSError: [Errno 113] No route to host

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/src/app/homeassistant/helpers/entity_platform.py", line 352, in _async_add_entity
    await entity.async_update_ha_state()
  File "/usr/src/app/homeassistant/helpers/entity.py", line 232, in async_update_ha_state
    state = self.state
  File "/usr/src/app/homeassistant/components/media_player/samsungtv.py", line 224, in state
    power = self.get_remote().power
  File "/usr/src/app/homeassistant/components/media_player/samsungtv.py", line 178, in get_remote
    self._remote.open()
  File "/usr/local/lib/python3.6/site-packages/samsungctl/utils.py", line 24, in wrapper
    return func(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/samsungctl/remote_legacy.py", line 87, in open
    raise RuntimeError('Unable to pair with TV.. Is the TV on?!?')
RuntimeError: Unable to pair with TV.. Is the TV on?!?

But then it continues and gives this error every ~10 sec:

Update for media_player.living_room_tv fails
Traceback (most recent call last):
  File "/usr/src/app/homeassistant/helpers/entity.py", line 221, in async_update_ha_state
    await self.async_device_update()
  File "/usr/src/app/homeassistant/helpers/entity.py", line 349, in async_device_update
    await self.hass.async_add_executor_job(self.update)
  File "/usr/local/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/usr/src/app/homeassistant/components/media_player/samsungtv.py", line 167, in update
    power = self.get_remote().power
  File "/usr/local/lib/python3.6/site-packages/samsungctl/upnp/UPNP_Device/upnp_class.py", line 131, in __getattr__
    return self.__class__.__dict__[item].fget(self)
  File "/usr/local/lib/python3.6/site-packages/samsungctl/utils.py", line 44, in wrapper
    result = func(*args, **kwargs)
  File "/usr/local/lib/python3.6/site-packages/samsungctl/remote_legacy.py", line 45, in power
    self.sock.self.sock.setblocking(0)
AttributeError: 'socket' object has no attribute 'self'

Perhaps you can enhance to code to check if the socket is actually open before trying to do something with it?

@arsaboo
Copy link
Contributor

arsaboo commented Feb 7, 2019

@kdschlosser Also, see #4210 for the I/O issues. We are doing a lot of I/O inside properties, which should be avoided.

@rome1983
Copy link

rome1983 commented Jul 12, 2019

on hassio all I get is this even if I manually put samsungctl folder there.
I'm trying to get this working on a 55JS8500

Fri Jul 12 2019 12:43:02 GMT-0500 (Central Daylight Time)
Error while setting up platform samsungtv
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 126, in _async_setup_platform
    SLOW_SETUP_MAX_WAIT)
  File "/usr/local/lib/python3.7/asyncio/tasks.py", line 416, in wait_for
    return fut.result()
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/samsungtv/media_player.py", line 102, in setup_platform
    from samsungctl.upnp.discover import auto_discover
ModuleNotFoundError: No module named 'samsungctl.upnp'

@andrew176
Copy link

on hassio all I get is this even if I manually put samsungctl folder there.
I'm trying to get this working on a 55JS8500

Fri Jul 12 2019 12:43:02 GMT-0500 (Central Daylight Time)
Error while setting up platform samsungtv
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/entity_platform.py", line 126, in _async_setup_platform
    SLOW_SETUP_MAX_WAIT)
  File "/usr/local/lib/python3.7/asyncio/tasks.py", line 416, in wait_for
    return fut.result()
  File "/usr/local/lib/python3.7/concurrent/futures/thread.py", line 57, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/config/custom_components/samsungtv/media_player.py", line 102, in setup_platform
    from samsungctl.upnp.discover import auto_discover
ModuleNotFoundError: No module named 'samsungctl.upnp'

I get the ModuleNotFoundError: No module named 'samsungctl.upnp' error too

@timdonovanuk
Copy link

Could someone please provide up to date installation instructions? They're very confusing from earlier, i.e.

  • are we replacing the lines
        from samsungctl import exceptions
        from samsungctl import Remote

with

   from custom_components.samsungctl import exceptions
   from custom_components.samsungctl import Remote

or overwriting?

Thank you.

@timdonovanuk
Copy link

timdonovanuk commented Jul 22, 2019

Okay, think I've got it half figured out

  1. Create a folder /homeassistant/custom_components/samsungtv
  2. Copy the files from https://github.com/home-assistant/home-assistant/tree/dev/homeassistant/components/samsungtv into /homeassistant/custom_components/samsungtv
  3. Create a folder /homeassistant/custom_components/samsungctl
  4. Copy the files from https://github.com/kdschlosser/samsungctl/tree/develop/samsungctl into /homeassistant/custom_components/samsungctl
  5. Add
 media_player:
 - platform: samsungtv
   host: <whatever> (not sure if host is needed but it wouldn't accept the config for me without it)

Think this is everything. It now recognises the power state of my TV (again) but remote control does not work.

Edit: nah, it's not working at all. Shows On constantly.

@rome1983
Copy link

I brought a rm mini 3. WiFi ir, works perfect for 2015 series

@holdestmade
Copy link

holdestmade commented Jul 27, 2019

I gave up on trying to get Samsung TV working with this and used a nodeMCU with ir transmitter running esphome and a power monitoring plug to detect when it is switched on.

@rome1983
Copy link

Port 8000 gives me accurate on/off state

@darkopetrovic
Copy link

I'm looking in /srv/homeassistant/lib/python3.7/site-packages/homeassistant/components/media_player folder like @Brunozumba but there is no samsungtv.py file in that folder for me.

Running Hassbian v0.97.2

There is indeed a component samsungtv at /srv/homeassistant/lib/python3.7/site-packages/homeassistant/components/samsungtv with media_player.py inside. I tried to put the code from the first post from @kdschlosser but obviously didn't work: Got Failed to get platform media_player.samsungtv in the log.

What is the last direction to follow to make samsungctl to work with Home Assistant ?

Thanks.

@mukundv
Copy link

mukundv commented Sep 15, 2019

I gave up on trying to get Samsung TV working with this and used a nodeMCU with ir transmitter running esphome and a power monitoring plug to detect when it is switched on.

Same here. Using Broadlink to learn the remote and replay them.

@utech-git
Copy link

I gave up on trying to get Samsung TV working with this and used a nodeMCU with ir transmitter running esphome and a power monitoring plug to detect when it is switched on.

I gave up on trying to get Samsung TV working with this and used a nodeMCU with ir transmitter running esphome and a power monitoring plug to detect when it is switched on.

Same here. Using Broadlink to learn the remote and replay them.

Hey guys, what power monitoring plug did you use to do this?
Thanks!

@holdestmade
Copy link

I used a Popp zwave socket, don't think they are made any more but any zwave or ZigBee socket with power monitoring capabilities should work.

@dolenec
Copy link

dolenec commented Sep 24, 2019

So.. should I try this solution (component) or not?
Currently on HA version 0.99.2 my 2 Samsung TV are not showing status at all.. Using in-build solution..

My TV:
UE43MU6172U
UE40H6200AK

@roberodin
Copy link

After HA updates, I have decided to create a custom component, it is working on the latest version of HA 0.99.3, I have uploaded the code to:

https://github.com/roberodin/ha-samsungtv-custom

I hope it helps you.

@xchwarze
Copy link

Hello!
I use this fork https://github.com/xchwarze/ha-samsungtv-custom/releases in 2016+ tv
All TizenOS tv should work

@roberodin
Copy link

roberodin commented Oct 17, 2019

Hi, I have uploaded the latest version 2.0.1 in HACS. If not working by default samsungctl protocol, try changing it to WS protocol for 2016+ TVs model…

https://github.com/roberodin/ha-samsungtv-custom

@sermayoral
Copy link
Contributor

Wow! That's great!!

We can test the HACS version and debug it until it is perfect!!

Thanks guys. Great work.

@pablolassalle
Copy link

@sermayoral Have you been able to make it work on an encrypted tv? Can you please help me with it?

@roberodin
Copy link

Update to version 3.0.0 and try the new protocols:
-ws (fixed from @xchwarze)
-ctl_beta
-ctl_qled

https://github.com/roberodin/ha-samsungtv-custom

@sermayoral
Copy link
Contributor

sermayoral commented Oct 18, 2019

@pablolassalle I have not tested this addon yet, but it sounds great.

Anyway. What is your problem? What is your TV's model? Mine is H6400 of 2014.

@roberodin Do you know if ha-samsungtv-custom works with encrypted tvs like H6400?

@pablolassalle
Copy link

@sermayoral my tv is a J5500 from 2015, my tv does require a pin for pairing. I think also your tv does require it. Problem is I have never that blue box on my tv asking for pairing with xxxx pin, which I should enter on my HOMEASSISTANT.
At the momment I am using a custom samsungtv I have found somewehere, but it only shows me if the TV is ON or OFF. I can´t control anything.

@Bosken85
Copy link

Awesome... i've been looking for a solution for months now. I can confirm that most things are working on the Q6 2019 samsung tv. Thanks a lot guys :)

@PhAzE-Variance
Copy link

@roberodin I'm also curious if this works on the 2014/2015 tv models (H and J).

Those used an encrypted connection, which I believe the original component on this git did support for a while.

@sbienia
Copy link

sbienia commented Oct 22, 2019

I have H series TV. I tried multiple components and they never work as expected

@poisondima
Copy link

@roberodin This is something incredible! I can control it. Thanks for this component.
Samsung 5 Series (32) (UE32M5500) 2017 TV.
Settings:
port: 8002
protocol: ws

@sermayoral
Copy link
Contributor

@roberodin. Can you help us with encrypted TVs? For example 2014 H Series? @kdschlosser got it working. Those different is to introduce the pin when TV shows you...

Thank you!

@LordXun
Copy link

LordXun commented Oct 29, 2019

.Hey Guys,
I've managed to get it working with the Samsung EU65NU8042 with respect to one "small" problem. TV asks me every 15 seconds if I allow the device to be connected. If I click yes, than, for 14 seconds it works, but after that, I need to agree once again... What the hell? :-)
My config is as follow:

- platform: samsungtv_custom
  host: 192.168.1.111 (correct one)
  port: 8002
  name: 'SamsungTv'

Any suggestions? Should I add MAC address, as I've seen in some configs that you have posted here?

@magicmatt007
Copy link

Sorry for the beginners question:

My home assistant is installed as "hassio" on a raspberry pi. I think on this installation, there is no folder "/homeassistant/components/media_player/samsungtv.py". Right?

If so, is there any other alternative measure to get this fix from kdschlosser installed on hassio?

Many thanks!

@rome1983
Copy link

@magicmatt007 this component doesn’t work anymore and no longer under development.

@hosquiat
Copy link

@magicmatt007 this component doesn’t work anymore and no longer under development.

Well that sucks.

@Houzzella
Copy link

Wake on lan works on wireless. The following lines will work. Do not add any port. The format is important that one needs to follow.

Enable WOL

wake_on_lan:

#SAMSUNG TV in Living Room
media_player:

  • platform: samsungtv
    host: x.x.x.x
    name: Living Room TV
    turn_on_action:
    service: wake_on_lan.send_magic_packet
    data:
    mac: 00:00:00:00:00:00

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests