Support for notifications
Would be great to be able to send notifications to the TV
This would be awesome but the question is if the api that the tv's provides supports this functionality.
Tested on B-series successfully
Could everybody with a different model please give it a try
"""
Send notifications to Samsung TV via uPnP MessageBox service
Tested on B-Series TV
UPDATE: Added rendering control
by tuxuser (2018/07/21) https://github.com/tuxuser
"""
import sys
import argparse
import requests
import upnpclient
from datetime import datetime
from lxml import etree
class SamsungTvNotifier(object):
def __init__(self, ip, port):
self._ip = ip
self._port = port
# MessageBox standard parameters
self._message_id = 0
self.message_type = 'text/xml'
# RenderingControl standard parameters
self.instance_id = 0
self.notify_service = None
self.rendering_service = None
@property
def message_id(self):
self._message_id += 1
return str(self._message_id)
@staticmethod
def get_etree_without_root(root_node):
ret = b''
for element in root_node:
ret += etree.tostring(element)
return ret.decode('utf-8')
@staticmethod
def build_sms_notification(sms_text, sender_name, sender_number, receiver_name, receiver_number,
receive_dt=datetime.now()):
root = etree.Element("root")
etree.SubElement(root, "Category").text = "SMS"
etree.SubElement(root, "DisplayType").text = "Maximum"
receive_time = etree.SubElement(root, "ReceiveTime")
etree.SubElement(receive_time, "Date").text = receive_dt.strftime('%Y-%m-%d')
etree.SubElement(receive_time, "Time").text = receive_dt.strftime('%H:%M:%S')
receiver = etree.SubElement(root, "Receiver")
etree.SubElement(receiver, "Number").text = receiver_number
etree.SubElement(receiver, "Name").text = receiver_name
sender = etree.SubElement(root, "Sender")
etree.SubElement(sender, "Number").text = sender_number
etree.SubElement(sender, "Name").text = sender_name
etree.SubElement(root, "Body").text = sms_text
return SamsungTvNotifier.get_etree_without_root(root)
@staticmethod
def build_call_notification(caller_name, caller_number, callee_name, callee_number,
call_dt=datetime.now()):
root = etree.Element("root")
etree.SubElement(root, "Category").text = "Incoming Call"
etree.SubElement(root, "DisplayType").text = "Maximum"
call_time = etree.SubElement(root, "CallTime")
etree.SubElement(call_time, "Date").text = call_dt.strftime('%Y-%m-%d')
etree.SubElement(call_time, "Time").text = call_dt.strftime('%H:%M:%S')
callee = etree.SubElement(root, "Callee")
etree.SubElement(callee, "Number").text = callee_number
etree.SubElement(callee, "Name").text = callee_name
caller = etree.SubElement(root, "Caller")
etree.SubElement(caller, "Number").text = caller_number
etree.SubElement(caller, "Name").text = caller_name
return SamsungTvNotifier.get_etree_without_root(root)
@staticmethod
def build_schedule_notification(subject, location, schedule_text,
owner_name, owner_number,
start_dt, end_dt):
root = etree.Element("root")
etree.SubElement(root, "Category").text = "Schedule Reminder"
etree.SubElement(root, "DisplayType").text = "Maximum"
start_time = etree.SubElement(root, "StartTime")
etree.SubElement(start_time, "Date").text = start_dt.strftime('%Y-%m-%d')
etree.SubElement(start_time, "Time").text = start_dt.strftime('%H:%M:%S')
owner = etree.SubElement(root, "Owner")
etree.SubElement(owner, "Number").text = owner_number
etree.SubElement(owner, "Name").text = owner_name
etree.SubElement(root, "Subject").text = subject
end_time = etree.SubElement(root, "EndTime")
etree.SubElement(end_time, "Date").text = end_dt.strftime('%Y-%m-%d')
etree.SubElement(end_time, "Time").text = end_dt.strftime('%H:%M:%S')
etree.SubElement(root, "Location").text = location
etree.SubElement(root, "Body").text = schedule_text
return SamsungTvNotifier.get_etree_without_root(root)
def _initialize_notification(self):
messagebox_url = 'http://{addr}:{port}/pmr/PersonalMessageReceiver.xml'.format(
addr=self._ip, port=self._port
)
try:
device = upnpclient.Device(messagebox_url)
except requests.exceptions.ConnectTimeout as e:
raise Exception('Device looks unavailable! msg: {0}'.format(e))
service = device.service_map.get('MessageBoxService')
if not service:
raise Exception('MessageBoxService not found')
return service
def _initialize_rendering(self):
renderer_url = 'http://{addr}:{port}/dmr/SamsungMRDesc.xml'.format(
addr=self._ip, port=self._port
)
try:
device = upnpclient.Device(renderer_url)
except requests.exceptions.ConnectTimeout as e:
raise Exception('Device looks unavailable! msg: {0}'.format(e))
service = device.service_map.get('RenderingControl')
if not service:
raise Exception('RenderingControk not found')
return service
def send_notification(self, notification_body):
if not self.notify_service:
self.notify_service = self._initialize_notification()
try:
add_message = self.notify_service['AddMessage']
except KeyError:
raise Exception('Notification action \'AddMessage\' is unavailable')
return add_message(MessageID=self.message_id, MessageType=self.message_type,
Message=notification_body)
def send_rendering_change(self, endpoint, **kwargs):
if not self.rendering_service:
self.rendering_service = self._initialize_rendering()
try:
rendering_action = self.rendering_service[endpoint]
except KeyError:
raise Exception('Rendering control \'{0}\' not existing!'.format(endpoint))
return rendering_action(InstanceID=self.instance_id, **kwargs)
def list_presets(self):
return self.send_rendering_change('ListPresets')
def select_preset(self, preset_name):
return self.send_rendering_change('SelectPreset', PresetName=preset_name)
def get_mute(self, channel='Master'):
resp = self.send_rendering_change('GetMute', Channel=channel)
return resp['CurrentMute']
def set_mute(self, do_mute, channel='Master'):
if do_mute:
desired_mute = 'true'
else:
desired_mute = 'false'
return self.send_rendering_change('SetMute', Channel=channel, DesiredMute=desired_mute)
def get_volume(self, channel='Master'):
resp = self.send_rendering_change('GetVolume', Channel=channel)
return resp['CurrentVolume']
def set_volume(self, volume, channel='Master'):
return self.send_rendering_change('SetVolume', Channel=channel, DesiredVolume=volume)
def get_brightness(self):
resp = self.send_rendering_change('GetBrightness')
return resp['CurrentBrightness']
def set_brightness(self, brightness):
return self.send_rendering_change('SetBrightness', DesiredBrightness=brightness)
def get_constrast(self):
resp = self.send_rendering_change('GetContrast')
return resp['CurrentContrast']
def set_constrast(self, constrast):
return self.send_rendering_change('SetContrast', DesiredContrast=constrast)
def get_sharpness(self):
resp = self.send_rendering_change('GetSharpness')
return resp['CurrentSharpness']
def set_sharpness(self, sharpness):
return self.send_rendering_change('SetSharpness', DesiredSharpness=sharpness)
def get_color_temperature(self):
resp = self.send_rendering_change('GetColorTemperature')
return resp['CurrentColorTemperature']
def set_color_temperature(self, color_temp):
return self.send_rendering_change('SetColorTemperature', DesiredColorTemperature=color_temp)
def get_slideshow_effect(self):
resp = self.send_rendering_change('X_GetSlideShowEffect')
return resp['SlideShowEffect']
def set_slideshow_effect(self, effect):
return self.send_rendering_change('X_SetSlideShowEffect', SlideShowEffect=effect)
def get_image_scale(self):
return self.send_rendering_change('X_GetImageScale')
def set_image_scale(self):
return self.send_rendering_change('X_SetImageScale')
def get_image_rotation(self):
return self.send_rendering_change('X_GetImageRotation')
def set_image_rotation(self):
return self.send_rendering_change('X_SetImageRotation')
if __name__ == '__main__':
parser = argparse.ArgumentParser('Samsung TV Notifier')
parser.add_argument('ip',
help='IP address of target Samsung TV')
parser.add_argument('--port', '-p', default=52235,
help='Port of uPnP service')
args = parser.parse_args()
notifier = SamsungTvNotifier(args.ip, args.port)
body = notifier.build_sms_notification('Hello, I sent you a SMS', 'tuxuser', '1337', 'samsungctl', '123')
ret = notifier.send_notification(body)
notifier.set_mute(False)
On my UE55MU6172 doesn't work :(
root@HomeAssistant:~/tizen# ./send.py --port 8001 192.168.10.12
Traceback (most recent call last):
File "./send.py", line 254, in
Defalt Port:
root@johnsubuntu:~/scripts# python send.py 10.0.0.92
Traceback (most recent call last):
File "send.py", line 252, in
Port 8001:
root@johnsubuntu:~/scripts# python send.py --port 8001 10.0.0.92
Traceback (most recent call last):
File "send.py", line 252, in
Not working for me either. Model: KS8000
Is this possible? Any progress?
Bought a 55" Samsung TV recently and it would be really great to get this working so I can be reminded about stuffs. Please and thank you <3
I got the notification pop up to allow my device on my UN75CU7000FXZA but then I get the same 404 error as @tomhash2. Any updates?