diff --git a/custom_components/samsungtv_custom/media_player.py b/custom_components/samsungtv_custom/media_player.py index 5513e17..04798ca 100644 --- a/custom_components/samsungtv_custom/media_player.py +++ b/custom_components/samsungtv_custom/media_player.py @@ -26,6 +26,7 @@ SUPPORT_TURN_ON, SUPPORT_VOLUME_MUTE, SUPPORT_VOLUME_STEP, + SUPPORT_VOLUME_SET, ) from homeassistant.const import ( CONF_HOST, @@ -55,6 +56,7 @@ SUPPORT_PAUSE | SUPPORT_VOLUME_STEP | SUPPORT_VOLUME_MUTE + | SUPPORT_VOLUME_SET | SUPPORT_PREVIOUS_TRACK | SUPPORT_SELECT_SOURCE | SUPPORT_NEXT_TRACK @@ -131,8 +133,9 @@ def __init__(self, host, port, name, timeout, mac, uuid, sourcelist): self._name = name self._mac = mac self._uuid = uuid - # Assume that the TV is not muted + # Assume that the TV is not muted and volume is 0 self._muted = False + self._volume = 0 # Assume that the TV is in Play mode self._playing = True self._state = None @@ -214,8 +217,15 @@ def state(self): @property def is_volume_muted(self): """Boolean if volume is currently muted.""" + self._muted = self._remote.get_mute() return self._muted + @property + def volume_level(self): + """Volume level of the media player (0..1).""" + self._volume = int(self._remote.get_volume()) / 100 + return str(self._volume) + @property def source_list(self): """List of available input sources.""" @@ -251,6 +261,10 @@ def volume_down(self): def mute_volume(self, mute): """Send mute command.""" self.send_key("KEY_MUTE") + + def set_volume_level(self, volume): + """Set volume level, range 0..1.""" + self._remote.set_volume(int(volume*100)) def media_play_pause(self): """Simulate play pause media player.""" diff --git a/custom_components/samsungtv_custom/samsungtvws/remote.py b/custom_components/samsungtv_custom/samsungtvws/remote.py index a9322be..3e87547 100644 --- a/custom_components/samsungtv_custom/samsungtvws/remote.py +++ b/custom_components/samsungtv_custom/samsungtvws/remote.py @@ -25,6 +25,8 @@ import time import ssl import websocket +import xml.etree.ElementTree as ET +import requests class SamsungTVWS(): @@ -40,6 +42,9 @@ def __init__(self, host, token=None, token_file=None, port=8002, timeout=None, k self.key_press_delay = key_press_delay self.name = name self.connection = None + + self.mute = False + self.volume = 0 def __exit__(self, type, value, traceback): self.close() @@ -260,3 +265,48 @@ def yellow(self): def blue(self): self.send_key('KEY_BLUE') + + def SOAPrequest(self, action, arguments, protocole): + headers = {'SOAPAction': '"urn:schemas-upnp-org:service:{protocole}:1#{action}"'.format(action=action, protocole=protocole), 'content-type': 'text/xml'} + body = """ + + + + 0 + {arguments} + + + """.format(action=action, arguments=arguments, protocole=protocole) + response = None + try: + response = requests.post("http://{host}:9197/upnp/control/{protocole}1".format(host=self.host, protocole=protocole), data=body, headers=headers, timeout=0.1) + response = response.content + except: + pass + return response + + def get_volume(self): + response = self.SOAPrequest('GetVolume', "Master", 'RenderingControl') + if response is not None: + volume_xml = response.decode('utf8') + tree = ET.fromstring(volume_xml) + for elem in tree.iter(tag='CurrentVolume'): + self.volume = elem.text + return self.volume + + + def set_volume(self, volume): + self.SOAPrequest('SetVolume', "Master{}".format(volume), 'RenderingControl') + + def get_mute(self): + response = self.SOAPrequest('GetMute', "Master", 'RenderingControl') + if response is not None: + # mute_xml = response.decode('utf8') + tree = ET.fromstring(response.decode('utf8')) + for elem in tree.iter(tag='CurrentMute'): + mute = elem.text + if (int(mute) == 0): + self.mute = False + else: + self.mute = True + return self.mute