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

LaMetric platform and notify module #8230

Merged
merged 17 commits into from Jul 7, 2017
3 changes: 3 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ omit =
homeassistant/components/knx.py
homeassistant/components/*/knx.py

homeassistant/components/lametric.py
homeassistant/components/*/lametric.py

homeassistant/components/lutron.py
homeassistant/components/*/lutron.py

Expand Down
90 changes: 90 additions & 0 deletions homeassistant/components/lametric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
"""
Support for LaMetric time.

This is the base platform to support LaMetric components:
Notify, Light, Mediaplayer

For more details about this component, please refer to the documentation at
https://home-assistant.io/components/lametric/
"""
import logging

import voluptuous as vol

import homeassistant.helpers.config_validation as cv

REQUIREMENTS = ['lmnotify==0.0.4']

_LOGGER = logging.getLogger(__name__)

CONF_CLIENT_ID = 'client_id'
CONF_CLIENT_SECRET = 'client_secret'

DOMAIN = 'lametric'
LAMETRIC_DEVICES = 'LAMETRIC_DEVICES'

CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Required(CONF_CLIENT_ID): cv.string,
vol.Required(CONF_CLIENT_SECRET): cv.string,
}),
}, extra=vol.ALLOW_EXTRA)


# pylint: disable=broad-except
def setup(hass, config):
"""Set up the LaMetricManager."""
_LOGGER.debug("Setting up LaMetric platform")
try:
conf = config[DOMAIN]
hlmn = HassLaMetricManager(client_id=conf[CONF_CLIENT_ID],
client_secret=conf[CONF_CLIENT_SECRET])
devices = hlmn.manager().get_devices()
except Exception as exception:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Broad-except is bad and we catch it on core. Please set the specific exception

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The possible exceptions aren't documented. I've already seen oauth exceptions, but there can be all kind of other exceptions.
I can remove the except completely. Personally I don't think this is a better solution.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can start with oauth and add more if you see others or other user report one

_LOGGER.error("Could not setup LaMetric platform: %s", exception)
return False

found = False
hass.data[DOMAIN] = hlmn
hass.data[LAMETRIC_DEVICES] = []
for dev in devices:
_LOGGER.debug("Discovered LaMetric device: %s", dev)
hass.data[LAMETRIC_DEVICES].append(dev)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you store that? Please remove it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might become handy to have this ready for other devices based on the platform. But I can remove it for now.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah we can add this if we had a use case for it.

found = True

return found


class HassLaMetricManager():
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please change the class designe to a instancable class that is stored in hass.data. This class is like global what is not allow anymore.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been changed how. The global instance is stored in hass.data now.

"""
A class that encapsulated requests to the LaMetric manager.

As the original class does not have a re-connect feature that is needed
for applications running for a long time as the OAuth tokens expire. This
class implements this reconnect() feature.
"""

def __init__(self, client_id, client_secret):
"""Initialize HassLaMetricManager and connect to LaMetric."""
from lmnotify import LaMetricManager

_LOGGER.debug("Connecting to LaMetric")
HassLaMetricManager.lmn = LaMetricManager(client_id, client_secret)
HassLaMetricManager._client_id = client_id
HassLaMetricManager._client_secret = client_secret
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use self


def reconnect(self):
"""
Reconnect to LaMetric.

This is usually necessary when the OAuth token is expired.
"""
from lmnotify import LaMetricManager
_LOGGER.debug("Reconnecting to LaMetric")
HassLaMetricManager.lmn = \
LaMetricManager(self._client_id,
self._client_secret)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use self


def manager(self):
"""Return the global LaMetricManager instance."""
return self.lmn
96 changes: 96 additions & 0 deletions homeassistant/components/notify/lametric.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
"""
Notifier for LaMetric time.

For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/notify.lametric/
"""
import logging

import voluptuous as vol

from homeassistant.components.notify import (
ATTR_TARGET, ATTR_DATA, PLATFORM_SCHEMA, BaseNotificationService)
from homeassistant.const import CONF_ICON
from homeassistant.exceptions import HomeAssistantError

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

'homeassistant.exceptions.HomeAssistantError' imported but unused

import homeassistant.helpers.config_validation as cv

from homeassistant.components.lametric import DOMAIN

REQUIREMENTS = ['lmnotify==0.0.4']

_LOGGER = logging.getLogger(__name__)

CONF_DISPLAY_TIME = "display_time"

PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Optional(CONF_ICON, default="i555"): cv.string,
vol.Optional(CONF_DISPLAY_TIME, default=10): cv.positive_int,
})


# pylint: disable=unused-variable
def get_service(hass, config, discovery_info=None):
"""Get the Slack notification service."""
hlmn = hass.data.get(DOMAIN)
try:
return LaMetricNotificationService(hlmn,
config[CONF_ICON],
config[CONF_DISPLAY_TIME] * 1000)
except HomeAssistantError:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you sure that will be possible?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this seems to be some old code. I can remove this.

_LOGGER.exception("Could not configure LaMetric notifier")
return None


class LaMetricNotificationService(BaseNotificationService):
"""Implement the notification service for LaMetric."""

def __init__(self, hasslametricmanager, icon, display_time):
"""Initialize the service."""
self.hasslametricmanager = hasslametricmanager
self._icon = icon
self._display_time = display_time

# pylint: disable=broad-except
def send_message(self, message="", **kwargs):
"""Send a message to some LaMetric deviced."""
from lmnotify import SimpleFrame, Sound, Model

targets = kwargs.get(ATTR_TARGET)
data = kwargs.get(ATTR_DATA)
_LOGGER.debug("Targets/Data: %s/%s", targets, data)
icon = self._icon
sound = None

# User-defined icon?
if data is not None:
if "icon" in data:
icon = data["icon"]
if "sound" in data:
try:
sound = Sound(category="notifications",
sound_id=data["sound"])
_LOGGER.debug("Adding notification sound %s",
data["sound"])
except Exception:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Specifiy exception

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The possible exceptions aren't documented. I've already seen oauth exceptions, but there can be all kind of other exceptions.
I can remove the except completely. Personally I don't think this is a better solution.

_LOGGER.error("Sound ID %s unknown, ignoring",
data["sound"])

text_frame = SimpleFrame(icon, message)
_LOGGER.debug("Icon/Message/Duration: %s, %s, %d",
icon, message, self._display_time)

frames = [text_frame]

if sound is not None:
frames.append(sound)

_LOGGER.debug(frames)

model = Model(frames=frames)
lmn = self.hasslametricmanager.manager()
devices = lmn.get_devices()
for dev in devices:
if (targets is None) or (dev["name"] in targets):
lmn.set_device(dev)
lmn.send_notification(model, lifetime=self._display_time)
_LOGGER.debug("Sent notification to LaMetric %s", dev["name"])
5 changes: 5 additions & 0 deletions requirements_all.txt
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,11 @@ limitlessled==1.0.8
# homeassistant.components.media_player.liveboxplaytv
liveboxplaytv==1.4.9

# homeassistant.components.lametric
# homeassistant.components.media_player.lametric
# homeassistant.components.notify.lametric
lmnotify==0.0.4

# homeassistant.components.sensor.lyft
lyft_rides==0.1.0b0

Expand Down