Open kylerw opened 7 years ago
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?
Would be great to be able to send notifications to the TV