Style updates (#5878)
* Use consts, update quoting, and update comments * Update log message * Update docstrings * Update log messages * Update log messages * Update style * Fix typo * Add newline * Fix indent * Fix line too long
This commit is contained in:
parent
b981bfba7e
commit
88653e66c8
9 changed files with 142 additions and 185 deletions
|
@ -13,10 +13,9 @@ import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.core import callback
|
from homeassistant.core import callback
|
||||||
from homeassistant.config import load_yaml_config_file
|
from homeassistant.config import load_yaml_config_file
|
||||||
from homeassistant.const import (CONF_ENTITY_ID, STATE_IDLE, CONF_NAME,
|
from homeassistant.const import (
|
||||||
CONF_STATE, STATE_ON, STATE_OFF,
|
CONF_ENTITY_ID, STATE_IDLE, CONF_NAME, CONF_STATE, STATE_ON, STATE_OFF,
|
||||||
SERVICE_TURN_ON, SERVICE_TURN_OFF,
|
SERVICE_TURN_ON, SERVICE_TURN_OFF, SERVICE_TOGGLE, ATTR_ENTITY_ID)
|
||||||
SERVICE_TOGGLE, ATTR_ENTITY_ID)
|
|
||||||
from homeassistant.helpers.entity import ToggleEntity
|
from homeassistant.helpers.entity import ToggleEntity
|
||||||
from homeassistant.helpers import service, event
|
from homeassistant.helpers import service, event
|
||||||
from homeassistant.util.async import run_callback_threadsafe
|
from homeassistant.util.async import run_callback_threadsafe
|
||||||
|
@ -32,13 +31,16 @@ CONF_NOTIFIERS = 'notifiers'
|
||||||
CONF_REPEAT = 'repeat'
|
CONF_REPEAT = 'repeat'
|
||||||
CONF_SKIP_FIRST = 'skip_first'
|
CONF_SKIP_FIRST = 'skip_first'
|
||||||
|
|
||||||
|
DEFAULT_CAN_ACK = True
|
||||||
|
DEFAULT_SKIP_FIRST = False
|
||||||
|
|
||||||
ALERT_SCHEMA = vol.Schema({
|
ALERT_SCHEMA = vol.Schema({
|
||||||
vol.Required(CONF_NAME): cv.string,
|
vol.Required(CONF_NAME): cv.string,
|
||||||
vol.Required(CONF_ENTITY_ID): cv.entity_id,
|
vol.Required(CONF_ENTITY_ID): cv.entity_id,
|
||||||
vol.Required(CONF_STATE, default=STATE_ON): cv.string,
|
vol.Required(CONF_STATE, default=STATE_ON): cv.string,
|
||||||
vol.Required(CONF_REPEAT): vol.All(cv.ensure_list, [vol.Coerce(float)]),
|
vol.Required(CONF_REPEAT): vol.All(cv.ensure_list, [vol.Coerce(float)]),
|
||||||
vol.Required(CONF_CAN_ACK, default=True): cv.boolean,
|
vol.Required(CONF_CAN_ACK, default=DEFAULT_CAN_ACK): cv.boolean,
|
||||||
vol.Required(CONF_SKIP_FIRST, default=False): cv.boolean,
|
vol.Required(CONF_SKIP_FIRST, default=DEFAULT_SKIP_FIRST): cv.boolean,
|
||||||
vol.Required(CONF_NOTIFIERS): cv.ensure_list})
|
vol.Required(CONF_NOTIFIERS): cv.ensure_list})
|
||||||
|
|
||||||
CONFIG_SCHEMA = vol.Schema({
|
CONFIG_SCHEMA = vol.Schema({
|
||||||
|
@ -99,7 +101,7 @@ def async_toggle(hass, entity_id):
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup(hass, config):
|
def async_setup(hass, config):
|
||||||
"""Setup alert component."""
|
"""Set up the Alert component."""
|
||||||
alerts = config.get(DOMAIN)
|
alerts = config.get(DOMAIN)
|
||||||
all_alerts = {}
|
all_alerts = {}
|
||||||
|
|
||||||
|
@ -117,7 +119,7 @@ def async_setup(hass, config):
|
||||||
else:
|
else:
|
||||||
yield from alert.async_turn_off()
|
yield from alert.async_turn_off()
|
||||||
|
|
||||||
# setup alerts
|
# Setup alerts
|
||||||
for entity_id, alert in alerts.items():
|
for entity_id, alert in alerts.items():
|
||||||
entity = Alert(hass, entity_id,
|
entity = Alert(hass, entity_id,
|
||||||
alert[CONF_NAME], alert[CONF_ENTITY_ID],
|
alert[CONF_NAME], alert[CONF_ENTITY_ID],
|
||||||
|
@ -126,13 +128,13 @@ def async_setup(hass, config):
|
||||||
alert[CONF_CAN_ACK])
|
alert[CONF_CAN_ACK])
|
||||||
all_alerts[entity.entity_id] = entity
|
all_alerts[entity.entity_id] = entity
|
||||||
|
|
||||||
# read descriptions
|
# Read descriptions
|
||||||
descriptions = yield from hass.loop.run_in_executor(
|
descriptions = yield from hass.loop.run_in_executor(
|
||||||
None, load_yaml_config_file, os.path.join(
|
None, load_yaml_config_file, os.path.join(
|
||||||
os.path.dirname(__file__), 'services.yaml'))
|
os.path.dirname(__file__), 'services.yaml'))
|
||||||
descriptions = descriptions.get(DOMAIN, {})
|
descriptions = descriptions.get(DOMAIN, {})
|
||||||
|
|
||||||
# setup service calls
|
# Setup service calls
|
||||||
hass.services.async_register(
|
hass.services.async_register(
|
||||||
DOMAIN, SERVICE_TURN_OFF, async_handle_alert_service,
|
DOMAIN, SERVICE_TURN_OFF, async_handle_alert_service,
|
||||||
descriptions.get(SERVICE_TURN_OFF), schema=ALERT_SERVICE_SCHEMA)
|
descriptions.get(SERVICE_TURN_OFF), schema=ALERT_SERVICE_SCHEMA)
|
||||||
|
@ -171,8 +173,8 @@ class Alert(ToggleEntity):
|
||||||
self._cancel = None
|
self._cancel = None
|
||||||
self.entity_id = ENTITY_ID_FORMAT.format(entity_id)
|
self.entity_id = ENTITY_ID_FORMAT.format(entity_id)
|
||||||
|
|
||||||
event.async_track_state_change(hass, watched_entity_id,
|
event.async_track_state_change(
|
||||||
self.watched_entity_change)
|
hass, watched_entity_id, self.watched_entity_change)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
|
@ -201,7 +203,7 @@ class Alert(ToggleEntity):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def watched_entity_change(self, entity, from_state, to_state):
|
def watched_entity_change(self, entity, from_state, to_state):
|
||||||
"""Determine if the alert should start or stop."""
|
"""Determine if the alert should start or stop."""
|
||||||
_LOGGER.debug('Watched entity (%s) has changed.', entity)
|
_LOGGER.debug("Watched entity (%s) has changed", entity)
|
||||||
if to_state.state == self._alert_state and not self._firing:
|
if to_state.state == self._alert_state and not self._firing:
|
||||||
yield from self.begin_alerting()
|
yield from self.begin_alerting()
|
||||||
if to_state.state != self._alert_state and self._firing:
|
if to_state.state != self._alert_state and self._firing:
|
||||||
|
@ -210,7 +212,7 @@ class Alert(ToggleEntity):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def begin_alerting(self):
|
def begin_alerting(self):
|
||||||
"""Begin the alert procedures."""
|
"""Begin the alert procedures."""
|
||||||
_LOGGER.debug('Beginning Alert: %s', self._name)
|
_LOGGER.debug("Beginning Alert: %s", self._name)
|
||||||
self._ack = False
|
self._ack = False
|
||||||
self._firing = True
|
self._firing = True
|
||||||
self._next_delay = 0
|
self._next_delay = 0
|
||||||
|
@ -225,7 +227,7 @@ class Alert(ToggleEntity):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def end_alerting(self):
|
def end_alerting(self):
|
||||||
"""End the alert procedures."""
|
"""End the alert procedures."""
|
||||||
_LOGGER.debug('Ending Alert: %s', self._name)
|
_LOGGER.debug("Ending Alert: %s", self._name)
|
||||||
self._cancel()
|
self._cancel()
|
||||||
self._ack = False
|
self._ack = False
|
||||||
self._firing = False
|
self._firing = False
|
||||||
|
@ -247,7 +249,7 @@ class Alert(ToggleEntity):
|
||||||
return
|
return
|
||||||
|
|
||||||
if not self._ack:
|
if not self._ack:
|
||||||
_LOGGER.info('Alerting: %s', self._name)
|
_LOGGER.info("Alerting: %s", self._name)
|
||||||
for target in self._notifiers:
|
for target in self._notifiers:
|
||||||
yield from self.hass.services.async_call(
|
yield from self.hass.services.async_call(
|
||||||
'notify', target, {'message': self._name})
|
'notify', target, {'message': self._name})
|
||||||
|
@ -256,14 +258,14 @@ class Alert(ToggleEntity):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_turn_on(self):
|
def async_turn_on(self):
|
||||||
"""Async Unacknowledge alert."""
|
"""Async Unacknowledge alert."""
|
||||||
_LOGGER.debug('Reset Alert: %s', self._name)
|
_LOGGER.debug("Reset Alert: %s", self._name)
|
||||||
self._ack = False
|
self._ack = False
|
||||||
yield from self.async_update_ha_state()
|
yield from self.async_update_ha_state()
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_turn_off(self):
|
def async_turn_off(self):
|
||||||
"""Async Acknowledge alert."""
|
"""Async Acknowledge alert."""
|
||||||
_LOGGER.debug('Acknowledged Alert: %s', self._name)
|
_LOGGER.debug("Acknowledged Alert: %s", self._name)
|
||||||
self._ack = True
|
self._ack = True
|
||||||
yield from self.async_update_ha_state()
|
yield from self.async_update_ha_state()
|
||||||
|
|
||||||
|
|
|
@ -77,14 +77,14 @@ class ApiaiIntentsView(HomeAssistantView):
|
||||||
"""Handle API.AI."""
|
"""Handle API.AI."""
|
||||||
data = yield from request.json()
|
data = yield from request.json()
|
||||||
|
|
||||||
_LOGGER.debug('Received Apiai request: %s', data)
|
_LOGGER.debug("Received api.ai request: %s", data)
|
||||||
|
|
||||||
req = data.get('result')
|
req = data.get('result')
|
||||||
|
|
||||||
if req is None:
|
if req is None:
|
||||||
_LOGGER.error('Received invalid data from Apiai: %s', data)
|
_LOGGER.error("Received invalid data from api.ai: %s", data)
|
||||||
return self.json_message('Expected result value not received',
|
return self.json_message(
|
||||||
HTTP_BAD_REQUEST)
|
"Expected result value not received", HTTP_BAD_REQUEST)
|
||||||
|
|
||||||
action_incomplete = req['actionIncomplete']
|
action_incomplete = req['actionIncomplete']
|
||||||
|
|
||||||
|
@ -106,7 +106,7 @@ class ApiaiIntentsView(HomeAssistantView):
|
||||||
# return self.json(response)
|
# return self.json(response)
|
||||||
|
|
||||||
if intent == "":
|
if intent == "":
|
||||||
_LOGGER.warning('Received intent with empty action')
|
_LOGGER.warning("Received intent with empty action")
|
||||||
response.add_speech(
|
response.add_speech(
|
||||||
"You have not defined an action in your api.ai intent.")
|
"You have not defined an action in your api.ai intent.")
|
||||||
return self.json(response)
|
return self.json(response)
|
||||||
|
@ -114,7 +114,7 @@ class ApiaiIntentsView(HomeAssistantView):
|
||||||
config = self.intents.get(intent)
|
config = self.intents.get(intent)
|
||||||
|
|
||||||
if config is None:
|
if config is None:
|
||||||
_LOGGER.warning('Received unknown intent %s', intent)
|
_LOGGER.warning("Received unknown intent %s", intent)
|
||||||
response.add_speech(
|
response.add_speech(
|
||||||
"Intent '%s' is not yet configured within Home Assistant." %
|
"Intent '%s' is not yet configured within Home Assistant." %
|
||||||
intent)
|
intent)
|
||||||
|
|
|
@ -17,7 +17,7 @@ DEPENDENCIES = ['qwikswitch']
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
"""Add lights from the main Qwikswitch component."""
|
"""Add lights from the main Qwikswitch component."""
|
||||||
if discovery_info is None:
|
if discovery_info is None:
|
||||||
_LOGGER.error("Configure Qwikswitch component")
|
_LOGGER.error("Configure Qwikswitch component failed")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
add_devices(qwikswitch.QSUSB['light'])
|
add_devices(qwikswitch.QSUSB['light'])
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
"""Support for Rflink lights.
|
"""
|
||||||
|
Support for Rflink lights.
|
||||||
For more details about this platform, please refer to the documentation
|
|
||||||
at https://home-assistant.io/components/light.rflink/
|
|
||||||
|
|
||||||
|
For more details about this platform, please refer to the documentation at
|
||||||
|
https://home-assistant.io/components/light.rflink/
|
||||||
"""
|
"""
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
@ -46,10 +46,9 @@ PLATFORM_SCHEMA = vol.Schema({
|
||||||
|
|
||||||
|
|
||||||
def entity_type_for_device_id(device_id):
|
def entity_type_for_device_id(device_id):
|
||||||
"""Return entity class for procotol of a given device_id.
|
"""Return entity class for protocol of a given device_id.
|
||||||
|
|
||||||
Async friendly.
|
Async friendly.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
entity_type_mapping = {
|
entity_type_mapping = {
|
||||||
# KlikAanKlikUit support both dimmers and on/off switches on the same
|
# KlikAanKlikUit support both dimmers and on/off switches on the same
|
||||||
|
@ -64,7 +63,6 @@ def entity_class_for_type(entity_type):
|
||||||
"""Translate entity type to entity class.
|
"""Translate entity type to entity class.
|
||||||
|
|
||||||
Async friendly.
|
Async friendly.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
entity_device_mapping = {
|
entity_device_mapping = {
|
||||||
# sends only 'dim' commands not compatible with on/off switches
|
# sends only 'dim' commands not compatible with on/off switches
|
||||||
|
@ -81,12 +79,12 @@ def entity_class_for_type(entity_type):
|
||||||
|
|
||||||
|
|
||||||
def devices_from_config(domain_config, hass=None):
|
def devices_from_config(domain_config, hass=None):
|
||||||
"""Parse config and add rflink switch devices."""
|
"""Parse configuration and add Rflink light devices."""
|
||||||
devices = []
|
devices = []
|
||||||
for device_id, config in domain_config[CONF_DEVICES].items():
|
for device_id, config in domain_config[CONF_DEVICES].items():
|
||||||
# determine which kind of entity to create
|
# Determine which kind of entity to create
|
||||||
if CONF_TYPE in config:
|
if CONF_TYPE in config:
|
||||||
# remove type from config to not pass it as and argument to entity
|
# Remove type from config to not pass it as and argument to entity
|
||||||
# instantiation
|
# instantiation
|
||||||
entity_type = config.pop(CONF_TYPE)
|
entity_type = config.pop(CONF_TYPE)
|
||||||
else:
|
else:
|
||||||
|
@ -97,19 +95,18 @@ def devices_from_config(domain_config, hass=None):
|
||||||
|
|
||||||
is_hybrid = entity_class is HybridRflinkLight
|
is_hybrid = entity_class is HybridRflinkLight
|
||||||
|
|
||||||
# make user aware this can cause problems
|
# Make user aware this can cause problems
|
||||||
repetitions_enabled = device_config[CONF_SIGNAL_REPETITIONS] != 1
|
repetitions_enabled = device_config[CONF_SIGNAL_REPETITIONS] != 1
|
||||||
if is_hybrid and repetitions_enabled:
|
if is_hybrid and repetitions_enabled:
|
||||||
_LOGGER.warning(
|
_LOGGER.warning(
|
||||||
"Hybrid type for %s not compatible with signal "
|
"Hybrid type for %s not compatible with signal "
|
||||||
"repetitions. Please set 'dimmable' or 'switchable' "
|
"repetitions. Please set 'dimmable' or 'switchable' "
|
||||||
"type explicity in configuration.",
|
"type explicity in configuration", device_id)
|
||||||
device_id)
|
|
||||||
|
|
||||||
device = entity_class(device_id, hass, **device_config)
|
device = entity_class(device_id, hass, **device_config)
|
||||||
devices.append(device)
|
devices.append(device)
|
||||||
|
|
||||||
# register entity (and aliasses) to listen to incoming rflink events
|
# Register entity (and aliasses) to listen to incoming rflink events
|
||||||
for _id in [device_id] + config[CONF_ALIASSES]:
|
for _id in [device_id] + config[CONF_ALIASSES]:
|
||||||
hass.data[DATA_ENTITY_LOOKUP][
|
hass.data[DATA_ENTITY_LOOKUP][
|
||||||
EVENT_KEY_COMMAND][_id].append(device)
|
EVENT_KEY_COMMAND][_id].append(device)
|
||||||
|
@ -119,11 +116,10 @@ def devices_from_config(domain_config, hass=None):
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Setup the Rflink platform."""
|
"""Set up the Rflink light platform."""
|
||||||
# add devices from config
|
|
||||||
yield from async_add_devices(devices_from_config(config, hass))
|
yield from async_add_devices(devices_from_config(config, hass))
|
||||||
|
|
||||||
# add new (unconfigured) devices to user desired group
|
# Add new (unconfigured) devices to user desired group
|
||||||
if config[CONF_NEW_DEVICES_GROUP]:
|
if config[CONF_NEW_DEVICES_GROUP]:
|
||||||
new_devices_group = yield from group.Group.async_create_group(
|
new_devices_group = yield from group.Group.async_create_group(
|
||||||
hass, config[CONF_NEW_DEVICES_GROUP], [], True)
|
hass, config[CONF_NEW_DEVICES_GROUP], [], True)
|
||||||
|
@ -142,14 +138,14 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
device = entity_class(device_id, hass, **device_config)
|
device = entity_class(device_id, hass, **device_config)
|
||||||
yield from async_add_devices([device])
|
yield from async_add_devices([device])
|
||||||
|
|
||||||
# register entity to listen to incoming rflink events
|
# Register entity to listen to incoming Rflink events
|
||||||
hass.data[DATA_ENTITY_LOOKUP][
|
hass.data[DATA_ENTITY_LOOKUP][
|
||||||
EVENT_KEY_COMMAND][device_id].append(device)
|
EVENT_KEY_COMMAND][device_id].append(device)
|
||||||
|
|
||||||
# make sure the event is processed by the new entity
|
# Make sure the event is processed by the new entity
|
||||||
device.handle_event(event)
|
device.handle_event(event)
|
||||||
|
|
||||||
# maybe add to new devices group
|
# Maybe add to new devices group
|
||||||
if new_devices_group:
|
if new_devices_group:
|
||||||
yield from new_devices_group.async_update_tracked_entity_ids(
|
yield from new_devices_group.async_update_tracked_entity_ids(
|
||||||
list(new_devices_group.tracking) + [device.entity_id])
|
list(new_devices_group.tracking) + [device.entity_id])
|
||||||
|
@ -202,7 +198,6 @@ class HybridRflinkLight(SwitchableRflinkDevice, Light):
|
||||||
command are send sequential and multiple 'on' commands to a dimmable
|
command are send sequential and multiple 'on' commands to a dimmable
|
||||||
device can cause the dimmer to switch into a pulsating brightness mode.
|
device can cause the dimmer to switch into a pulsating brightness mode.
|
||||||
Which results in a nice house disco :)
|
Which results in a nice house disco :)
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
_brightness = 255
|
_brightness = 255
|
||||||
|
@ -221,7 +216,7 @@ class HybridRflinkLight(SwitchableRflinkDevice, Light):
|
||||||
# if the receiving device does not support dimlevel this
|
# if the receiving device does not support dimlevel this
|
||||||
# will ensure it is turned on when full brightness is set
|
# will ensure it is turned on when full brightness is set
|
||||||
if self._brightness == 255:
|
if self._brightness == 255:
|
||||||
yield from self._async_handle_command("turn_on")
|
yield from self._async_handle_command('turn_on')
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def brightness(self):
|
def brightness(self):
|
||||||
|
|
|
@ -9,13 +9,14 @@ import logging
|
||||||
import voluptuous as vol
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.components.notify import (
|
from homeassistant.components.notify import (
|
||||||
PLATFORM_SCHEMA, BaseNotificationService,
|
PLATFORM_SCHEMA, BaseNotificationService, ATTR_TITLE, ATTR_TITLE_DEFAULT,
|
||||||
ATTR_TITLE, ATTR_TITLE_DEFAULT, ATTR_DATA)
|
ATTR_DATA)
|
||||||
from homeassistant.const import (CONF_TOKEN, CONF_DOMAIN,
|
from homeassistant.const import (
|
||||||
CONF_RECIPIENT, CONF_SENDER)
|
CONF_TOKEN, CONF_DOMAIN, CONF_RECIPIENT, CONF_SENDER)
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
REQUIREMENTS = ['https://github.com/pschmitt/pymailgun/'
|
REQUIREMENTS = ['https://github.com/pschmitt/pymailgun/'
|
||||||
'archive/1.3.zip#'
|
'archive/1.3.zip#'
|
||||||
'pymailgun==1.3']
|
'pymailgun==1.3']
|
||||||
|
@ -23,12 +24,9 @@ REQUIREMENTS = ['https://github.com/pschmitt/pymailgun/'
|
||||||
# Images to attach to notification
|
# Images to attach to notification
|
||||||
ATTR_IMAGES = 'images'
|
ATTR_IMAGES = 'images'
|
||||||
|
|
||||||
# Configuration item for the domain to use.
|
|
||||||
CONF_SANDBOX = 'sandbox'
|
CONF_SANDBOX = 'sandbox'
|
||||||
|
|
||||||
# Default sender name
|
|
||||||
DEFAULT_SENDER = 'hass@{domain}'
|
DEFAULT_SENDER = 'hass@{domain}'
|
||||||
# Default sandbox value
|
|
||||||
DEFAULT_SANDBOX = False
|
DEFAULT_SANDBOX = False
|
||||||
|
|
||||||
# pylint: disable=no-value-for-parameter
|
# pylint: disable=no-value-for-parameter
|
||||||
|
@ -43,11 +41,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
|
|
||||||
def get_service(hass, config, discovery_info=None):
|
def get_service(hass, config, discovery_info=None):
|
||||||
"""Get the Mailgun notification service."""
|
"""Get the Mailgun notification service."""
|
||||||
mailgun_service = MailgunNotificationService(config.get(CONF_DOMAIN),
|
mailgun_service = MailgunNotificationService(
|
||||||
config.get(CONF_SANDBOX),
|
config.get(CONF_DOMAIN), config.get(CONF_SANDBOX),
|
||||||
config.get(CONF_TOKEN),
|
config.get(CONF_TOKEN), config.get(CONF_SENDER),
|
||||||
config.get(CONF_SENDER),
|
config.get(CONF_RECIPIENT))
|
||||||
config.get(CONF_RECIPIENT))
|
|
||||||
if mailgun_service.connection_is_valid():
|
if mailgun_service.connection_is_valid():
|
||||||
return mailgun_service
|
return mailgun_service
|
||||||
else:
|
else:
|
||||||
|
@ -70,7 +67,7 @@ class MailgunNotificationService(BaseNotificationService):
|
||||||
"""Initialize the connection to Mailgun."""
|
"""Initialize the connection to Mailgun."""
|
||||||
from pymailgun import Client
|
from pymailgun import Client
|
||||||
self._client = Client(self._token, self._domain, self._sandbox)
|
self._client = Client(self._token, self._domain, self._sandbox)
|
||||||
_LOGGER.debug('Mailgun domain: %s', self._client.domain)
|
_LOGGER.debug("Mailgun domain: %s", self._client.domain)
|
||||||
self._domain = self._client.domain
|
self._domain = self._client.domain
|
||||||
if not self._sender:
|
if not self._sender:
|
||||||
self._sender = DEFAULT_SENDER.format(domain=self._domain)
|
self._sender = DEFAULT_SENDER.format(domain=self._domain)
|
||||||
|
@ -81,7 +78,7 @@ class MailgunNotificationService(BaseNotificationService):
|
||||||
try:
|
try:
|
||||||
self.initialize_client()
|
self.initialize_client()
|
||||||
except MailgunCredentialsError:
|
except MailgunCredentialsError:
|
||||||
_LOGGER.exception('Invalid credentials')
|
_LOGGER.exception("Invalid credentials")
|
||||||
return False
|
return False
|
||||||
except MailgunDomainError as mailgun_error:
|
except MailgunDomainError as mailgun_error:
|
||||||
_LOGGER.exception(mailgun_error)
|
_LOGGER.exception(mailgun_error)
|
||||||
|
@ -99,11 +96,9 @@ class MailgunNotificationService(BaseNotificationService):
|
||||||
# Initialize the client in case it was not.
|
# Initialize the client in case it was not.
|
||||||
if self._client is None:
|
if self._client is None:
|
||||||
self.initialize_client()
|
self.initialize_client()
|
||||||
resp = self._client.send_mail(sender=self._sender,
|
resp = self._client.send_mail(
|
||||||
to=self._recipient,
|
sender=self._sender, to=self._recipient, subject=subject,
|
||||||
subject=subject,
|
text=message, files=files)
|
||||||
text=message,
|
_LOGGER.debug("Message sent: %s", resp)
|
||||||
files=files)
|
|
||||||
_LOGGER.debug('Message sent: %s', resp)
|
|
||||||
except MailgunError as mailgun_error:
|
except MailgunError as mailgun_error:
|
||||||
_LOGGER.exception('Failed to send message: %s', mailgun_error)
|
_LOGGER.exception("Failed to send message: %s", mailgun_error)
|
||||||
|
|
|
@ -1,48 +1,33 @@
|
||||||
"""Support for Rflink components.
|
"""
|
||||||
|
Support for Rflink components.
|
||||||
|
|
||||||
For more details about this component, please refer to the documentation at
|
For more details about this component, please refer to the documentation at
|
||||||
https://home-assistant.io/components/rflink/
|
https://home-assistant.io/components/rflink/
|
||||||
|
|
||||||
Technical overview:
|
|
||||||
|
|
||||||
The Rflink gateway is a USB serial device (Arduino with Rflink firwmare)
|
|
||||||
connected to a 433Mhz transceiver module.
|
|
||||||
|
|
||||||
The the `rflink` Python module a asyncio transport/protocol is setup that
|
|
||||||
fires an callback for every (valid/supported) packet received by the Rflink
|
|
||||||
gateway.
|
|
||||||
|
|
||||||
This component uses this callback to distribute 'rflink packet events' over
|
|
||||||
the HASS bus which can be subscribed to by entities/platform implementations.
|
|
||||||
|
|
||||||
The platform implementions take care of creating new devices (if enabled) for
|
|
||||||
unsees incoming packet id's.
|
|
||||||
|
|
||||||
Device Entities take care of matching to the packet id, interpreting and
|
|
||||||
performing actions based on the packet contents. Common entitiy logic is
|
|
||||||
maintained in this file.
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import asyncio
|
import asyncio
|
||||||
from collections import defaultdict
|
from collections import defaultdict
|
||||||
import functools as ft
|
import functools as ft
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
|
import voluptuous as vol
|
||||||
|
|
||||||
from homeassistant.const import (
|
from homeassistant.const import (
|
||||||
ATTR_ENTITY_ID, CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STOP,
|
ATTR_ENTITY_ID, CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STOP,
|
||||||
STATE_UNKNOWN)
|
STATE_UNKNOWN)
|
||||||
from homeassistant.core import CoreState, callback
|
from homeassistant.core import CoreState, callback
|
||||||
import homeassistant.helpers.config_validation as cv
|
import homeassistant.helpers.config_validation as cv
|
||||||
from homeassistant.helpers.entity import Entity
|
from homeassistant.helpers.entity import Entity
|
||||||
import voluptuous as vol
|
|
||||||
|
|
||||||
REQUIREMENTS = ['rflink==0.0.28']
|
REQUIREMENTS = ['rflink==0.0.28']
|
||||||
|
|
||||||
DOMAIN = 'rflink'
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
ATTR_EVENT = 'event'
|
||||||
|
ATTR_STATE = 'state'
|
||||||
|
|
||||||
CONF_ALIASSES = 'aliasses'
|
CONF_ALIASSES = 'aliasses'
|
||||||
CONF_DEVICES = 'devices'
|
|
||||||
CONF_DEVICE_DEFAULTS = 'device_defaults'
|
CONF_DEVICE_DEFAULTS = 'device_defaults'
|
||||||
|
CONF_DEVICES = 'devices'
|
||||||
CONF_FIRE_EVENT = 'fire_event'
|
CONF_FIRE_EVENT = 'fire_event'
|
||||||
CONF_IGNORE_DEVICES = 'ignore_devices'
|
CONF_IGNORE_DEVICES = 'ignore_devices'
|
||||||
CONF_NEW_DEVICES_GROUP = 'new_devices_group'
|
CONF_NEW_DEVICES_GROUP = 'new_devices_group'
|
||||||
|
@ -50,8 +35,18 @@ CONF_RECONNECT_INTERVAL = 'reconnect_interval'
|
||||||
CONF_SIGNAL_REPETITIONS = 'signal_repetitions'
|
CONF_SIGNAL_REPETITIONS = 'signal_repetitions'
|
||||||
CONF_WAIT_FOR_ACK = 'wait_for_ack'
|
CONF_WAIT_FOR_ACK = 'wait_for_ack'
|
||||||
|
|
||||||
DEFAULT_SIGNAL_REPETITIONS = 1
|
DATA_DEVICE_REGISTER = 'rflink_device_register'
|
||||||
|
DATA_ENTITY_LOOKUP = 'rflink_entity_lookup'
|
||||||
DEFAULT_RECONNECT_INTERVAL = 10
|
DEFAULT_RECONNECT_INTERVAL = 10
|
||||||
|
DEFAULT_SIGNAL_REPETITIONS = 1
|
||||||
|
|
||||||
|
EVENT_BUTTON_PRESSED = 'button_pressed'
|
||||||
|
EVENT_KEY_COMMAND = 'command'
|
||||||
|
EVENT_KEY_ID = 'id'
|
||||||
|
EVENT_KEY_SENSOR = 'sensor'
|
||||||
|
EVENT_KEY_UNIT = 'unit'
|
||||||
|
|
||||||
|
DOMAIN = 'rflink'
|
||||||
|
|
||||||
DEVICE_DEFAULTS_SCHEMA = vol.Schema({
|
DEVICE_DEFAULTS_SCHEMA = vol.Schema({
|
||||||
vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean,
|
vol.Optional(CONF_FIRE_EVENT, default=False): cv.boolean,
|
||||||
|
@ -71,27 +66,11 @@ CONFIG_SCHEMA = vol.Schema({
|
||||||
}),
|
}),
|
||||||
}, extra=vol.ALLOW_EXTRA)
|
}, extra=vol.ALLOW_EXTRA)
|
||||||
|
|
||||||
ATTR_EVENT = 'event'
|
|
||||||
ATTR_STATE = 'state'
|
|
||||||
|
|
||||||
DATA_DEVICE_REGISTER = 'rflink_device_register'
|
|
||||||
DATA_ENTITY_LOOKUP = 'rflink_entity_lookup'
|
|
||||||
|
|
||||||
EVENT_BUTTON_PRESSED = 'button_pressed'
|
|
||||||
|
|
||||||
EVENT_KEY_COMMAND = 'command'
|
|
||||||
EVENT_KEY_ID = 'id'
|
|
||||||
EVENT_KEY_SENSOR = 'sensor'
|
|
||||||
EVENT_KEY_UNIT = 'unit'
|
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
|
|
||||||
def identify_event_type(event):
|
def identify_event_type(event):
|
||||||
"""Look at event to determine type of device.
|
"""Look at event to determine type of device.
|
||||||
|
|
||||||
Async friendly.
|
Async friendly.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
if EVENT_KEY_COMMAND in event:
|
if EVENT_KEY_COMMAND in event:
|
||||||
return EVENT_KEY_COMMAND
|
return EVENT_KEY_COMMAND
|
||||||
|
@ -103,79 +82,78 @@ def identify_event_type(event):
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup(hass, config):
|
def async_setup(hass, config):
|
||||||
"""Setup the Rflink component."""
|
"""Set up the Rflink component."""
|
||||||
from rflink.protocol import create_rflink_connection
|
from rflink.protocol import create_rflink_connection
|
||||||
import serial
|
import serial
|
||||||
|
|
||||||
# allow entities to register themselves by device_id to be looked up when
|
# Allow entities to register themselves by device_id to be looked up when
|
||||||
# new rflink events arrive to be handled
|
# new rflink events arrive to be handled
|
||||||
hass.data[DATA_ENTITY_LOOKUP] = {
|
hass.data[DATA_ENTITY_LOOKUP] = {
|
||||||
EVENT_KEY_COMMAND: defaultdict(list),
|
EVENT_KEY_COMMAND: defaultdict(list),
|
||||||
EVENT_KEY_SENSOR: defaultdict(list),
|
EVENT_KEY_SENSOR: defaultdict(list),
|
||||||
}
|
}
|
||||||
|
|
||||||
# allow platform to specify function to register new unknown devices
|
# Allow platform to specify function to register new unknown devices
|
||||||
hass.data[DATA_DEVICE_REGISTER] = {}
|
hass.data[DATA_DEVICE_REGISTER] = {}
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def event_callback(event):
|
def event_callback(event):
|
||||||
"""Handle incoming rflink events.
|
"""Handle incoming Rflink events.
|
||||||
|
|
||||||
Rflink events arrive as dictionaries of varying content
|
Rflink events arrive as dictionaries of varying content
|
||||||
depending on their type. Identify the events and distribute
|
depending on their type. Identify the events and distribute
|
||||||
accordingly.
|
accordingly.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
event_type = identify_event_type(event)
|
event_type = identify_event_type(event)
|
||||||
_LOGGER.debug('event of type %s: %s', event_type, event)
|
_LOGGER.debug('event of type %s: %s', event_type, event)
|
||||||
|
|
||||||
# don't propagate non entity events (eg: version string, ack response)
|
# Don't propagate non entity events (eg: version string, ack response)
|
||||||
if event_type not in hass.data[DATA_ENTITY_LOOKUP]:
|
if event_type not in hass.data[DATA_ENTITY_LOOKUP]:
|
||||||
_LOGGER.debug('unhandled event of type: %s', event_type)
|
_LOGGER.debug('unhandled event of type: %s', event_type)
|
||||||
return
|
return
|
||||||
|
|
||||||
# lookup entities who registered this device id as device id or alias
|
# Lookup entities who registered this device id as device id or alias
|
||||||
event_id = event.get('id', None)
|
event_id = event.get('id', None)
|
||||||
entities = hass.data[DATA_ENTITY_LOOKUP][event_type][event_id]
|
entities = hass.data[DATA_ENTITY_LOOKUP][event_type][event_id]
|
||||||
|
|
||||||
if entities:
|
if entities:
|
||||||
# propagate event to every entity matching the device id
|
# Propagate event to every entity matching the device id
|
||||||
for entity in entities:
|
for entity in entities:
|
||||||
_LOGGER.debug('passing event to %s', entities)
|
_LOGGER.debug('passing event to %s', entities)
|
||||||
entity.handle_event(event)
|
entity.handle_event(event)
|
||||||
else:
|
else:
|
||||||
_LOGGER.debug('device_id not known, adding new device')
|
_LOGGER.debug('device_id not known, adding new device')
|
||||||
|
|
||||||
# if device is not yet known, register with platform (if loaded)
|
# If device is not yet known, register with platform (if loaded)
|
||||||
if event_type in hass.data[DATA_DEVICE_REGISTER]:
|
if event_type in hass.data[DATA_DEVICE_REGISTER]:
|
||||||
hass.async_run_job(
|
hass.async_run_job(
|
||||||
hass.data[DATA_DEVICE_REGISTER][event_type], event)
|
hass.data[DATA_DEVICE_REGISTER][event_type], event)
|
||||||
|
|
||||||
# when connecting to tcp host instead of serial port (optional)
|
# When connecting to tcp host instead of serial port (optional)
|
||||||
host = config[DOMAIN][CONF_HOST]
|
host = config[DOMAIN][CONF_HOST]
|
||||||
# tcp port when host configured, otherwise serial port
|
# TCP port when host configured, otherwise serial port
|
||||||
port = config[DOMAIN][CONF_PORT]
|
port = config[DOMAIN][CONF_PORT]
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def reconnect(exc=None):
|
def reconnect(exc=None):
|
||||||
"""Schedule reconnect after connection has been unexpectedly lost."""
|
"""Schedule reconnect after connection has been unexpectedly lost."""
|
||||||
# reset protocol binding before starting reconnect
|
# Reset protocol binding before starting reconnect
|
||||||
RflinkCommand.set_rflink_protocol(None)
|
RflinkCommand.set_rflink_protocol(None)
|
||||||
|
|
||||||
# if HA is not stopping, initiate new connection
|
# If HA is not stopping, initiate new connection
|
||||||
if hass.state != CoreState.stopping:
|
if hass.state != CoreState.stopping:
|
||||||
_LOGGER.warning('disconnected from Rflink, reconnecting')
|
_LOGGER.warning('disconnected from Rflink, reconnecting')
|
||||||
hass.async_add_job(connect)
|
hass.async_add_job(connect)
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def connect():
|
def connect():
|
||||||
"""Setup connection and hook it into HA for reconnect/shutdown."""
|
"""Set up connection and hook it into HA for reconnect/shutdown."""
|
||||||
_LOGGER.info('initiating Rflink connection')
|
_LOGGER.info("Initiating Rflink connection")
|
||||||
|
|
||||||
# rflink create_rflink_connection decides based on the value of host
|
# Rflink create_rflink_connection decides based on the value of host
|
||||||
# (string or None) if serial or tcp mode should be used
|
# (string or None) if serial or tcp mode should be used
|
||||||
|
|
||||||
# initiate serial/tcp connection to Rflink gateway
|
# Initiate serial/tcp connection to Rflink gateway
|
||||||
connection = create_rflink_connection(
|
connection = create_rflink_connection(
|
||||||
port=port,
|
port=port,
|
||||||
host=host,
|
host=host,
|
||||||
|
@ -191,38 +169,32 @@ def async_setup(hass, config):
|
||||||
TimeoutError) as exc:
|
TimeoutError) as exc:
|
||||||
reconnect_interval = config[DOMAIN][CONF_RECONNECT_INTERVAL]
|
reconnect_interval = config[DOMAIN][CONF_RECONNECT_INTERVAL]
|
||||||
_LOGGER.exception(
|
_LOGGER.exception(
|
||||||
'error connecting to Rflink, reconnecting in %s',
|
"Error connecting to Rflink, reconnecting in %s",
|
||||||
reconnect_interval)
|
reconnect_interval)
|
||||||
hass.loop.call_later(reconnect_interval, reconnect, exc)
|
hass.loop.call_later(reconnect_interval, reconnect, exc)
|
||||||
return
|
return
|
||||||
|
|
||||||
# bind protocol to command class to allow entities to send commands
|
# Bind protocol to command class to allow entities to send commands
|
||||||
RflinkCommand.set_rflink_protocol(
|
RflinkCommand.set_rflink_protocol(
|
||||||
protocol, config[DOMAIN][CONF_WAIT_FOR_ACK])
|
protocol, config[DOMAIN][CONF_WAIT_FOR_ACK])
|
||||||
|
|
||||||
# handle shutdown of rflink asyncio transport
|
# handle shutdown of Rflink asyncio transport
|
||||||
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP,
|
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP,
|
||||||
lambda x: transport.close())
|
lambda x: transport.close())
|
||||||
|
|
||||||
_LOGGER.info('connected to Rflink')
|
_LOGGER.info("Connected to Rflink")
|
||||||
|
|
||||||
# make initial connection
|
|
||||||
yield from connect()
|
yield from connect()
|
||||||
|
|
||||||
# whoo
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class RflinkDevice(Entity):
|
class RflinkDevice(Entity):
|
||||||
"""Represents a Rflink device.
|
"""Representation of a Rflink device.
|
||||||
|
|
||||||
Contains the common logic for Rflink entities.
|
Contains the common logic for Rflink entities.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# should be set by component implementation
|
|
||||||
platform = None
|
platform = None
|
||||||
# default state
|
|
||||||
_state = STATE_UNKNOWN
|
_state = STATE_UNKNOWN
|
||||||
|
|
||||||
def __init__(self, device_id, hass, name=None,
|
def __init__(self, device_id, hass, name=None,
|
||||||
|
@ -231,14 +203,14 @@ class RflinkDevice(Entity):
|
||||||
"""Initialize the device."""
|
"""Initialize the device."""
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
|
|
||||||
# rflink specific attributes for every component type
|
# Rflink specific attributes for every component type
|
||||||
self._device_id = device_id
|
self._device_id = device_id
|
||||||
if name:
|
if name:
|
||||||
self._name = name
|
self._name = name
|
||||||
else:
|
else:
|
||||||
self._name = device_id
|
self._name = device_id
|
||||||
|
|
||||||
# generate list of device_ids to match against
|
# Generate list of device_ids to match against
|
||||||
if aliasses:
|
if aliasses:
|
||||||
self._aliasses = aliasses
|
self._aliasses = aliasses
|
||||||
else:
|
else:
|
||||||
|
@ -249,23 +221,21 @@ class RflinkDevice(Entity):
|
||||||
|
|
||||||
def handle_event(self, event):
|
def handle_event(self, event):
|
||||||
"""Handle incoming event for device type."""
|
"""Handle incoming event for device type."""
|
||||||
# call platform specific event handler
|
# Call platform specific event handler
|
||||||
self._handle_event(event)
|
self._handle_event(event)
|
||||||
|
|
||||||
# propagate changes through ha
|
# Propagate changes through ha
|
||||||
self.hass.async_add_job(self.async_update_ha_state())
|
self.hass.async_add_job(self.async_update_ha_state())
|
||||||
|
|
||||||
# put command onto bus for user to subscribe to
|
# Put command onto bus for user to subscribe to
|
||||||
if self._should_fire_event and identify_event_type(
|
if self._should_fire_event and identify_event_type(
|
||||||
event) == EVENT_KEY_COMMAND:
|
event) == EVENT_KEY_COMMAND:
|
||||||
self.hass.bus.fire(EVENT_BUTTON_PRESSED, {
|
self.hass.bus.fire(EVENT_BUTTON_PRESSED, {
|
||||||
ATTR_ENTITY_ID: self.entity_id,
|
ATTR_ENTITY_ID: self.entity_id,
|
||||||
ATTR_STATE: event[EVENT_KEY_COMMAND],
|
ATTR_STATE: event[EVENT_KEY_COMMAND],
|
||||||
})
|
})
|
||||||
_LOGGER.debug(
|
_LOGGER.debug("Fired bus event for %s: %s",
|
||||||
'fired bus event for %s: %s',
|
self.entity_id, event[EVENT_KEY_COMMAND])
|
||||||
self.entity_id,
|
|
||||||
event[EVENT_KEY_COMMAND])
|
|
||||||
|
|
||||||
def _handle_event(self, event):
|
def _handle_event(self, event):
|
||||||
"""Platform specific event handler."""
|
"""Platform specific event handler."""
|
||||||
|
@ -303,10 +273,9 @@ class RflinkCommand(RflinkDevice):
|
||||||
|
|
||||||
The Rflink interface is managed as a class level and set during setup (and
|
The Rflink interface is managed as a class level and set during setup (and
|
||||||
reset on reconnect).
|
reset on reconnect).
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# keep repetition tasks to cancel if state is changed before repetitions
|
# Keep repetition tasks to cancel if state is changed before repetitions
|
||||||
# are sent
|
# are sent
|
||||||
_repetition_task = None
|
_repetition_task = None
|
||||||
|
|
||||||
|
@ -322,7 +291,7 @@ class RflinkCommand(RflinkDevice):
|
||||||
"""Do bookkeeping for command, send it to rflink and update state."""
|
"""Do bookkeeping for command, send it to rflink and update state."""
|
||||||
self.cancel_queued_send_commands()
|
self.cancel_queued_send_commands()
|
||||||
|
|
||||||
if command == "turn_on":
|
if command == 'turn_on':
|
||||||
cmd = 'on'
|
cmd = 'on'
|
||||||
self._state = True
|
self._state = True
|
||||||
|
|
||||||
|
@ -335,8 +304,8 @@ class RflinkCommand(RflinkDevice):
|
||||||
cmd = str(int(args[0] / 17))
|
cmd = str(int(args[0] / 17))
|
||||||
self._state = True
|
self._state = True
|
||||||
|
|
||||||
# send initial command and queue repetitions
|
# Send initial command and queue repetitions.
|
||||||
# this allows the entity state to be updated quickly and not having to
|
# This allows the entity state to be updated quickly and not having to
|
||||||
# wait for all repetitions to be sent
|
# wait for all repetitions to be sent
|
||||||
yield from self._async_send_command(cmd, self._signal_repetitions)
|
yield from self._async_send_command(cmd, self._signal_repetitions)
|
||||||
|
|
||||||
|
@ -349,7 +318,6 @@ class RflinkCommand(RflinkDevice):
|
||||||
For example when user changed state while repetitions are still
|
For example when user changed state while repetitions are still
|
||||||
queued for broadcast. Or when a incoming Rflink command (remote
|
queued for broadcast. Or when a incoming Rflink command (remote
|
||||||
switch) changes the state.
|
switch) changes the state.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# cancel any outstanding tasks from the previous state change
|
# cancel any outstanding tasks from the previous state change
|
||||||
if self._repetition_task:
|
if self._repetition_task:
|
||||||
|
@ -358,8 +326,8 @@ class RflinkCommand(RflinkDevice):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def _async_send_command(self, cmd, repetitions):
|
def _async_send_command(self, cmd, repetitions):
|
||||||
"""Send a command for device to Rflink gateway."""
|
"""Send a command for device to Rflink gateway."""
|
||||||
_LOGGER.debug('sending command: %s to rflink device: %s',
|
_LOGGER.debug(
|
||||||
cmd, self._device_id)
|
"Sending command: %s to Rflink device: %s", cmd, self._device_id)
|
||||||
|
|
||||||
if self._wait_ack:
|
if self._wait_ack:
|
||||||
# Puts command on outgoing buffer then waits for Rflink to confirm
|
# Puts command on outgoing buffer then waits for Rflink to confirm
|
||||||
|
@ -394,9 +362,9 @@ class SwitchableRflinkDevice(RflinkCommand):
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_turn_on(self, **kwargs):
|
def async_turn_on(self, **kwargs):
|
||||||
"""Turn the device on."""
|
"""Turn the device on."""
|
||||||
yield from self._async_handle_command("turn_on")
|
yield from self._async_handle_command('turn_on')
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_turn_off(self, **kwargs):
|
def async_turn_off(self, **kwargs):
|
||||||
"""Turn the device off."""
|
"""Turn the device off."""
|
||||||
yield from self._async_handle_command("turn_off")
|
yield from self._async_handle_command('turn_off')
|
||||||
|
|
|
@ -37,7 +37,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
|
||||||
|
|
||||||
|
|
||||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||||
"""Setup the OpenEVSE sensor."""
|
"""Set up the OpenEVSE sensor."""
|
||||||
import openevsewifi
|
import openevsewifi
|
||||||
|
|
||||||
host = config.get(CONF_HOST)
|
host = config.get(CONF_HOST)
|
||||||
|
@ -85,7 +85,7 @@ class OpenEVSESensor(Entity):
|
||||||
if self.type == 'status':
|
if self.type == 'status':
|
||||||
self._state = self.charger.getStatus()
|
self._state = self.charger.getStatus()
|
||||||
elif self.type == 'charge_time':
|
elif self.type == 'charge_time':
|
||||||
self._state = self.charger.getChargeTimeElapsed()/60
|
self._state = self.charger.getChargeTimeElapsed() / 60
|
||||||
elif self.type == 'ambient_temp':
|
elif self.type == 'ambient_temp':
|
||||||
self._state = self.charger.getAmbientTemperature()
|
self._state = self.charger.getAmbientTemperature()
|
||||||
elif self.type == 'ir_temp':
|
elif self.type == 'ir_temp':
|
||||||
|
@ -93,10 +93,10 @@ class OpenEVSESensor(Entity):
|
||||||
elif self.type == 'rtc_temp':
|
elif self.type == 'rtc_temp':
|
||||||
self._state = self.charger.getRTCTemperature()
|
self._state = self.charger.getRTCTemperature()
|
||||||
elif self.type == 'usage_session':
|
elif self.type == 'usage_session':
|
||||||
self._state = float(self.charger.getUsageSession())/1000
|
self._state = float(self.charger.getUsageSession()) / 1000
|
||||||
elif self.type == 'usage_total':
|
elif self.type == 'usage_total':
|
||||||
self._state = float(self.charger.getUsageTotal())/1000
|
self._state = float(self.charger.getUsageTotal()) / 1000
|
||||||
else:
|
else:
|
||||||
self._state = 'Unknown'
|
self._state = 'Unknown'
|
||||||
except (RequestException, ValueError, KeyError):
|
except (RequestException, ValueError, KeyError):
|
||||||
_LOGGER.warning('Could not update status for %s', self.name)
|
_LOGGER.warning("Could not update status for %s", self.name)
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
"""Support for Rflink sensors.
|
"""
|
||||||
|
Support for Rflink sensors.
|
||||||
For more details about this platform, please refer to the documentation
|
|
||||||
at https://home-assistant.io/components/light.rflink/
|
|
||||||
|
|
||||||
|
For more details about this platform, please refer to the documentation at
|
||||||
|
https://home-assistant.io/components/light.rflink/
|
||||||
"""
|
"""
|
||||||
import asyncio
|
import asyncio
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
@ -48,7 +48,6 @@ def lookup_unit_for_sensor_type(sensor_type):
|
||||||
"""Get unit for sensor type.
|
"""Get unit for sensor type.
|
||||||
|
|
||||||
Async friendly.
|
Async friendly.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from rflink.parser import UNITS, PACKET_FIELDS
|
from rflink.parser import UNITS, PACKET_FIELDS
|
||||||
field_abbrev = {v: k for k, v in PACKET_FIELDS.items()}
|
field_abbrev = {v: k for k, v in PACKET_FIELDS.items()}
|
||||||
|
@ -57,7 +56,7 @@ def lookup_unit_for_sensor_type(sensor_type):
|
||||||
|
|
||||||
|
|
||||||
def devices_from_config(domain_config, hass=None):
|
def devices_from_config(domain_config, hass=None):
|
||||||
"""Parse config and add rflink sensor devices."""
|
"""Parse configuration and add Rflink sensor devices."""
|
||||||
devices = []
|
devices = []
|
||||||
for device_id, config in domain_config[CONF_DEVICES].items():
|
for device_id, config in domain_config[CONF_DEVICES].items():
|
||||||
if not config[ATTR_UNIT_OF_MEASUREMENT]:
|
if not config[ATTR_UNIT_OF_MEASUREMENT]:
|
||||||
|
@ -66,7 +65,7 @@ def devices_from_config(domain_config, hass=None):
|
||||||
device = RflinkSensor(device_id, hass, **config)
|
device = RflinkSensor(device_id, hass, **config)
|
||||||
devices.append(device)
|
devices.append(device)
|
||||||
|
|
||||||
# register entity to listen to incoming rflink events
|
# Register entity to listen to incoming rflink events
|
||||||
hass.data[DATA_ENTITY_LOOKUP][
|
hass.data[DATA_ENTITY_LOOKUP][
|
||||||
EVENT_KEY_SENSOR][device_id].append(device)
|
EVENT_KEY_SENSOR][device_id].append(device)
|
||||||
return devices
|
return devices
|
||||||
|
@ -74,11 +73,10 @@ def devices_from_config(domain_config, hass=None):
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Setup the Rflink platform."""
|
"""Set up the Rflink platform."""
|
||||||
# add devices from config
|
|
||||||
yield from async_add_devices(devices_from_config(config, hass))
|
yield from async_add_devices(devices_from_config(config, hass))
|
||||||
|
|
||||||
# add new (unconfigured) devices to user desired group
|
# Add new (unconfigured) devices to user desired group
|
||||||
if config[CONF_NEW_DEVICES_GROUP]:
|
if config[CONF_NEW_DEVICES_GROUP]:
|
||||||
new_devices_group = yield from group.Group.async_create_group(
|
new_devices_group = yield from group.Group.async_create_group(
|
||||||
hass, config[CONF_NEW_DEVICES_GROUP], [], True)
|
hass, config[CONF_NEW_DEVICES_GROUP], [], True)
|
||||||
|
@ -92,17 +90,17 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
|
|
||||||
rflinksensor = partial(RflinkSensor, device_id, hass)
|
rflinksensor = partial(RflinkSensor, device_id, hass)
|
||||||
device = rflinksensor(event[EVENT_KEY_SENSOR], event[EVENT_KEY_UNIT])
|
device = rflinksensor(event[EVENT_KEY_SENSOR], event[EVENT_KEY_UNIT])
|
||||||
# add device entity
|
# Add device entity
|
||||||
yield from async_add_devices([device])
|
yield from async_add_devices([device])
|
||||||
|
|
||||||
# register entity to listen to incoming rflink events
|
# Register entity to listen to incoming rflink events
|
||||||
hass.data[DATA_ENTITY_LOOKUP][
|
hass.data[DATA_ENTITY_LOOKUP][
|
||||||
EVENT_KEY_SENSOR][device_id].append(device)
|
EVENT_KEY_SENSOR][device_id].append(device)
|
||||||
|
|
||||||
# make sure the event is processed by the new entity
|
# Make sure the event is processed by the new entity
|
||||||
device.handle_event(event)
|
device.handle_event(event)
|
||||||
|
|
||||||
# maybe add to new devices group
|
# Maybe add to new devices group
|
||||||
if new_devices_group:
|
if new_devices_group:
|
||||||
yield from new_devices_group.async_update_tracked_entity_ids(
|
yield from new_devices_group.async_update_tracked_entity_ids(
|
||||||
list(new_devices_group.tracking) + [device.entity_id])
|
list(new_devices_group.tracking) + [device.entity_id])
|
||||||
|
@ -113,8 +111,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
class RflinkSensor(RflinkDevice):
|
class RflinkSensor(RflinkDevice):
|
||||||
"""Representation of a Rflink sensor."""
|
"""Representation of a Rflink sensor."""
|
||||||
|
|
||||||
def __init__(self, device_id, hass, sensor_type,
|
def __init__(self, device_id, hass, sensor_type, unit_of_measurement,
|
||||||
unit_of_measurement, **kwargs):
|
**kwargs):
|
||||||
"""Handle sensor specific args and super init."""
|
"""Handle sensor specific args and super init."""
|
||||||
self._sensor_type = sensor_type
|
self._sensor_type = sensor_type
|
||||||
self._unit_of_measurement = unit_of_measurement
|
self._unit_of_measurement = unit_of_measurement
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
"""Support for Rflink switches.
|
"""
|
||||||
|
Support for Rflink switches.
|
||||||
For more details about this platform, please refer to the documentation
|
|
||||||
at https://home-assistant.io/components/switch.rflink/
|
|
||||||
|
|
||||||
|
For more details about this platform, please refer to the documentation at
|
||||||
|
https://home-assistant.io/components/switch.rflink/
|
||||||
"""
|
"""
|
||||||
import asyncio
|
import asyncio
|
||||||
import logging
|
import logging
|
||||||
|
@ -18,7 +18,6 @@ DEPENDENCIES = ['rflink']
|
||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
PLATFORM_SCHEMA = vol.Schema({
|
PLATFORM_SCHEMA = vol.Schema({
|
||||||
vol.Required(CONF_PLATFORM): DOMAIN,
|
vol.Required(CONF_PLATFORM): DOMAIN,
|
||||||
vol.Optional(CONF_DEVICE_DEFAULTS, default=DEVICE_DEFAULTS_SCHEMA({})):
|
vol.Optional(CONF_DEVICE_DEFAULTS, default=DEVICE_DEFAULTS_SCHEMA({})):
|
||||||
|
@ -36,14 +35,14 @@ PLATFORM_SCHEMA = vol.Schema({
|
||||||
|
|
||||||
|
|
||||||
def devices_from_config(domain_config, hass=None):
|
def devices_from_config(domain_config, hass=None):
|
||||||
"""Parse config and add rflink switch devices."""
|
"""Parse configuration and add Rflink switch devices."""
|
||||||
devices = []
|
devices = []
|
||||||
for device_id, config in domain_config[CONF_DEVICES].items():
|
for device_id, config in domain_config[CONF_DEVICES].items():
|
||||||
device_config = dict(domain_config[CONF_DEVICE_DEFAULTS], **config)
|
device_config = dict(domain_config[CONF_DEVICE_DEFAULTS], **config)
|
||||||
device = RflinkSwitch(device_id, hass, **device_config)
|
device = RflinkSwitch(device_id, hass, **device_config)
|
||||||
devices.append(device)
|
devices.append(device)
|
||||||
|
|
||||||
# register entity (and aliasses) to listen to incoming rflink events
|
# Register entity (and aliasses) to listen to incoming rflink events
|
||||||
for _id in config[CONF_ALIASSES] + [device_id]:
|
for _id in config[CONF_ALIASSES] + [device_id]:
|
||||||
hass.data[DATA_ENTITY_LOOKUP][
|
hass.data[DATA_ENTITY_LOOKUP][
|
||||||
EVENT_KEY_COMMAND][_id].append(device)
|
EVENT_KEY_COMMAND][_id].append(device)
|
||||||
|
@ -52,7 +51,7 @@ def devices_from_config(domain_config, hass=None):
|
||||||
|
|
||||||
@asyncio.coroutine
|
@asyncio.coroutine
|
||||||
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
|
||||||
"""Setup the Rflink platform."""
|
"""Set up the Rflink platform."""
|
||||||
yield from async_add_devices(devices_from_config(config, hass))
|
yield from async_add_devices(devices_from_config(config, hass))
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue