-
-
Notifications
You must be signed in to change notification settings - Fork 29.3k
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
Fix Notifications for Android TV #10798
Changes from 6 commits
98bec40
a92374b
7ef6019
f87560a
56a3de9
5e5ba26
a459203
4df8316
eceb4c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,7 @@ | |
from homeassistant.components.notify import ( | ||
ATTR_TITLE, ATTR_TITLE_DEFAULT, ATTR_DATA, BaseNotificationService, | ||
PLATFORM_SCHEMA) | ||
from homeassistant.const import CONF_TIMEOUT | ||
from homeassistant.const import CONF_TIMEOUT, CONF_ICON | ||
import homeassistant.helpers.config_validation as cv | ||
|
||
_LOGGER = logging.getLogger(__name__) | ||
|
@@ -31,13 +31,16 @@ | |
DEFAULT_COLOR = 'grey' | ||
DEFAULT_INTERRUPT = False | ||
DEFAULT_TIMEOUT = 5 | ||
DEFAULT_ICON = None | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This isn't used. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Thanks for catching this. Now it is being used. :) |
||
|
||
ATTR_DURATION = 'duration' | ||
ATTR_POSITION = 'position' | ||
ATTR_TRANSPARENCY = 'transparency' | ||
ATTR_COLOR = 'color' | ||
ATTR_BKGCOLOR = 'bkgcolor' | ||
ATTR_INTERRUPT = 'interrupt' | ||
ATTR_ICON = 'icon' | ||
ATTR_FILENAME = 'filename' | ||
|
||
POSITIONS = { | ||
'bottom-right': 0, | ||
|
@@ -79,6 +82,7 @@ | |
vol.In(COLORS.keys()), | ||
vol.Optional(CONF_TIMEOUT, default=DEFAULT_TIMEOUT): vol.Coerce(int), | ||
vol.Optional(CONF_INTERRUPT, default=DEFAULT_INTERRUPT): cv.boolean, | ||
vol.Optional(CONF_ICON, default=DEFAULT_ICON): cv.string, | ||
}) | ||
|
||
|
||
|
@@ -92,16 +96,18 @@ def get_service(hass, config, discovery_info=None): | |
color = config.get(CONF_COLOR) | ||
interrupt = config.get(CONF_INTERRUPT) | ||
timeout = config.get(CONF_TIMEOUT) | ||
icon = config.get(CONF_ICON) | ||
|
||
return NFAndroidTVNotificationService( | ||
remoteip, duration, position, transparency, color, interrupt, timeout) | ||
remoteip, duration, position, transparency, color, interrupt, timeout, | ||
icon) | ||
|
||
|
||
class NFAndroidTVNotificationService(BaseNotificationService): | ||
"""Notification service for Notifications for Android TV.""" | ||
|
||
def __init__(self, remoteip, duration, position, transparency, color, | ||
interrupt, timeout): | ||
interrupt, timeout, icon): | ||
"""Initialize the service.""" | ||
self._target = 'http://{}:7676'.format(remoteip) | ||
self._default_duration = duration | ||
|
@@ -110,19 +116,26 @@ def __init__(self, remoteip, duration, position, transparency, color, | |
self._default_color = color | ||
self._default_interrupt = interrupt | ||
self._timeout = timeout | ||
self._icon_file = os.path.join( | ||
os.path.dirname(__file__), '..', 'frontend', 'www_static', 'icons', | ||
'favicon-192x192.png') | ||
self._icon_file = None | ||
if icon: | ||
self._icon_file = icon | ||
else: | ||
try: | ||
import hass_frontend | ||
default_icon = os.path.join( | ||
hass_frontend.__path__[0], 'icons', 'favicon-192x192.png') | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Use |
||
if os.path.exists(default_icon): | ||
self._icon_file = default_icon | ||
except ImportError: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually, it's weird that this component even depends on the frontend at all. I wonder if we should include a Home Assistant logo in this repo for such circumstances. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In most situations an icon probably is not required. It's rather a problematic design choice at the TV app. But since I can't influence that there's no other way. Before the changes to the frontend the icons where here, so it wasn't an issue. Having an icon here would be fine for me. Any suggestions where it should go? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why don't we start with just the bytes of an empty gif, you could embed that in the code. |
||
_LOGGER.warning( | ||
"hass_frontend icon not found. " + | ||
"Provide an icon when calling the service.") | ||
|
||
def send_message(self, message="", **kwargs): | ||
"""Send a message to a Android TV device.""" | ||
_LOGGER.debug("Sending notification to: %s", self._target) | ||
|
||
payload = dict(filename=('icon.png', | ||
open(self._icon_file, 'rb'), | ||
'application/octet-stream', | ||
{'Expires': '0'}), type='0', | ||
title=kwargs.get(ATTR_TITLE, ATTR_TITLE_DEFAULT), | ||
payload = dict(title=kwargs.get(ATTR_TITLE, ATTR_TITLE_DEFAULT), | ||
msg=message, duration="%i" % self._default_duration, | ||
position='%i' % POSITIONS.get(self._default_position), | ||
bkgcolor='%s' % COLORS.get(self._default_color), | ||
|
@@ -131,8 +144,11 @@ def send_message(self, message="", **kwargs): | |
offset='0', app=ATTR_TITLE_DEFAULT, force='true', | ||
interrupt='%i' % self._default_interrupt) | ||
|
||
icon_file = None | ||
data = kwargs.get(ATTR_DATA) | ||
if data: | ||
if ATTR_ICON in data: | ||
icon_file = data.get(ATTR_ICON) | ||
if ATTR_DURATION in data: | ||
duration = data.get(ATTR_DURATION) | ||
try: | ||
|
@@ -169,6 +185,16 @@ def send_message(self, message="", **kwargs): | |
_LOGGER.warning("Invalid interrupt-value: %s", | ||
str(interrupt)) | ||
|
||
if self._icon_file is None and icon_file is None: | ||
_LOGGER.error("No icon available. Not sending notification.") | ||
return | ||
if icon_file is None: | ||
icon_file = self._icon_file | ||
payload[ATTR_FILENAME] = ('icon.png', | ||
open(icon_file, 'rb'), | ||
'application/octet-stream', | ||
{'Expires': '0'}) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We should check the path with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If I do that this fix doesn't work anymore. Using resources from hass_frontend seems to not be allowed. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm wondering how that's possible because There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm developing this on a Debian VM as root within a venv. And root shouldn't have any issues with permissions. I haven't looked more deeply into it though. I just noticed, that with a default-configuration (no custom icon set) it won't work anymore. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since the user is allowed to specify any path to an icon, we need to use I think the easier approach here is to remove the option to set custom icons. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh I see now that setting a custom icon is added in this PR, please revert that change. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Dynamic icons actually were a feature request a while back. And even though there are some restrcitions with the supported formats it makes sense. Just like other notifiers (like telegram) support sending images. |
||
|
||
try: | ||
_LOGGER.debug("Payload: %s", str(payload)) | ||
response = requests.post( | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
'homeassistant.const.CONF_ICON' imported but unused