Update docstrings to match PEP257

This commit is contained in:
Fabian Affolter 2016-03-07 18:49:31 +01:00
parent 7ff9aecd4e
commit b8a40457ee
40 changed files with 371 additions and 483 deletions

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.apcupsd Support for status output of APCUPSd via its Network Information Server (NIS).
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets up and provides access to the status output of APCUPSd via its Network
Information Server (NIS).
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/apcupsd/ https://home-assistant.io/components/apcupsd/
@ -34,7 +31,7 @@ _LOGGER = logging.getLogger(__name__)
def setup(hass, config): def setup(hass, config):
""" Use config values to set up a function enabling status retrieval. """ """Use config values to set up a function enabling status retrieval."""
global DATA global DATA
host = config[DOMAIN].get(CONF_HOST, DEFAULT_HOST) host = config[DOMAIN].get(CONF_HOST, DEFAULT_HOST)
@ -68,12 +65,12 @@ class APCUPSdData(object):
@property @property
def status(self): def status(self):
""" Get latest update if throttle allows. Return status. """ """Get latest update if throttle allows. Return status."""
self.update() self.update()
return self._status return self._status
def _get_status(self): def _get_status(self):
""" Get the status from APCUPSd and parse it into a dict. """ """Get the status from APCUPSd and parse it into a dict."""
return self._parse(self._get(host=self._host, port=self._port)) return self._parse(self._get(host=self._host, port=self._port))
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)

View File

@ -1,8 +1,5 @@
""" """
components.arduino Support for Arduino boards running with the Firmata firmware.
~~~~~~~~~~~~~~~~~~
Arduino component that connects to a directly attached Arduino board which
runs with the Firmata firmware.
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/arduino/ https://home-assistant.io/components/arduino/
@ -20,8 +17,7 @@ _LOGGER = logging.getLogger(__name__)
def setup(hass, config): def setup(hass, config):
""" Setup the Arduino component. """ """Setup the Arduino component."""
if not validate_config(config, if not validate_config(config,
{DOMAIN: ['port']}, {DOMAIN: ['port']},
_LOGGER): _LOGGER):
@ -40,11 +36,11 @@ def setup(hass, config):
return False return False
def stop_arduino(event): def stop_arduino(event):
""" Stop the Arduino service. """ """Stop the Arduino service."""
BOARD.disconnect() BOARD.disconnect()
def start_arduino(event): def start_arduino(event):
""" Start the Arduino service. """ """Start the Arduino service."""
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_arduino) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_arduino)
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_arduino) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_arduino)
@ -53,15 +49,14 @@ def setup(hass, config):
class ArduinoBoard(object): class ArduinoBoard(object):
""" Represents an Arduino board. """ """Represents an Arduino board."""
def __init__(self, port): def __init__(self, port):
from PyMata.pymata import PyMata from PyMata.pymata import PyMata
self._port = port self._port = port
self._board = PyMata(self._port, verbose=False) self._board = PyMata(self._port, verbose=False)
def set_mode(self, pin, direction, mode): def set_mode(self, pin, direction, mode):
""" Sets the mode and the direction of a given pin. """ """Set the mode and the direction of a given pin."""
if mode == 'analog' and direction == 'in': if mode == 'analog' and direction == 'in':
self._board.set_pin_mode(pin, self._board.set_pin_mode(pin,
self._board.INPUT, self._board.INPUT,
@ -84,31 +79,31 @@ class ArduinoBoard(object):
self._board.PWM) self._board.PWM)
def get_analog_inputs(self): def get_analog_inputs(self):
""" Get the values from the pins. """ """Get the values from the pins."""
self._board.capability_query() self._board.capability_query()
return self._board.get_analog_response_table() return self._board.get_analog_response_table()
def set_digital_out_high(self, pin): def set_digital_out_high(self, pin):
""" Sets a given digital pin to high. """ """Set a given digital pin to high."""
self._board.digital_write(pin, 1) self._board.digital_write(pin, 1)
def set_digital_out_low(self, pin): def set_digital_out_low(self, pin):
""" Sets a given digital pin to low. """ """Set a given digital pin to low."""
self._board.digital_write(pin, 0) self._board.digital_write(pin, 0)
def get_digital_in(self, pin): def get_digital_in(self, pin):
""" Gets the value from a given digital pin. """ """Get the value from a given digital pin."""
self._board.digital_read(pin) self._board.digital_read(pin)
def get_analog_in(self, pin): def get_analog_in(self, pin):
""" Gets the value from a given analog pin. """ """Get the value from a given analog pin."""
self._board.analog_read(pin) self._board.analog_read(pin)
def get_firmata(self): def get_firmata(self):
""" Return the version of the Firmata firmware. """ """Return the version of the Firmata firmware."""
return self._board.get_firmata_version() return self._board.get_firmata_version()
def disconnect(self): def disconnect(self):
""" Disconnects the board and closes the serial connection. """ """Disconnects the board and closes the serial connection."""
self._board.reset() self._board.reset()
self._board.close() self._board.close()

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.bloomsky
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for BloomSky weather station. Support for BloomSky weather station.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.configurator Support to allow pieces of code to request configuration from the user.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A component to allow pieces of code to request configuration from the user.
Initiate a request by calling the `request_config` method with a callback. Initiate a request by calling the `request_config` method with a callback.
This will return a request id that has to be used for future calls. This will return a request id that has to be used for future calls.
@ -38,9 +35,9 @@ _LOGGER = logging.getLogger(__name__)
def request_config( def request_config(
hass, name, callback, description=None, description_image=None, hass, name, callback, description=None, description_image=None,
submit_caption=None, fields=None): submit_caption=None, fields=None):
""" Create a new request for config. """Create a new request for configuration.
Will return an ID to be used for sequent calls. """ Will return an ID to be used for sequent calls.
"""
instance = _get_instance(hass) instance = _get_instance(hass)
request_id = instance.request_config( request_id = instance.request_config(
@ -53,7 +50,7 @@ def request_config(
def notify_errors(request_id, error): def notify_errors(request_id, error):
""" Add errors to a config request. """ """Add errors to a config request."""
try: try:
_REQUESTS[request_id].notify_errors(request_id, error) _REQUESTS[request_id].notify_errors(request_id, error)
except KeyError: except KeyError:
@ -62,7 +59,7 @@ def notify_errors(request_id, error):
def request_done(request_id): def request_done(request_id):
""" Mark a config request as done. """ """Mark a configuration request as done."""
try: try:
_REQUESTS.pop(request_id).request_done(request_id) _REQUESTS.pop(request_id).request_done(request_id)
except KeyError: except KeyError:
@ -71,12 +68,12 @@ def request_done(request_id):
def setup(hass, config): def setup(hass, config):
""" Set up Configurator. """ """Setup the configurator component."""
return True return True
def _get_instance(hass): def _get_instance(hass):
""" Get an instance per hass object. """ """Get an instance per hass object."""
try: try:
return _INSTANCES[hass] return _INSTANCES[hass]
except KeyError: except KeyError:
@ -89,10 +86,7 @@ def _get_instance(hass):
class Configurator(object): class Configurator(object):
""" """Class to keep track of current configuration requests."""
Class to keep track of current configuration requests.
"""
def __init__(self, hass): def __init__(self, hass):
self.hass = hass self.hass = hass
self._cur_id = 0 self._cur_id = 0
@ -104,8 +98,7 @@ class Configurator(object):
def request_config( def request_config(
self, name, callback, self, name, callback,
description, description_image, submit_caption, fields): description, description_image, submit_caption, fields):
""" Setup a request for configuration. """ """Setup a request for configuration."""
entity_id = generate_entity_id(ENTITY_ID_FORMAT, name, hass=self.hass) entity_id = generate_entity_id(ENTITY_ID_FORMAT, name, hass=self.hass)
if fields is None: if fields is None:
@ -133,7 +126,7 @@ class Configurator(object):
return request_id return request_id
def notify_errors(self, request_id, error): def notify_errors(self, request_id, error):
""" Update the state with errors. """ """Update the state with errors."""
if not self._validate_request_id(request_id): if not self._validate_request_id(request_id):
return return
@ -147,7 +140,7 @@ class Configurator(object):
self.hass.states.set(entity_id, STATE_CONFIGURE, new_data) self.hass.states.set(entity_id, STATE_CONFIGURE, new_data)
def request_done(self, request_id): def request_done(self, request_id):
""" Remove the config request. """ """Remove the configuration request."""
if not self._validate_request_id(request_id): if not self._validate_request_id(request_id):
return return
@ -160,13 +153,13 @@ class Configurator(object):
self.hass.states.set(entity_id, STATE_CONFIGURED) self.hass.states.set(entity_id, STATE_CONFIGURED)
def deferred_remove(event): def deferred_remove(event):
""" Remove the request state. """ """Remove the request state."""
self.hass.states.remove(entity_id) self.hass.states.remove(entity_id)
self.hass.bus.listen_once(EVENT_TIME_CHANGED, deferred_remove) self.hass.bus.listen_once(EVENT_TIME_CHANGED, deferred_remove)
def handle_service_call(self, call): def handle_service_call(self, call):
""" Handle a configure service call. """ """Handle a configure service call."""
request_id = call.data.get(ATTR_CONFIGURE_ID) request_id = call.data.get(ATTR_CONFIGURE_ID)
if not self._validate_request_id(request_id): if not self._validate_request_id(request_id):
@ -180,10 +173,10 @@ class Configurator(object):
callback(call.data.get(ATTR_FIELDS, {})) callback(call.data.get(ATTR_FIELDS, {}))
def _generate_unique_id(self): def _generate_unique_id(self):
""" Generates a unique configurator id. """ """Generates a unique configurator ID."""
self._cur_id += 1 self._cur_id += 1
return "{}-{}".format(id(self), self._cur_id) return "{}-{}".format(id(self), self._cur_id)
def _validate_request_id(self, request_id): def _validate_request_id(self, request_id):
""" Validate that the request belongs to this instance. """ """Validate that the request belongs to this instance."""
return request_id in self._requests return request_id in self._requests

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.conversation Support for functionality to have conversations with Home Assistant.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides functionality to have conversations with Home Assistant.
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/conversation/ https://home-assistant.io/components/conversation/
@ -25,13 +23,13 @@ REQUIREMENTS = ['fuzzywuzzy==0.8.0']
def setup(hass, config): def setup(hass, config):
""" Registers the process service. """ """Registers the process service."""
from fuzzywuzzy import process as fuzzyExtract from fuzzywuzzy import process as fuzzyExtract
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
def process(service): def process(service):
""" Parses text into commands for Home Assistant. """ """Parses text into commands."""
if ATTR_TEXT not in service.data: if ATTR_TEXT not in service.data:
logger.error("Received process service call without a text") logger.error("Received process service call without a text")
return return

View File

@ -29,7 +29,7 @@ CONF_DEVICE_GROUP = 'device_group'
# pylint: disable=too-many-locals # pylint: disable=too-many-locals
def setup(hass, config): def setup(hass, config):
""" Triggers to turn lights on or off based on device precense. """ """Triggers to turn lights on or off based on device presence."""
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
device_tracker = get_component('device_tracker') device_tracker = get_component('device_tracker')
group = get_component('group') group = get_component('group')
@ -78,26 +78,29 @@ def setup(hass, config):
@track_state_change(sun.ENTITY_ID, sun.STATE_BELOW_HORIZON, @track_state_change(sun.ENTITY_ID, sun.STATE_BELOW_HORIZON,
sun.STATE_ABOVE_HORIZON) sun.STATE_ABOVE_HORIZON)
def schedule_lights_at_sun_set(hass, entity, old_state, new_state): def schedule_lights_at_sun_set(hass, entity, old_state, new_state):
"""The moment sun sets we want to have all the lights on. """
We will schedule to have each light start after one another The moment sun sets we want to have all the lights on.
and slowly transition in.""" We will schedule to have each light start after one another
and slowly transition in.
"""
start_point = calc_time_for_light_when_sunset() start_point = calc_time_for_light_when_sunset()
if not start_point: if not start_point:
return return
def turn_on(light_id): def turn_on(light_id):
""" Lambda can keep track of function parameters but not local """
Lambda can keep track of function parameters but not local
parameters. If we put the lambda directly in the below statement parameters. If we put the lambda directly in the below statement
only the last light will be turned on.. """ only the last light will be turned on.
"""
return lambda now: turn_light_on_before_sunset(light_id) return lambda now: turn_light_on_before_sunset(light_id)
for index, light_id in enumerate(light_ids): for index, light_id in enumerate(light_ids):
track_point_in_time(hass, turn_on(light_id), track_point_in_time(hass, turn_on(light_id),
start_point + index * LIGHT_TRANSITION_TIME) start_point + index * LIGHT_TRANSITION_TIME)
# If the sun is already above horizon # If the sun is already above horizon schedule the time-based pre-sun set
# schedule the time-based pre-sun set event # event.
if sun.is_on(hass): if sun.is_on(hass):
schedule_lights_at_sun_set(hass, None, None, None) schedule_lights_at_sun_set(hass, None, None, None)

View File

@ -37,8 +37,8 @@ SERVICE_HANDLERS = {
def listen(hass, service, callback): def listen(hass, service, callback):
"""Setup listener for discovery of specific service. """
Setup listener for discovery of specific service.
Service can be a string or a list/tuple. Service can be a string or a list/tuple.
""" """
if isinstance(service, str): if isinstance(service, str):
@ -55,10 +55,7 @@ def listen(hass, service, callback):
def discover(hass, service, discovered=None, component=None, hass_config=None): def discover(hass, service, discovered=None, component=None, hass_config=None):
"""Fire discovery event. """Fire discovery event. Can ensure a component is loaded."""
Can ensure a component is loaded.
"""
if component is not None: if component is not None:
bootstrap.setup_component(hass, component, hass_config) bootstrap.setup_component(hass, component, hass_config)
@ -73,7 +70,7 @@ def discover(hass, service, discovered=None, component=None, hass_config=None):
def setup(hass, config): def setup(hass, config):
""" Starts a discovery service. """ """Starts a discovery service."""
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
from netdisco.service import DiscoveryService from netdisco.service import DiscoveryService
@ -84,13 +81,13 @@ def setup(hass, config):
lock = threading.Lock() lock = threading.Lock()
def new_service_listener(service, info): def new_service_listener(service, info):
""" Called when a new service is found. """ """Called when a new service is found."""
with lock: with lock:
logger.info("Found new service: %s %s", service, info) logger.info("Found new service: %s %s", service, info)
component = SERVICE_HANDLERS.get(service) component = SERVICE_HANDLERS.get(service)
# We do not know how to handle this service # We do not know how to handle this service.
if not component: if not component:
return return
@ -105,7 +102,7 @@ def setup(hass, config):
# pylint: disable=unused-argument # pylint: disable=unused-argument
def start_discovery(event): def start_discovery(event):
""" Start discovering. """ """Start discovering."""
netdisco = DiscoveryService(SCAN_INTERVAL) netdisco = DiscoveryService(SCAN_INTERVAL)
netdisco.add_listener(new_service_listener) netdisco.add_listener(new_service_listener)
netdisco.start() netdisco.start()

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.downloader Support for functionality to download files.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides functionality to download files.
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/downloader/ https://home-assistant.io/components/downloader/
@ -28,8 +26,7 @@ CONF_DOWNLOAD_DIR = 'download_dir'
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
def setup(hass, config): def setup(hass, config):
""" Listens for download events to download files. """ """Listens for download events to download files."""
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
if not validate_config(config, {DOMAIN: [CONF_DOWNLOAD_DIR]}, logger): if not validate_config(config, {DOMAIN: [CONF_DOWNLOAD_DIR]}, logger):
@ -50,14 +47,13 @@ def setup(hass, config):
return False return False
def download_file(service): def download_file(service):
""" Starts thread to download file specified in the url. """ """Starts thread to download file specified in the URL."""
if ATTR_URL not in service.data: if ATTR_URL not in service.data:
logger.error("Service called but 'url' parameter not specified.") logger.error("Service called but 'url' parameter not specified.")
return return
def do_download(): def do_download():
""" Downloads the file. """ """Downloads the file."""
try: try:
url = service.data[ATTR_URL] url = service.data[ATTR_URL]

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.ecobee Support for Ecobee.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Ecobee component
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/ecobee/ https://home-assistant.io/components/ecobee/
@ -31,12 +29,12 @@ _LOGGER = logging.getLogger(__name__)
ECOBEE_CONFIG_FILE = 'ecobee.conf' ECOBEE_CONFIG_FILE = 'ecobee.conf'
_CONFIGURING = {} _CONFIGURING = {}
# Return cached results if last scan was less then this time ago # Return cached results if last scan was less then this time ago.
MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=180) MIN_TIME_BETWEEN_UPDATES = timedelta(seconds=180)
def request_configuration(network, hass, config): def request_configuration(network, hass, config):
""" Request configuration steps from the user. """ """Request configuration steps from the user."""
configurator = get_component('configurator') configurator = get_component('configurator')
if 'ecobee' in _CONFIGURING: if 'ecobee' in _CONFIGURING:
configurator.notify_errors( configurator.notify_errors(
@ -46,7 +44,7 @@ def request_configuration(network, hass, config):
# pylint: disable=unused-argument # pylint: disable=unused-argument
def ecobee_configuration_callback(callback_data): def ecobee_configuration_callback(callback_data):
""" Actions to do when our configuration callback is called. """ """Actions to do when our configuration callback is called."""
network.request_tokens() network.request_tokens()
network.update() network.update()
setup_ecobee(hass, network, config) setup_ecobee(hass, network, config)
@ -62,7 +60,7 @@ def request_configuration(network, hass, config):
def setup_ecobee(hass, network, config): def setup_ecobee(hass, network, config):
""" Setup Ecobee thermostat. """ """Setup Ecobee thermostat."""
# If ecobee has a PIN then it needs to be configured. # If ecobee has a PIN then it needs to be configured.
if network.pin is not None: if network.pin is not None:
request_configuration(network, hass, config) request_configuration(network, hass, config)
@ -93,15 +91,14 @@ def setup_ecobee(hass, network, config):
# pylint: disable=too-few-public-methods # pylint: disable=too-few-public-methods
class EcobeeData(object): class EcobeeData(object):
""" Gets the latest data and update the states. """ """Gets the latest data and update the states."""
def __init__(self, config_file): def __init__(self, config_file):
from pyecobee import Ecobee from pyecobee import Ecobee
self.ecobee = Ecobee(config_file) self.ecobee = Ecobee(config_file)
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)
def update(self): def update(self):
""" Get the latest data from pyecobee. """ """Get the latest data from pyecobee."""
self.ecobee.update() self.ecobee.update()
_LOGGER.info("ecobee data updated successfully.") _LOGGER.info("ecobee data updated successfully.")

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.history
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provide pre-made queries on top of the recorder component. Provide pre-made queries on top of the recorder component.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
@ -26,7 +24,7 @@ URL_HISTORY_PERIOD = re.compile(
def last_5_states(entity_id): def last_5_states(entity_id):
""" Return the last 5 states for entity_id. """ """Return the last 5 states for entity_id."""
entity_id = entity_id.lower() entity_id = entity_id.lower()
query = """ query = """
@ -39,12 +37,12 @@ def last_5_states(entity_id):
def get_significant_states(start_time, end_time=None, entity_id=None): def get_significant_states(start_time, end_time=None, entity_id=None):
"""Return states changes during UTC period start_time - end_time. """
Return states changes during UTC period start_time - end_time.
Significant states are all states where there is a state change, Significant states are all states where there is a state change,
as well as all states from certain domains (for instance as well as all states from certain domains (for instance
thermostat so that we get current temperature in our graphs). thermostat so that we get current temperature in our graphs).
""" """
where = """ where = """
(domain IN ({}) OR last_changed=last_updated) (domain IN ({}) OR last_changed=last_updated)
@ -95,7 +93,7 @@ def state_changes_during_period(start_time, end_time=None, entity_id=None):
def get_states(utc_point_in_time, entity_ids=None, run=None): def get_states(utc_point_in_time, entity_ids=None, run=None):
""" Returns the states at a specific point in time. """ """Returns the states at a specific point in time."""
if run is None: if run is None:
run = recorder.run_information(utc_point_in_time) run = recorder.run_information(utc_point_in_time)
@ -124,7 +122,8 @@ def get_states(utc_point_in_time, entity_ids=None, run=None):
def states_to_json(states, start_time, entity_id): def states_to_json(states, start_time, entity_id):
"""Converts SQL results into JSON friendly data structure. """
Converts SQL results into JSON friendly data structure.
This takes our state list and turns it into a JSON friendly data This takes our state list and turns it into a JSON friendly data
structure {'entity_id': [list of states], 'entity_id2': [list of states]} structure {'entity_id': [list of states], 'entity_id2': [list of states]}
@ -133,7 +132,6 @@ def states_to_json(states, start_time, entity_id):
each list of states, otherwise our graphs won't start on the Y each list of states, otherwise our graphs won't start on the Y
axis correctly. axis correctly.
""" """
result = defaultdict(list) result = defaultdict(list)
entity_ids = [entity_id] if entity_id is not None else None entity_ids = [entity_id] if entity_id is not None else None
@ -151,7 +149,7 @@ def states_to_json(states, start_time, entity_id):
def get_state(utc_point_in_time, entity_id, run=None): def get_state(utc_point_in_time, entity_id, run=None):
""" Return a state at a specific point in time. """ """Return a state at a specific point in time."""
states = get_states(utc_point_in_time, (entity_id,), run) states = get_states(utc_point_in_time, (entity_id,), run)
return states[0] if states else None return states[0] if states else None
@ -159,7 +157,7 @@ def get_state(utc_point_in_time, entity_id, run=None):
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup(hass, config): def setup(hass, config):
""" Setup history hooks. """ """Setup history hooks."""
hass.http.register_path( hass.http.register_path(
'GET', 'GET',
re.compile( re.compile(
@ -175,14 +173,14 @@ def setup(hass, config):
# pylint: disable=unused-argument # pylint: disable=unused-argument
# pylint: disable=invalid-name # pylint: disable=invalid-name
def _api_last_5_states(handler, path_match, data): def _api_last_5_states(handler, path_match, data):
""" Return the last 5 states for an entity id as JSON. """ """Return the last 5 states for an entity id as JSON."""
entity_id = path_match.group('entity_id') entity_id = path_match.group('entity_id')
handler.write_json(last_5_states(entity_id)) handler.write_json(last_5_states(entity_id))
def _api_history_period(handler, path_match, data): def _api_history_period(handler, path_match, data):
""" Return history over a period of time. """ """Return history over a period of time."""
date_str = path_match.group('date') date_str = path_match.group('date')
one_day = timedelta(seconds=86400) one_day = timedelta(seconds=86400)
@ -206,7 +204,8 @@ def _api_history_period(handler, path_match, data):
def _is_significant(state): def _is_significant(state):
"""Test if state is significant for history charts. """
Test if state is significant for history charts.
Will only test for things that are not filtered out in SQL. Will only test for things that are not filtered out in SQL.
""" """

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.http
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This module provides an API and a HTTP interface for debug purposes. This module provides an API and a HTTP interface for debug purposes.
For more details about the RESTful API, please refer to the documentation at For more details about the RESTful API, please refer to the documentation at
@ -52,7 +50,7 @@ _LOGGER = logging.getLogger(__name__)
def setup(hass, config): def setup(hass, config):
""" Sets up the HTTP API and debug interface. """ """Sets up the HTTP API and debug interface."""
conf = config.get(DOMAIN, {}) conf = config.get(DOMAIN, {})
api_password = util.convert(conf.get(CONF_API_PASSWORD), str) api_password = util.convert(conf.get(CONF_API_PASSWORD), str)
@ -87,9 +85,8 @@ def setup(hass, config):
# pylint: disable=too-many-instance-attributes # pylint: disable=too-many-instance-attributes
class HomeAssistantHTTPServer(ThreadingMixIn, HTTPServer): class HomeAssistantHTTPServer(ThreadingMixIn, HTTPServer):
""" Handle HTTP requests in a threaded fashion. """ """Handle HTTP requests in a threaded fashion."""
# pylint: disable=too-few-public-methods # pylint: disable=too-few-public-methods
allow_reuse_address = True allow_reuse_address = True
daemon_threads = True daemon_threads = True
@ -119,9 +116,9 @@ class HomeAssistantHTTPServer(ThreadingMixIn, HTTPServer):
self.socket = context.wrap_socket(self.socket, server_side=True) self.socket = context.wrap_socket(self.socket, server_side=True)
def start(self): def start(self):
""" Starts the HTTP server. """ """Starts the HTTP server."""
def stop_http(event): def stop_http(event):
""" Stops the HTTP server. """ """Stops the HTTP server."""
self.shutdown() self.shutdown()
self.hass.bus.listen_once(ha.EVENT_HOMEASSISTANT_STOP, stop_http) self.hass.bus.listen_once(ha.EVENT_HOMEASSISTANT_STOP, stop_http)
@ -140,11 +137,11 @@ class HomeAssistantHTTPServer(ThreadingMixIn, HTTPServer):
self.serve_forever() self.serve_forever()
def register_path(self, method, url, callback, require_auth=True): def register_path(self, method, url, callback, require_auth=True):
""" Registers a path with the server. """ """Registers a path with the server."""
self.paths.append((method, url, callback, require_auth)) self.paths.append((method, url, callback, require_auth))
def log_message(self, fmt, *args): def log_message(self, fmt, *args):
""" Redirect built-in log to HA logging """ """Redirect built-in log to HA logging."""
# pylint: disable=no-self-use # pylint: disable=no-self-use
_LOGGER.info(fmt, *args) _LOGGER.info(fmt, *args)
@ -157,17 +154,16 @@ class RequestHandler(SimpleHTTPRequestHandler):
We extend from SimpleHTTPRequestHandler instead of Base so we We extend from SimpleHTTPRequestHandler instead of Base so we
can use the guess content type methods. can use the guess content type methods.
""" """
server_version = "HomeAssistant/1.0" server_version = "HomeAssistant/1.0"
def __init__(self, req, client_addr, server): def __init__(self, req, client_addr, server):
""" Contructor, call the base constructor and set up session """ """Contructor, call the base constructor and set up session."""
# Track if this was an authenticated request # Track if this was an authenticated request
self.authenticated = False self.authenticated = False
SimpleHTTPRequestHandler.__init__(self, req, client_addr, server) SimpleHTTPRequestHandler.__init__(self, req, client_addr, server)
def log_message(self, fmt, *arguments): def log_message(self, fmt, *arguments):
""" Redirect built-in log to HA logging """ """Redirect built-in log to HA logging."""
if self.server.api_password is None: if self.server.api_password is None:
_LOGGER.info(fmt, *arguments) _LOGGER.info(fmt, *arguments)
else: else:
@ -176,7 +172,7 @@ class RequestHandler(SimpleHTTPRequestHandler):
if isinstance(arg, str) else arg for arg in arguments)) if isinstance(arg, str) else arg for arg in arguments))
def _handle_request(self, method): # pylint: disable=too-many-branches def _handle_request(self, method): # pylint: disable=too-many-branches
""" Does some common checks and calls appropriate method. """ """Does some common checks and calls appropriate method."""
url = urlparse(self.path) url = urlparse(self.path)
# Read query input. parse_qs gives a list for each value, we want last # Read query input. parse_qs gives a list for each value, we want last
@ -254,31 +250,31 @@ class RequestHandler(SimpleHTTPRequestHandler):
self.end_headers() self.end_headers()
def do_HEAD(self): # pylint: disable=invalid-name def do_HEAD(self): # pylint: disable=invalid-name
""" HEAD request handler. """ """HEAD request handler."""
self._handle_request('HEAD') self._handle_request('HEAD')
def do_GET(self): # pylint: disable=invalid-name def do_GET(self): # pylint: disable=invalid-name
""" GET request handler. """ """GET request handler."""
self._handle_request('GET') self._handle_request('GET')
def do_POST(self): # pylint: disable=invalid-name def do_POST(self): # pylint: disable=invalid-name
""" POST request handler. """ """POST request handler."""
self._handle_request('POST') self._handle_request('POST')
def do_PUT(self): # pylint: disable=invalid-name def do_PUT(self): # pylint: disable=invalid-name
""" PUT request handler. """ """PUT request handler."""
self._handle_request('PUT') self._handle_request('PUT')
def do_DELETE(self): # pylint: disable=invalid-name def do_DELETE(self): # pylint: disable=invalid-name
""" DELETE request handler. """ """DELETE request handler."""
self._handle_request('DELETE') self._handle_request('DELETE')
def write_json_message(self, message, status_code=HTTP_OK): def write_json_message(self, message, status_code=HTTP_OK):
""" Helper method to return a message to the caller. """ """Helper method to return a message to the caller."""
self.write_json({'message': message}, status_code=status_code) self.write_json({'message': message}, status_code=status_code)
def write_json(self, data=None, status_code=HTTP_OK, location=None): def write_json(self, data=None, status_code=HTTP_OK, location=None):
""" Helper method to return JSON to the caller. """ """Helper method to return JSON to the caller."""
self.send_response(status_code) self.send_response(status_code)
self.send_header(HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON) self.send_header(HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON)
@ -295,7 +291,7 @@ class RequestHandler(SimpleHTTPRequestHandler):
cls=rem.JSONEncoder).encode("UTF-8")) cls=rem.JSONEncoder).encode("UTF-8"))
def write_text(self, message, status_code=HTTP_OK): def write_text(self, message, status_code=HTTP_OK):
""" Helper method to return a text message to the caller. """ """Helper method to return a text message to the caller."""
self.send_response(status_code) self.send_response(status_code)
self.send_header(HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_TEXT_PLAIN) self.send_header(HTTP_HEADER_CONTENT_TYPE, CONTENT_TYPE_TEXT_PLAIN)
@ -306,7 +302,7 @@ class RequestHandler(SimpleHTTPRequestHandler):
self.wfile.write(message.encode("UTF-8")) self.wfile.write(message.encode("UTF-8"))
def write_file(self, path, cache_headers=True): def write_file(self, path, cache_headers=True):
""" Returns a file to the user. """ """Returns a file to the user."""
try: try:
with open(path, 'rb') as inp: with open(path, 'rb') as inp:
self.write_file_pointer(self.guess_type(path), inp, self.write_file_pointer(self.guess_type(path), inp,
@ -354,7 +350,7 @@ class RequestHandler(SimpleHTTPRequestHandler):
self.copyfile(inp, self.wfile) self.copyfile(inp, self.wfile)
def set_cache_header(self): def set_cache_header(self):
""" Add cache headers if not in development """ """Add cache headers if not in development."""
if self.server.development: if self.server.development:
return return
@ -369,7 +365,7 @@ class RequestHandler(SimpleHTTPRequestHandler):
self.date_time_string(time.time()+cache_time)) self.date_time_string(time.time()+cache_time))
def set_session_cookie_header(self): def set_session_cookie_header(self):
""" Add the header for the session cookie and return session id. """ """Add the header for the session cookie and return session ID."""
if not self.authenticated: if not self.authenticated:
return None return None
@ -387,13 +383,13 @@ class RequestHandler(SimpleHTTPRequestHandler):
return session_id return session_id
def verify_session(self): def verify_session(self):
""" Verify that we are in a valid session. """ """Verify that we are in a valid session."""
return self.get_cookie_session_id() is not None return self.get_cookie_session_id() is not None
def get_cookie_session_id(self): def get_cookie_session_id(self):
""" """
Extracts the current session id from the Extracts the current session id from the cookie or returns None if not
cookie or returns None if not set or invalid set or invalid.
""" """
if 'Cookie' not in self.headers: if 'Cookie' not in self.headers:
return None return None
@ -417,7 +413,7 @@ class RequestHandler(SimpleHTTPRequestHandler):
return None return None
def destroy_session(self): def destroy_session(self):
""" Destroys session. """ """Destroys session."""
session_id = self.get_cookie_session_id() session_id = self.get_cookie_session_id()
if session_id is None: if session_id is None:
@ -428,27 +424,27 @@ class RequestHandler(SimpleHTTPRequestHandler):
def session_valid_time(): def session_valid_time():
""" Time till when a session will be valid. """ """Time till when a session will be valid."""
return date_util.utcnow() + timedelta(seconds=SESSION_TIMEOUT_SECONDS) return date_util.utcnow() + timedelta(seconds=SESSION_TIMEOUT_SECONDS)
class SessionStore(object): class SessionStore(object):
""" Responsible for storing and retrieving http sessions """ """Responsible for storing and retrieving HTTP sessions."""
def __init__(self): def __init__(self):
""" Set up the session store """ """Setup the session store."""
self._sessions = {} self._sessions = {}
self._lock = threading.RLock() self._lock = threading.RLock()
@util.Throttle(SESSION_CLEAR_INTERVAL) @util.Throttle(SESSION_CLEAR_INTERVAL)
def _remove_expired(self): def _remove_expired(self):
""" Remove any expired sessions. """ """Remove any expired sessions."""
now = date_util.utcnow() now = date_util.utcnow()
for key in [key for key, valid_time in self._sessions.items() for key in [key for key, valid_time in self._sessions.items()
if valid_time < now]: if valid_time < now]:
self._sessions.pop(key) self._sessions.pop(key)
def is_valid(self, key): def is_valid(self, key):
""" Return True if a valid session is given. """ """Return True if a valid session is given."""
with self._lock: with self._lock:
self._remove_expired() self._remove_expired()
@ -456,19 +452,19 @@ class SessionStore(object):
self._sessions[key] > date_util.utcnow()) self._sessions[key] > date_util.utcnow())
def extend_validation(self, key): def extend_validation(self, key):
""" Extend a session validation time. """ """Extend a session validation time."""
with self._lock: with self._lock:
if key not in self._sessions: if key not in self._sessions:
return return
self._sessions[key] = session_valid_time() self._sessions[key] = session_valid_time()
def destroy(self, key): def destroy(self, key):
""" Destroy a session by key. """ """Destroy a session by key."""
with self._lock: with self._lock:
self._sessions.pop(key, None) self._sessions.pop(key, None)
def create(self): def create(self):
""" Creates a new session. """ """Creates a new session."""
with self._lock: with self._lock:
session_id = util.get_random_string(20) session_id = util.get_random_string(20)

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.ifttt Support to trigger Maker IFTTT recipes.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
This component enable you to trigger Maker IFTTT recipes.
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/ifttt/ https://home-assistant.io/components/ifttt/
@ -27,7 +25,7 @@ REQUIREMENTS = ['pyfttt==0.3']
def trigger(hass, event, value1=None, value2=None, value3=None): def trigger(hass, event, value1=None, value2=None, value3=None):
""" Trigger a Maker IFTTT recipe. """ """Trigger a Maker IFTTT recipe."""
data = { data = {
ATTR_EVENT: event, ATTR_EVENT: event,
ATTR_VALUE1: value1, ATTR_VALUE1: value1,
@ -38,15 +36,14 @@ def trigger(hass, event, value1=None, value2=None, value3=None):
def setup(hass, config): def setup(hass, config):
""" Setup the ifttt service component. """ """Setup the IFTTT service component."""
if not validate_config(config, {DOMAIN: ['key']}, _LOGGER): if not validate_config(config, {DOMAIN: ['key']}, _LOGGER):
return False return False
key = config[DOMAIN]['key'] key = config[DOMAIN]['key']
def trigger_service(call): def trigger_service(call):
""" Handle ifttt trigger service calls. """ """Handle IFTTT trigger service calls."""
event = call.data.get(ATTR_EVENT) event = call.data.get(ATTR_EVENT)
value1 = call.data.get(ATTR_VALUE1) value1 = call.data.get(ATTR_VALUE1)
value2 = call.data.get(ATTR_VALUE2) value2 = call.data.get(ATTR_VALUE2)

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.input_boolean
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component to keep track of user controlled booleans for within automation. Component to keep track of user controlled booleans for within automation.
For more details about this component, please refer to the documentation For more details about this component, please refer to the documentation
@ -41,7 +39,7 @@ def turn_off(hass, entity_id):
def setup(hass, config): def setup(hass, config):
""" Set up input boolean. """ """Set up input boolean."""
if not isinstance(config.get(DOMAIN), dict): if not isinstance(config.get(DOMAIN), dict):
_LOGGER.error('Expected %s config to be a dictionary', DOMAIN) _LOGGER.error('Expected %s config to be a dictionary', DOMAIN)
return False return False
@ -68,7 +66,7 @@ def setup(hass, config):
return False return False
def toggle_service(service): def toggle_service(service):
""" Handle a calls to the input boolean services. """ """Handle a calls to the input boolean services."""
target_inputs = component.extract_from_service(service) target_inputs = component.extract_from_service(service)
for input_b in target_inputs: for input_b in target_inputs:
@ -86,8 +84,7 @@ def setup(hass, config):
class InputBoolean(ToggleEntity): class InputBoolean(ToggleEntity):
""" Represent a boolean input. """ """Represent a boolean input."""
def __init__(self, object_id, name, state, icon): def __init__(self, object_id, name, state, icon):
""" Initialize a boolean input. """ """ Initialize a boolean input. """
self.entity_id = ENTITY_ID_FORMAT.format(object_id) self.entity_id = ENTITY_ID_FORMAT.format(object_id)
@ -97,22 +94,22 @@ class InputBoolean(ToggleEntity):
@property @property
def should_poll(self): def should_poll(self):
"""If entitiy should be polled.""" """If entity should be polled."""
return False return False
@property @property
def name(self): def name(self):
"""Name of the boolean input.""" """Return name of the boolean input."""
return self._name return self._name
@property @property
def icon(self): def icon(self):
"""Icon to be used for this entity.""" """Returh the icon to be used for this entity."""
return self._icon return self._icon
@property @property
def is_on(self): def is_on(self):
"""True if entity is on.""" """Return true if entity is on."""
return self._state return self._state
def turn_on(self, **kwargs): def turn_on(self, **kwargs):

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.input_select
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component to offer a way to select an option from a list. Component to offer a way to select an option from a list.
For more details about this component, please refer to the documentation For more details about this component, please refer to the documentation
@ -29,7 +27,7 @@ SERVICE_SELECT_OPTION = 'select_option'
def select_option(hass, entity_id, option): def select_option(hass, entity_id, option):
""" Set input_select to False. """ """Set input_select to False."""
hass.services.call(DOMAIN, SERVICE_SELECT_OPTION, { hass.services.call(DOMAIN, SERVICE_SELECT_OPTION, {
ATTR_ENTITY_ID: entity_id, ATTR_ENTITY_ID: entity_id,
ATTR_OPTION: option, ATTR_OPTION: option,
@ -37,7 +35,7 @@ def select_option(hass, entity_id, option):
def setup(hass, config): def setup(hass, config):
""" Set up input select. """ """Setup input select."""
if not isinstance(config.get(DOMAIN), dict): if not isinstance(config.get(DOMAIN), dict):
_LOGGER.error('Expected %s config to be a dictionary', DOMAIN) _LOGGER.error('Expected %s config to be a dictionary', DOMAIN)
return False return False
@ -77,7 +75,7 @@ def setup(hass, config):
return False return False
def select_option_service(call): def select_option_service(call):
""" Handle a calls to the input select services. """ """Handle a calls to the input select services."""
target_inputs = component.extract_from_service(call) target_inputs = component.extract_from_service(call)
for input_select in target_inputs: for input_select in target_inputs:
@ -92,8 +90,7 @@ def setup(hass, config):
class InputSelect(Entity): class InputSelect(Entity):
""" Represent a select input. """ """Represent a select input."""
# pylint: disable=too-many-arguments # pylint: disable=too-many-arguments
def __init__(self, object_id, name, state, options, icon): def __init__(self, object_id, name, state, options, icon):
""" Initialize a select input. """ """ Initialize a select input. """
@ -105,33 +102,33 @@ class InputSelect(Entity):
@property @property
def should_poll(self): def should_poll(self):
""" If entity should be polled. """ """If entity should be polled."""
return False return False
@property @property
def name(self): def name(self):
""" Name of the select input. """ """Return the name of the select input."""
return self._name return self._name
@property @property
def icon(self): def icon(self):
""" Icon to be used for this entity. """ """Return the icon to be used for this entity."""
return self._icon return self._icon
@property @property
def state(self): def state(self):
""" State of the component. """ """Return the state of the component."""
return self._current_option return self._current_option
@property @property
def state_attributes(self): def state_attributes(self):
""" State attributes. """ """Return the state attributes."""
return { return {
ATTR_OPTIONS: self._options, ATTR_OPTIONS: self._options,
} }
def select_option(self, option): def select_option(self, option):
""" Select new option. """ """Select new option."""
if option not in self._options: if option not in self._options:
_LOGGER.warning('Invalid option: %s (possible options: %s)', _LOGGER.warning('Invalid option: %s (possible options: %s)',
option, ', '.join(self._options)) option, ', '.join(self._options))

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.insteon_hub
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for Insteon Hub. Support for Insteon Hub.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
@ -58,24 +56,23 @@ def setup(hass, config):
class InsteonToggleDevice(ToggleEntity): class InsteonToggleDevice(ToggleEntity):
""" Abstract Class for an Insteon node. """ """ An abstract Class for an Insteon node."""
def __init__(self, node): def __init__(self, node):
self.node = node self.node = node
self._value = 0 self._value = 0
@property @property
def name(self): def name(self):
""" Returns the name of the node. """ """Return the the name of the node."""
return self.node.DeviceName return self.node.DeviceName
@property @property
def unique_id(self): def unique_id(self):
""" Returns the id of this insteon node. """ """Return the ID of this insteon node."""
return self.node.DeviceID return self.node.DeviceID
def update(self): def update(self):
""" Update state of the sensor. """ """Update state of the sensor."""
resp = self.node.send_command('get_status', wait=True) resp = self.node.send_command('get_status', wait=True)
try: try:
self._value = resp['response']['level'] self._value = resp['response']['level']
@ -84,7 +81,7 @@ class InsteonToggleDevice(ToggleEntity):
@property @property
def is_on(self): def is_on(self):
""" Returns boolean response if the node is on. """ """Return the boolean response if the node is on."""
return self._value != 0 return self._value != 0
def turn_on(self, **kwargs): def turn_on(self, **kwargs):

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.introduction
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component that will help guide the user taking its first steps. Component that will help guide the user taking its first steps.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
@ -12,7 +10,7 @@ DOMAIN = 'introduction'
def setup(hass, config=None): def setup(hass, config=None):
""" Setup the introduction component. """ """Setup the introduction component."""
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
log.info(""" log.info("""

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.isy994 Support the ISY-994 controllers.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Connects to an ISY-994 controller and loads relevant components to control its
devices. Also contains the base classes for ISY Sensors, Lights, and Switches.
For configuration details please visit the documentation for this component at For configuration details please visit the documentation for this component at
https://home-assistant.io/components/isy994/ https://home-assistant.io/components/isy994/
@ -45,7 +42,7 @@ def setup(hass, config):
_LOGGER): _LOGGER):
return False return False
# pull and parse standard configuration # Pull and parse standard configuration.
user = config[DOMAIN][CONF_USERNAME] user = config[DOMAIN][CONF_USERNAME]
password = config[DOMAIN][CONF_PASSWORD] password = config[DOMAIN][CONF_PASSWORD]
host = urlparse(config[DOMAIN][CONF_HOST]) host = urlparse(config[DOMAIN][CONF_HOST])
@ -62,24 +59,24 @@ def setup(hass, config):
port = host.port port = host.port
addr = addr.replace(':{}'.format(port), '') addr = addr.replace(':{}'.format(port), '')
# pull and parse optional configuration # Pull and parse optional configuration.
global SENSOR_STRING global SENSOR_STRING
global HIDDEN_STRING global HIDDEN_STRING
SENSOR_STRING = str(config[DOMAIN].get('sensor_string', SENSOR_STRING)) SENSOR_STRING = str(config[DOMAIN].get('sensor_string', SENSOR_STRING))
HIDDEN_STRING = str(config[DOMAIN].get('hidden_string', HIDDEN_STRING)) HIDDEN_STRING = str(config[DOMAIN].get('hidden_string', HIDDEN_STRING))
tls_version = config[DOMAIN].get(CONF_TLS_VER, None) tls_version = config[DOMAIN].get(CONF_TLS_VER, None)
# connect to ISY controller # Connect to ISY controller.
global ISY global ISY
ISY = PyISY.ISY(addr, port, user, password, use_https=https, ISY = PyISY.ISY(addr, port, user, password, use_https=https,
tls_ver=tls_version, log=_LOGGER) tls_ver=tls_version, log=_LOGGER)
if not ISY.connected: if not ISY.connected:
return False return False
# listen for HA stop to disconnect # Listen for HA stop to disconnect.
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop)
# Load components for the devices in the ISY controller that we support # Load components for the devices in the ISY controller that we support.
for comp_name, discovery in ((('sensor', DISCOVER_SENSORS), for comp_name, discovery in ((('sensor', DISCOVER_SENSORS),
('light', DISCOVER_LIGHTS), ('light', DISCOVER_LIGHTS),
('switch', DISCOVER_SWITCHES))): ('switch', DISCOVER_SWITCHES))):
@ -94,13 +91,12 @@ def setup(hass, config):
def stop(event): def stop(event):
""" Cleanup the ISY subscription. """ """Cleanup the ISY subscription."""
ISY.auto_update = False ISY.auto_update = False
class ISYDeviceABC(ToggleEntity): class ISYDeviceABC(ToggleEntity):
""" Abstract Class for an ISY device. """ """An abstract Class for an ISY device."""
_attrs = {} _attrs = {}
_onattrs = [] _onattrs = []
_states = [] _states = []
@ -117,35 +113,35 @@ class ISYDeviceABC(ToggleEntity):
subscribe('changed', self.on_update) subscribe('changed', self.on_update)
def __del__(self): def __del__(self):
""" cleanup subscriptions because it is the right thing to do. """ """Cleanup subscriptions because it is the right thing to do."""
self._change_handler.unsubscribe() self._change_handler.unsubscribe()
@property @property
def domain(self): def domain(self):
""" Returns the domain of the entity. """ """Return the domain of the entity."""
return self._domain return self._domain
@property @property
def dtype(self): def dtype(self):
""" Returns the data type of the entity (binary or analog). """ """Return the data type of the entity (binary or analog)."""
if self._dtype in ['analog', 'binary']: if self._dtype in ['analog', 'binary']:
return self._dtype return self._dtype
return 'binary' if self.unit_of_measurement is None else 'analog' return 'binary' if self.unit_of_measurement is None else 'analog'
@property @property
def should_poll(self): def should_poll(self):
""" Tells Home Assistant not to poll this entity. """ """No polling needed."""
return False return False
@property @property
def value(self): def value(self):
""" Returns the unclean value from the controller. """ """Return the unclean value from the controller."""
# pylint: disable=protected-access # pylint: disable=protected-access
return self.node.status._val return self.node.status._val
@property @property
def state_attributes(self): def state_attributes(self):
""" Returns the state attributes for the node. """ """Return the state attributes for the node."""
attr = {} attr = {}
for name, prop in self._attrs.items(): for name, prop in self._attrs.items():
attr[name] = getattr(self, prop) attr[name] = getattr(self, prop)
@ -153,61 +149,61 @@ class ISYDeviceABC(ToggleEntity):
return attr return attr
def _attr_filter(self, attr): def _attr_filter(self, attr):
""" Placeholder for attribute filters. """ """A Placeholder for attribute filters."""
# pylint: disable=no-self-use # pylint: disable=no-self-use
return attr return attr
@property @property
def unique_id(self): def unique_id(self):
""" Returns the id of this ISY sensor. """ """Return the ID of this ISY sensor."""
# pylint: disable=protected-access # pylint: disable=protected-access
return self.node._id return self.node._id
@property @property
def raw_name(self): def raw_name(self):
""" Returns the unclean node name. """ """Return the unclean node name."""
return str(self._name) \ return str(self._name) \
if self._name is not None else str(self.node.name) if self._name is not None else str(self.node.name)
@property @property
def name(self): def name(self):
""" Returns the cleaned name of the node. """ """Return the cleaned name of the node."""
return self.raw_name.replace(HIDDEN_STRING, '').strip() \ return self.raw_name.replace(HIDDEN_STRING, '').strip() \
.replace('_', ' ') .replace('_', ' ')
@property @property
def hidden(self): def hidden(self):
""" Suggestion if the entity should be hidden from UIs. """ """Suggestion if the entity should be hidden from UIs."""
return HIDDEN_STRING in self.raw_name return HIDDEN_STRING in self.raw_name
def update(self): def update(self):
""" Update state of the sensor. """ """Update state of the sensor."""
# ISY objects are automatically updated by the ISY's event stream # ISY objects are automatically updated by the ISY's event stream
pass pass
def on_update(self, event): def on_update(self, event):
""" Handles the update received event. """ """Handles the update received event."""
self.update_ha_state() self.update_ha_state()
@property @property
def is_on(self): def is_on(self):
""" Returns boolean response if the node is on. """ """Return a boolean response if the node is on."""
return bool(self.value) return bool(self.value)
@property @property
def is_open(self): def is_open(self):
""" Returns boolean respons if the node is open. On = Open. """ """Return boolean response if the node is open. On = Open."""
return self.is_on return self.is_on
@property @property
def state(self): def state(self):
""" Returns the state of the node. """ """Return the state of the node."""
if len(self._states) > 0: if len(self._states) > 0:
return self._states[0] if self.is_on else self._states[1] return self._states[0] if self.is_on else self._states[1]
return self.value return self.value
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
""" Turns the device on. """ """Turns the device on."""
if self.domain is not 'sensor': if self.domain is not 'sensor':
attrs = [kwargs.get(name) for name in self._onattrs] attrs = [kwargs.get(name) for name in self._onattrs]
self.node.on(*attrs) self.node.on(*attrs)
@ -215,7 +211,7 @@ class ISYDeviceABC(ToggleEntity):
_LOGGER.error('ISY cannot turn on sensors.') _LOGGER.error('ISY cannot turn on sensors.')
def turn_off(self, **kwargs): def turn_off(self, **kwargs):
""" Turns the device off. """ """Turns the device off."""
if self.domain is not 'sensor': if self.domain is not 'sensor':
self.node.off() self.node.off()
else: else:
@ -223,7 +219,7 @@ class ISYDeviceABC(ToggleEntity):
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
""" Returns the defined units of measurement or None. """ """Return the defined units of measurement or None."""
try: try:
return self.node.units return self.node.units
except AttributeError: except AttributeError:

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.keyboard
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides functionality to emulate keyboard presses on host machine. Provides functionality to emulate keyboard presses on host machine.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at
@ -16,37 +14,37 @@ REQUIREMENTS = ['pyuserinput==0.1.9']
def volume_up(hass): def volume_up(hass):
""" Press the keyboard button for volume up. """ """Press the keyboard button for volume up."""
hass.services.call(DOMAIN, SERVICE_VOLUME_UP) hass.services.call(DOMAIN, SERVICE_VOLUME_UP)
def volume_down(hass): def volume_down(hass):
""" Press the keyboard button for volume down. """ """Press the keyboard button for volume down."""
hass.services.call(DOMAIN, SERVICE_VOLUME_DOWN) hass.services.call(DOMAIN, SERVICE_VOLUME_DOWN)
def volume_mute(hass): def volume_mute(hass):
""" Press the keyboard button for muting volume. """ """Press the keyboard button for muting volume."""
hass.services.call(DOMAIN, SERVICE_VOLUME_MUTE) hass.services.call(DOMAIN, SERVICE_VOLUME_MUTE)
def media_play_pause(hass): def media_play_pause(hass):
""" Press the keyboard button for play/pause. """ """Press the keyboard button for play/pause."""
hass.services.call(DOMAIN, SERVICE_MEDIA_PLAY_PAUSE) hass.services.call(DOMAIN, SERVICE_MEDIA_PLAY_PAUSE)
def media_next_track(hass): def media_next_track(hass):
""" Press the keyboard button for next track. """ """Press the keyboard button for next track."""
hass.services.call(DOMAIN, SERVICE_MEDIA_NEXT_TRACK) hass.services.call(DOMAIN, SERVICE_MEDIA_NEXT_TRACK)
def media_prev_track(hass): def media_prev_track(hass):
""" Press the keyboard button for prev track. """ """Press the keyboard button for prev track. """
hass.services.call(DOMAIN, SERVICE_MEDIA_PREVIOUS_TRACK) hass.services.call(DOMAIN, SERVICE_MEDIA_PREVIOUS_TRACK)
def setup(hass, config): def setup(hass, config):
""" Listen for keyboard events. """ """Listen for keyboard events."""
import pykeyboard import pykeyboard
keyboard = pykeyboard.PyKeyboard() keyboard = pykeyboard.PyKeyboard()

View File

@ -56,7 +56,6 @@ def log_entry(hass, name, message, domain=None, entity_id=None):
def setup(hass, config): def setup(hass, config):
"""Listens for download events to download files.""" """Listens for download events to download files."""
def log_message(service): def log_message(service):
"""Handle sending notification message service calls.""" """Handle sending notification message service calls."""
message = service.data.get(ATTR_MESSAGE) message = service.data.get(ATTR_MESSAGE)
@ -101,7 +100,6 @@ def _handle_get_logbook(handler, path_match, data):
class Entry(object): class Entry(object):
"""A human readable version of the log.""" """A human readable version of the log."""
# pylint: disable=too-many-arguments, too-few-public-methods # pylint: disable=too-many-arguments, too-few-public-methods
def __init__(self, when=None, name=None, message=None, domain=None, def __init__(self, when=None, name=None, message=None, domain=None,
entity_id=None): entity_id=None):
@ -237,7 +235,6 @@ def _entry_message_from_state(domain, state):
"""Convert a state to a message for the logbook.""" """Convert a state to a message for the logbook."""
# We pass domain in so we don't have to split entity_id again # We pass domain in so we don't have to split entity_id again
# pylint: disable=too-many-return-statements # pylint: disable=too-many-return-statements
if domain == 'device_tracker': if domain == 'device_tracker':
if state.state == STATE_NOT_HOME: if state.state == STATE_NOT_HOME:
return 'is away' return 'is away'

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.logger
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component that will help set the level of logging for components. Component that will help set the level of logging for 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
@ -27,16 +25,15 @@ LOGGER_LOGS = 'logs'
class HomeAssistantLogFilter(logging.Filter): class HomeAssistantLogFilter(logging.Filter):
""" A log filter. """ """A log filter."""
# pylint: disable=no-init,too-few-public-methods # pylint: disable=no-init,too-few-public-methods
def __init__(self, logfilter): def __init__(self, logfilter):
super().__init__() super().__init__()
self.logfilter = logfilter self.logfilter = logfilter
def filter(self, record): def filter(self, record):
"""A filter to use."""
# Log with filtered severity # Log with filtered severity
if LOGGER_LOGS in self.logfilter: if LOGGER_LOGS in self.logfilter:
for filtername in self.logfilter[LOGGER_LOGS]: for filtername in self.logfilter[LOGGER_LOGS]:
@ -50,8 +47,7 @@ class HomeAssistantLogFilter(logging.Filter):
def setup(hass, config=None): def setup(hass, config=None):
""" Setup the logger component. """ """Setup the logger component."""
logfilter = dict() logfilter = dict()
# Set default log severity # Set default log severity

View File

@ -157,7 +157,6 @@ def pf_callback_factory(map_sv_types, devices, add_devices, entity_class):
class GatewayWrapper(object): class GatewayWrapper(object):
"""Gateway wrapper class.""" """Gateway wrapper class."""
def __init__(self, gateway, version, optimistic): def __init__(self, gateway, version, optimistic):
"""Setup class attributes on instantiation. """Setup class attributes on instantiation.

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.thermostat.nest Support for Nest thermostats.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Adds support for Nest thermostats.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/thermostat.nest/ https://home-assistant.io/components/thermostat.nest/
@ -18,7 +16,7 @@ NEST = None
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup(hass, config): def setup(hass, config):
""" Sets up the nest thermostat. """ """Setup the Nest thermostat component."""
global NEST global NEST
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.proximity
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component to monitor the proximity of devices to a particular zone and the Component to monitor the proximity of devices to a particular zone and the
direction of travel. direction of travel.
@ -32,13 +30,13 @@ _LOGGER = logging.getLogger(__name__)
def setup(hass, config): # pylint: disable=too-many-locals,too-many-statements def setup(hass, config): # pylint: disable=too-many-locals,too-many-statements
""" Get the zones and offsets from configuration.yaml. """ """Get the zones and offsets from configuration.yaml."""
ignored_zones = [] ignored_zones = []
if 'ignored_zones' in config[DOMAIN]: if 'ignored_zones' in config[DOMAIN]:
for variable in config[DOMAIN]['ignored_zones']: for variable in config[DOMAIN]['ignored_zones']:
ignored_zones.append(variable) ignored_zones.append(variable)
# Get the devices from configuration.yaml # Get the devices from configuration.yaml.
if 'devices' not in config[DOMAIN]: if 'devices' not in config[DOMAIN]:
_LOGGER.error('devices not found in config') _LOGGER.error('devices not found in config')
return False return False
@ -47,10 +45,10 @@ def setup(hass, config): # pylint: disable=too-many-locals,too-many-statements
for variable in config[DOMAIN]['devices']: for variable in config[DOMAIN]['devices']:
proximity_devices.append(variable) proximity_devices.append(variable)
# Get the direction of travel tolerance from configuration.yaml # Get the direction of travel tolerance from configuration.yaml.
tolerance = config[DOMAIN].get('tolerance', DEFAULT_TOLERANCE) tolerance = config[DOMAIN].get('tolerance', DEFAULT_TOLERANCE)
# Get the zone to monitor proximity to from configuration.yaml # Get the zone to monitor proximity to from configuration.yaml.
proximity_zone = config[DOMAIN].get('zone', DEFAULT_PROXIMITY_ZONE) proximity_zone = config[DOMAIN].get('zone', DEFAULT_PROXIMITY_ZONE)
entity_id = DOMAIN + '.' + proximity_zone entity_id = DOMAIN + '.' + proximity_zone
@ -59,7 +57,7 @@ def setup(hass, config): # pylint: disable=too-many-locals,too-many-statements
state = hass.states.get(proximity_zone) state = hass.states.get(proximity_zone)
zone_friendly_name = (state.name).lower() zone_friendly_name = (state.name).lower()
# set the default values # Set the default values.
dist_to_zone = 'not set' dist_to_zone = 'not set'
dir_of_travel = 'not set' dir_of_travel = 'not set'
nearest = 'not set' nearest = 'not set'
@ -71,7 +69,7 @@ def setup(hass, config): # pylint: disable=too-many-locals,too-many-statements
proximity.update_ha_state() proximity.update_ha_state()
# Main command to monitor proximity of devices # Main command to monitor proximity of devices.
track_state_change(hass, proximity_devices, track_state_change(hass, proximity_devices,
proximity.check_proximity_state_change) proximity.check_proximity_state_change)
@ -79,7 +77,7 @@ def setup(hass, config): # pylint: disable=too-many-locals,too-many-statements
class Proximity(Entity): # pylint: disable=too-many-instance-attributes class Proximity(Entity): # pylint: disable=too-many-instance-attributes
""" Represents a Proximity. """ """Represents a Proximity."""
def __init__(self, hass, zone_friendly_name, dist_to, dir_of_travel, def __init__(self, hass, zone_friendly_name, dist_to, dir_of_travel,
nearest, ignored_zones, proximity_devices, tolerance, nearest, ignored_zones, proximity_devices, tolerance,
proximity_zone): proximity_zone):
@ -101,17 +99,17 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
@property @property
def state(self): def state(self):
""" Returns the state. """ """Return the state."""
return self.dist_to return self.dist_to
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
""" Unit of measurement of this entity. """ """Return the unit of measurement of this entity."""
return "km" return "km"
@property @property
def state_attributes(self): def state_attributes(self):
""" Returns the state attributes. """ """Return the state attributes."""
return { return {
ATTR_DIR_OF_TRAVEL: self.dir_of_travel, ATTR_DIR_OF_TRAVEL: self.dir_of_travel,
ATTR_NEAREST: self.nearest, ATTR_NEAREST: self.nearest,
@ -119,7 +117,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
def check_proximity_state_change(self, entity, old_state, new_state): def check_proximity_state_change(self, entity, old_state, new_state):
# pylint: disable=too-many-branches,too-many-statements,too-many-locals # pylint: disable=too-many-branches,too-many-statements,too-many-locals
""" Function to perform the proximity checking. """ """Function to perform the proximity checking."""
entity_name = new_state.name entity_name = new_state.name
devices_to_calculate = False devices_to_calculate = False
devices_in_zone = '' devices_in_zone = ''
@ -128,21 +126,21 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
proximity_latitude = zone_state.attributes.get('latitude') proximity_latitude = zone_state.attributes.get('latitude')
proximity_longitude = zone_state.attributes.get('longitude') proximity_longitude = zone_state.attributes.get('longitude')
# Check for devices in the monitored zone # Check for devices in the monitored zone.
for device in self.proximity_devices: for device in self.proximity_devices:
device_state = self.hass.states.get(device) device_state = self.hass.states.get(device)
if device_state.state not in self.ignored_zones: if device_state.state not in self.ignored_zones:
devices_to_calculate = True devices_to_calculate = True
# Check the location of all devices # Check the location of all devices.
if (device_state.state).lower() == (self.friendly_name).lower(): if (device_state.state).lower() == (self.friendly_name).lower():
device_friendly = device_state.name device_friendly = device_state.name
if devices_in_zone != '': if devices_in_zone != '':
devices_in_zone = devices_in_zone + ', ' devices_in_zone = devices_in_zone + ', '
devices_in_zone = devices_in_zone + device_friendly devices_in_zone = devices_in_zone + device_friendly
# No-one to track so reset the entity # No-one to track so reset the entity.
if not devices_to_calculate: if not devices_to_calculate:
self.dist_to = 'not set' self.dist_to = 'not set'
self.dir_of_travel = 'not set' self.dir_of_travel = 'not set'
@ -150,7 +148,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
self.update_ha_state() self.update_ha_state()
return return
# At least one device is in the monitored zone so update the entity # At least one device is in the monitored zone so update the entity.
if devices_in_zone != '': if devices_in_zone != '':
self.dist_to = 0 self.dist_to = 0
self.dir_of_travel = 'arrived' self.dir_of_travel = 'arrived'
@ -158,32 +156,33 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
self.update_ha_state() self.update_ha_state()
return return
# We can't check proximity because latitude and longitude don't exist # We can't check proximity because latitude and longitude don't exist.
if 'latitude' not in new_state.attributes: if 'latitude' not in new_state.attributes:
return return
# Collect distances to the zone for all devices # Collect distances to the zone for all devices.
distances_to_zone = {} distances_to_zone = {}
for device in self.proximity_devices: for device in self.proximity_devices:
# Ignore devices in an ignored zone # Ignore devices in an ignored zone.
device_state = self.hass.states.get(device) device_state = self.hass.states.get(device)
if device_state.state in self.ignored_zones: if device_state.state in self.ignored_zones:
continue continue
# Ignore devices if proximity cannot be calculated # Ignore devices if proximity cannot be calculated.
if 'latitude' not in device_state.attributes: if 'latitude' not in device_state.attributes:
continue continue
# Calculate the distance to the proximity zone # Calculate the distance to the proximity zone.
dist_to_zone = distance(proximity_latitude, dist_to_zone = distance(proximity_latitude,
proximity_longitude, proximity_longitude,
device_state.attributes['latitude'], device_state.attributes['latitude'],
device_state.attributes['longitude']) device_state.attributes['longitude'])
# Add the device and distance to a dictionary # Add the device and distance to a dictionary.
distances_to_zone[device] = round(dist_to_zone / 1000, 1) distances_to_zone[device] = round(dist_to_zone / 1000, 1)
# Loop through each of the distances collected and work out the closest # Loop through each of the distances collected and work out the
# closest.
closest_device = '' closest_device = ''
dist_to_zone = 1000000 dist_to_zone = 1000000
@ -192,7 +191,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
closest_device = device closest_device = device
dist_to_zone = distances_to_zone[device] dist_to_zone = distances_to_zone[device]
# If the closest device is one of the other devices # If the closest device is one of the other devices.
if closest_device != entity: if closest_device != entity:
self.dist_to = round(distances_to_zone[closest_device]) self.dist_to = round(distances_to_zone[closest_device])
self.dir_of_travel = 'unknown' self.dir_of_travel = 'unknown'
@ -202,7 +201,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
return return
# Stop if we cannot calculate the direction of travel (i.e. we don't # Stop if we cannot calculate the direction of travel (i.e. we don't
# have a previous state and a current LAT and LONG) # have a previous state and a current LAT and LONG).
if old_state is None or 'latitude' not in old_state.attributes: if old_state is None or 'latitude' not in old_state.attributes:
self.dist_to = round(distances_to_zone[entity]) self.dist_to = round(distances_to_zone[entity])
self.dir_of_travel = 'unknown' self.dir_of_travel = 'unknown'
@ -213,7 +212,7 @@ class Proximity(Entity): # pylint: disable=too-many-instance-attributes
# Reset the variables # Reset the variables
distance_travelled = 0 distance_travelled = 0
# Calculate the distance travelled # Calculate the distance travelled.
old_distance = distance(proximity_latitude, proximity_longitude, old_distance = distance(proximity_latitude, proximity_longitude,
old_state.attributes['latitude'], old_state.attributes['latitude'],
old_state.attributes['longitude']) old_state.attributes['longitude'])

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.recorder
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component that records all events and state changes. Allows other components Component that records all events and state changes. Allows other components
to query this database. to query this database.
@ -35,14 +33,14 @@ _LOGGER = logging.getLogger(__name__)
def query(sql_query, arguments=None): def query(sql_query, arguments=None):
""" Query the database. """ """Query the database."""
_verify_instance() _verify_instance()
return _INSTANCE.query(sql_query, arguments) return _INSTANCE.query(sql_query, arguments)
def query_states(state_query, arguments=None): def query_states(state_query, arguments=None):
""" Query the database and return a list of states. """ """Query the database and return a list of states."""
return [ return [
row for row in row for row in
(row_to_state(row) for row in query(state_query, arguments)) (row_to_state(row) for row in query(state_query, arguments))
@ -50,7 +48,7 @@ def query_states(state_query, arguments=None):
def query_events(event_query, arguments=None): def query_events(event_query, arguments=None):
""" Query the database and return a list of states. """ """Query the database and return a list of states."""
return [ return [
row for row in row for row in
(row_to_event(row) for row in query(event_query, arguments)) (row_to_event(row) for row in query(event_query, arguments))
@ -58,7 +56,7 @@ def query_events(event_query, arguments=None):
def row_to_state(row): def row_to_state(row):
""" Convert a database row to a state. """ """Convert a database row to a state."""
try: try:
return State( return State(
row[1], row[2], json.loads(row[3]), row[1], row[2], json.loads(row[3]),
@ -71,7 +69,7 @@ def row_to_state(row):
def row_to_event(row): def row_to_event(row):
""" Convert a databse row to an event. """ """Convert a databse row to an event."""
try: try:
return Event(row[1], json.loads(row[2]), EventOrigin(row[3]), return Event(row[1], json.loads(row[2]), EventOrigin(row[3]),
dt_util.utc_from_timestamp(row[5])) dt_util.utc_from_timestamp(row[5]))
@ -98,7 +96,7 @@ def run_information(point_in_time=None):
def setup(hass, config): def setup(hass, config):
""" Setup the recorder. """ """Setup the recorder."""
# pylint: disable=global-statement # pylint: disable=global-statement
global _INSTANCE global _INSTANCE
@ -108,7 +106,7 @@ def setup(hass, config):
class RecorderRun(object): class RecorderRun(object):
""" Represents a recorder run. """ """Represents a recorder run."""
def __init__(self, row=None): def __init__(self, row=None):
self.end = None self.end = None
@ -160,7 +158,7 @@ class RecorderRun(object):
class Recorder(threading.Thread): class Recorder(threading.Thread):
""" Threaded recorder class """ """A threaded recorder class."""
def __init__(self, hass): def __init__(self, hass):
threading.Thread.__init__(self) threading.Thread.__init__(self)
@ -173,7 +171,7 @@ class Recorder(threading.Thread):
self.utc_offset = dt_util.now().utcoffset().total_seconds() self.utc_offset = dt_util.now().utcoffset().total_seconds()
def start_recording(event): def start_recording(event):
""" Start recording. """ """Start recording."""
self.start() self.start()
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_recording) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_recording)
@ -181,7 +179,7 @@ class Recorder(threading.Thread):
hass.bus.listen(MATCH_ALL, self.event_listener) hass.bus.listen(MATCH_ALL, self.event_listener)
def run(self): def run(self):
""" Start processing events to save. """ """Start processing events to save."""
self._setup_connection() self._setup_connection()
self._setup_run() self._setup_run()
@ -215,12 +213,12 @@ class Recorder(threading.Thread):
self.queue.put(event) self.queue.put(event)
def shutdown(self, event): def shutdown(self, event):
""" Tells the recorder to shut down. """ """Tells the recorder to shut down."""
self.queue.put(self.quit_object) self.queue.put(self.quit_object)
self.block_till_done() self.block_till_done()
def record_state(self, entity_id, state, event_id): def record_state(self, entity_id, state, event_id):
""" Save a state to the database. """ """Save a state to the database."""
now = dt_util.utcnow() now = dt_util.utcnow()
# State got deleted # State got deleted
@ -251,7 +249,7 @@ class Recorder(threading.Thread):
info) info)
def record_event(self, event): def record_event(self, event):
""" Save an event to the database. """ """Save an event to the database."""
info = ( info = (
event.event_type, json.dumps(event.data, cls=JSONEncoder), event.event_type, json.dumps(event.data, cls=JSONEncoder),
str(event.origin), dt_util.utcnow(), event.time_fired, str(event.origin), dt_util.utcnow(), event.time_fired,
@ -292,11 +290,11 @@ class Recorder(threading.Thread):
return [] return []
def block_till_done(self): def block_till_done(self):
""" Blocks till all events processed. """ """Blocks till all events processed."""
self.queue.join() self.queue.join()
def _setup_connection(self): def _setup_connection(self):
""" Ensure database is ready to fly. """ """Ensure database is ready to fly."""
db_path = self.hass.config.path(DB_FILE) db_path = self.hass.config.path(DB_FILE)
self.conn = sqlite3.connect(db_path, check_same_thread=False) self.conn = sqlite3.connect(db_path, check_same_thread=False)
self.conn.row_factory = sqlite3.Row self.conn.row_factory = sqlite3.Row
@ -305,15 +303,15 @@ class Recorder(threading.Thread):
# without the STOP event being fired. # without the STOP event being fired.
atexit.register(self._close_connection) atexit.register(self._close_connection)
# Have datetime objects be saved as integers # Have datetime objects be saved as integers.
sqlite3.register_adapter(date, _adapt_datetime) sqlite3.register_adapter(date, _adapt_datetime)
sqlite3.register_adapter(datetime, _adapt_datetime) sqlite3.register_adapter(datetime, _adapt_datetime)
# Validate we are on the correct schema or that we have to migrate # Validate we are on the correct schema or that we have to migrate.
cur = self.conn.cursor() cur = self.conn.cursor()
def save_migration(migration_id): def save_migration(migration_id):
""" Save and commit a migration to the database. """ """Save and commit a migration to the database."""
cur.execute('INSERT INTO schema_version VALUES (?, ?)', cur.execute('INSERT INTO schema_version VALUES (?, ?)',
(migration_id, dt_util.utcnow())) (migration_id, dt_util.utcnow()))
self.conn.commit() self.conn.commit()
@ -324,7 +322,7 @@ class Recorder(threading.Thread):
migration_id = cur.fetchone()[0] or 0 migration_id = cur.fetchone()[0] or 0
except sqlite3.OperationalError: except sqlite3.OperationalError:
# The table does not exist # The table does not exist.
cur.execute('CREATE TABLE schema_version (' cur.execute('CREATE TABLE schema_version ('
'migration_id integer primary key, performed integer)') 'migration_id integer primary key, performed integer)')
migration_id = 0 migration_id = 0
@ -399,7 +397,7 @@ class Recorder(threading.Thread):
save_migration(3) save_migration(3)
if migration_id < 4: if migration_id < 4:
# We had a bug where we did not save utc offset for recorder runs # We had a bug where we did not save utc offset for recorder runs.
cur.execute( cur.execute(
"""UPDATE recorder_runs SET utc_offset=? """UPDATE recorder_runs SET utc_offset=?
WHERE utc_offset IS NULL""", [self.utc_offset]) WHERE utc_offset IS NULL""", [self.utc_offset])
@ -412,15 +410,15 @@ class Recorder(threading.Thread):
save_migration(4) save_migration(4)
if migration_id < 5: if migration_id < 5:
# Add domain so that thermostat graphs look right # Add domain so that thermostat graphs look right.
try: try:
cur.execute(""" cur.execute("""
ALTER TABLE states ALTER TABLE states
ADD COLUMN domain text ADD COLUMN domain text
""") """)
except sqlite3.OperationalError: except sqlite3.OperationalError:
# We had a bug in this migration for a while on dev # We had a bug in this migration for a while on dev.
# Without this, dev-users will have to throw away their db # Without this, dev-users will have to throw away their db.
pass pass
# TravisCI has Python compiled against an old version of SQLite3 # TravisCI has Python compiled against an old version of SQLite3
@ -429,13 +427,13 @@ class Recorder(threading.Thread):
"instr", 2, "instr", 2,
lambda string, substring: string.find(substring) + 1) lambda string, substring: string.find(substring) + 1)
# populate domain with defaults # Populate domain with defaults.
cur.execute(""" cur.execute("""
UPDATE states UPDATE states
set domain=substr(entity_id, 0, instr(entity_id, '.')) set domain=substr(entity_id, 0, instr(entity_id, '.'))
""") """)
# add indexes we are going to use a lot on selects # Add indexes we are going to use a lot on selects.
cur.execute(""" cur.execute("""
CREATE INDEX states__state_changes ON CREATE INDEX states__state_changes ON
states (last_changed, last_updated, entity_id)""") states (last_changed, last_updated, entity_id)""")
@ -445,13 +443,13 @@ class Recorder(threading.Thread):
save_migration(5) save_migration(5)
def _close_connection(self): def _close_connection(self):
""" Close connection to the database. """ """Close connection to the database."""
_LOGGER.info("Closing database") _LOGGER.info("Closing database")
atexit.unregister(self._close_connection) atexit.unregister(self._close_connection)
self.conn.close() self.conn.close()
def _setup_run(self): def _setup_run(self):
""" Log the start of the current run. """ """Log the start of the current run."""
if self.query("""UPDATE recorder_runs SET end=?, closed_incorrect=1 if self.query("""UPDATE recorder_runs SET end=?, closed_incorrect=1
WHERE end IS NULL""", (self.recording_start, ), WHERE end IS NULL""", (self.recording_start, ),
return_value=RETURN_ROWCOUNT): return_value=RETURN_ROWCOUNT):
@ -464,18 +462,18 @@ class Recorder(threading.Thread):
(self.recording_start, dt_util.utcnow(), self.utc_offset)) (self.recording_start, dt_util.utcnow(), self.utc_offset))
def _close_run(self): def _close_run(self):
""" Save end time for current run. """ """Save end time for current run."""
self.query( self.query(
"UPDATE recorder_runs SET end=? WHERE start=?", "UPDATE recorder_runs SET end=? WHERE start=?",
(dt_util.utcnow(), self.recording_start)) (dt_util.utcnow(), self.recording_start))
def _adapt_datetime(datetimestamp): def _adapt_datetime(datetimestamp):
""" Turn a datetime into an integer for in the DB. """ """Turn a datetime into an integer for in the DB."""
return dt_util.as_utc(datetimestamp.replace(microsecond=0)).timestamp() return dt_util.as_utc(datetimestamp.replace(microsecond=0)).timestamp()
def _verify_instance(): def _verify_instance():
""" Throws error if recorder not initialized. """ """Throws error if recorder not initialized."""
if _INSTANCE is None: if _INSTANCE is None:
raise RuntimeError("Recorder not initialized.") raise RuntimeError("Recorder not initialized.")

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.rfxtrx Support for RFXtrx components.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides support for RFXtrx 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/rfxtrx/ https://home-assistant.io/components/rfxtrx/
@ -33,11 +31,10 @@ RFXOBJECT = None
def setup(hass, config): def setup(hass, config):
""" Setup the RFXtrx component. """ """Setup the RFXtrx component."""
# Declare the Handle event # Declare the Handle event
def handle_receive(event): def handle_receive(event):
""" Callback all subscribers for RFXtrx gateway. """ """Callback all subscribers for RFXtrx gateway."""
# Log RFXCOM event # Log RFXCOM event
if not event.device.id_string: if not event.device.id_string:
return return
@ -47,14 +44,14 @@ def setup(hass, config):
_LOGGER.info("Receive RFXCOM event from %s => %s", _LOGGER.info("Receive RFXCOM event from %s => %s",
event.device, entity_name) event.device, entity_name)
# Callback to HA registered components # Callback to HA registered components.
for subscriber in RECEIVED_EVT_SUBSCRIBERS: for subscriber in RECEIVED_EVT_SUBSCRIBERS:
subscriber(event) subscriber(event)
# Try to load the RFXtrx module # Try to load the RFXtrx module.
import RFXtrx as rfxtrxmod import RFXtrx as rfxtrxmod
# Init the rfxtrx module # Init the rfxtrx module.
global RFXOBJECT global RFXOBJECT
if ATTR_DEVICE not in config[DOMAIN]: if ATTR_DEVICE not in config[DOMAIN]:
@ -79,7 +76,7 @@ def setup(hass, config):
def get_rfx_object(packetid): def get_rfx_object(packetid):
""" Return the RFXObject with the packetid. """ """Return the RFXObject with the packetid."""
import RFXtrx as rfxtrxmod import RFXtrx as rfxtrxmod
binarypacket = bytearray.fromhex(packetid) binarypacket = bytearray.fromhex(packetid)

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.rpi_gpio Support for controlling GPIO pins of a Raspberry Pi.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Allows to control the GPIO pins of a Raspberry Pi.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/rpi_gpio/ https://home-assistant.io/components/rpi_gpio/
@ -19,15 +17,15 @@ _LOGGER = logging.getLogger(__name__)
# pylint: disable=no-member # pylint: disable=no-member
def setup(hass, config): def setup(hass, config):
""" Sets up the Raspberry PI GPIO component. """ """Setup the Raspberry PI GPIO component."""
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
def cleanup_gpio(event): def cleanup_gpio(event):
""" Stuff to do before stop home assistant. """ """Stuff to do before stopping."""
GPIO.cleanup() GPIO.cleanup()
def prepare_gpio(event): def prepare_gpio(event):
""" Stuff to do when home assistant starts. """ """Stuff to do when home assistant starts."""
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, cleanup_gpio) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, cleanup_gpio)
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, prepare_gpio) hass.bus.listen_once(EVENT_HOMEASSISTANT_START, prepare_gpio)
@ -36,32 +34,32 @@ def setup(hass, config):
def setup_output(port): def setup_output(port):
""" Setup a GPIO as output. """ """Setup a GPIO as output."""
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
GPIO.setup(port, GPIO.OUT) GPIO.setup(port, GPIO.OUT)
def setup_input(port, pull_mode): def setup_input(port, pull_mode):
""" Setup a GPIO as input. """ """Setup a GPIO as input."""
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
GPIO.setup(port, GPIO.IN, GPIO.setup(port, GPIO.IN,
GPIO.PUD_DOWN if pull_mode == 'DOWN' else GPIO.PUD_UP) GPIO.PUD_DOWN if pull_mode == 'DOWN' else GPIO.PUD_UP)
def write_output(port, value): def write_output(port, value):
""" Write a value to a GPIO. """ """Write a value to a GPIO."""
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
GPIO.output(port, value) GPIO.output(port, value)
def read_input(port): def read_input(port):
""" Read a value from a GPIO. """ """Read a value from a GPIO."""
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
return GPIO.input(port) return GPIO.input(port)
def edge_detect(port, event_callback, bounce): def edge_detect(port, event_callback, bounce):
""" Adds detection for RISING and FALLING events. """ """Adds detection for RISING and FALLING events."""
import RPi.GPIO as GPIO import RPi.GPIO as GPIO
GPIO.add_event_detect( GPIO.add_event_detect(
port, port,

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.script
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Scripts are a sequence of actions that can be triggered manually Scripts are a sequence of actions that can be triggered manually
by the user or automatically based upon automation events, etc. by the user or automatically based upon automation events, etc.
@ -45,30 +43,29 @@ _LOGGER = logging.getLogger(__name__)
def is_on(hass, entity_id): def is_on(hass, entity_id):
""" Returns if the switch is on based on the statemachine. """ """Returns if the switch is on based on the statemachine."""
return hass.states.is_state(entity_id, STATE_ON) return hass.states.is_state(entity_id, STATE_ON)
def turn_on(hass, entity_id): def turn_on(hass, entity_id):
""" Turn script on. """ """Turn script on."""
_, object_id = split_entity_id(entity_id) _, object_id = split_entity_id(entity_id)
hass.services.call(DOMAIN, object_id) hass.services.call(DOMAIN, object_id)
def turn_off(hass, entity_id): def turn_off(hass, entity_id):
""" Turn script on. """ """Turn script on."""
hass.services.call(DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id}) hass.services.call(DOMAIN, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id})
def toggle(hass, entity_id): def toggle(hass, entity_id):
""" Toggles script. """ """Toggles script."""
hass.services.call(DOMAIN, SERVICE_TOGGLE, {ATTR_ENTITY_ID: entity_id}) hass.services.call(DOMAIN, SERVICE_TOGGLE, {ATTR_ENTITY_ID: entity_id})
def setup(hass, config): def setup(hass, config):
""" Load the scripts from the configuration. """ """Load the scripts from the configuration."""
component = EntityComponent(_LOGGER, DOMAIN, hass) component = EntityComponent(_LOGGER, DOMAIN, hass)
def service_handler(service): def service_handler(service):
@ -97,19 +94,19 @@ def setup(hass, config):
hass.services.register(DOMAIN, object_id, service_handler) hass.services.register(DOMAIN, object_id, service_handler)
def turn_on_service(service): def turn_on_service(service):
""" Calls a service to turn script on. """ """Calls a service to turn script on."""
# We could turn on script directly here, but we only want to offer # We could turn on script directly here, but we only want to offer
# one way to do it. Otherwise no easy way to call invocations. # one way to do it. Otherwise no easy way to call invocations.
for script in component.extract_from_service(service): for script in component.extract_from_service(service):
turn_on(hass, script.entity_id) turn_on(hass, script.entity_id)
def turn_off_service(service): def turn_off_service(service):
""" Cancels a script. """ """Cancels a script."""
for script in component.extract_from_service(service): for script in component.extract_from_service(service):
script.turn_off() script.turn_off()
def toggle_service(service): def toggle_service(service):
""" Toggles a script. """ """Toggles a script."""
for script in component.extract_from_service(service): for script in component.extract_from_service(service):
script.toggle() script.toggle()
@ -121,7 +118,7 @@ def setup(hass, config):
class Script(ToggleEntity): class Script(ToggleEntity):
""" Represents a script. """ """Represents a script."""
# pylint: disable=too-many-instance-attributes # pylint: disable=too-many-instance-attributes
def __init__(self, object_id, name, sequence): def __init__(self, object_id, name, sequence):
self.entity_id = ENTITY_ID_FORMAT.format(object_id) self.entity_id = ENTITY_ID_FORMAT.format(object_id)
@ -136,16 +133,17 @@ class Script(ToggleEntity):
@property @property
def should_poll(self): def should_poll(self):
"""No polling needed."""
return False return False
@property @property
def name(self): def name(self):
""" Returns the name of the entity. """ """Return the name of the entity."""
return self._name return self._name
@property @property
def state_attributes(self): def state_attributes(self):
""" Returns the state attributes. """ """Return the state attributes."""
attrs = {} attrs = {}
if self._can_cancel: if self._can_cancel:
attrs[ATTR_CAN_CANCEL] = self._can_cancel attrs[ATTR_CAN_CANCEL] = self._can_cancel
@ -155,11 +153,11 @@ class Script(ToggleEntity):
@property @property
def is_on(self): def is_on(self):
""" True if entity is on. """ """True if entity is on."""
return self._cur != -1 return self._cur != -1
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
""" Turn the entity on. """ """Turn the entity on."""
_LOGGER.info("Executing script %s", self._name) _LOGGER.info("Executing script %s", self._name)
with self._lock: with self._lock:
if self._cur == -1: if self._cur == -1:
@ -197,7 +195,7 @@ class Script(ToggleEntity):
self.update_ha_state() self.update_ha_state()
def turn_off(self, **kwargs): def turn_off(self, **kwargs):
""" Turn script off. """ """Turn script off."""
_LOGGER.info("Cancelled script %s", self._name) _LOGGER.info("Cancelled script %s", self._name)
with self._lock: with self._lock:
if self._cur == -1: if self._cur == -1:
@ -208,7 +206,7 @@ class Script(ToggleEntity):
self._remove_listener() self._remove_listener()
def _call_service(self, action): def _call_service(self, action):
""" Calls the service specified in the action. """ """Calls the service specified in the action."""
# Backwards compatibility # Backwards compatibility
if CONF_SERVICE not in action and CONF_SERVICE_OLD in action: if CONF_SERVICE not in action and CONF_SERVICE_OLD in action:
action[CONF_SERVICE] = action[CONF_SERVICE_OLD] action[CONF_SERVICE] = action[CONF_SERVICE_OLD]
@ -222,14 +220,14 @@ class Script(ToggleEntity):
call_from_config(self.hass, action, True) call_from_config(self.hass, action, True)
def _fire_event(self, action): def _fire_event(self, action):
""" Fires an event. """ """Fires an event."""
self._last_action = action.get(CONF_ALIAS, action[CONF_EVENT]) self._last_action = action.get(CONF_ALIAS, action[CONF_EVENT])
_LOGGER.info("Executing script %s step %s", self._name, _LOGGER.info("Executing script %s step %s", self._name,
self._last_action) self._last_action)
self.hass.bus.fire(action[CONF_EVENT], action.get(CONF_EVENT_DATA)) self.hass.bus.fire(action[CONF_EVENT], action.get(CONF_EVENT_DATA))
def _remove_listener(self): def _remove_listener(self):
""" Remove point in time listener, if any. """ """Remove point in time listener, if any."""
if self._listener: if self._listener:
self.hass.bus.remove_listener(EVENT_TIME_CHANGED, self.hass.bus.remove_listener(EVENT_TIME_CHANGED,
self._listener) self._listener)

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.scsgate Support for SCSGate components.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides support for SCSGate 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/scsgate/ https://home-assistant.io/components/scsgate/
@ -18,8 +16,7 @@ _LOGGER = logging.getLogger(__name__)
class SCSGate: class SCSGate:
""" Class dealing with the SCSGate device via scsgate.Reactor. """ """Class dealing with the SCSGate device via scsgate.Reactor."""
def __init__(self, device, logger): def __init__(self, device, logger):
self._logger = logger self._logger = logger
self._devices = {} self._devices = {}
@ -38,7 +35,7 @@ class SCSGate:
handle_message=self.handle_message) handle_message=self.handle_message)
def handle_message(self, message): def handle_message(self, message):
""" Method called whenever a message is seen on the bus. """ """Method called whenever a message is seen on the bus."""
from scsgate.messages import StateMessage, ScenarioTriggeredMessage from scsgate.messages import StateMessage, ScenarioTriggeredMessage
self._logger.debug("Received message {}".format(message)) self._logger.debug("Received message {}".format(message))
@ -88,14 +85,14 @@ class SCSGate:
self._devices[device.scs_id] = device self._devices[device.scs_id] = device
def add_devices_to_register(self, devices): def add_devices_to_register(self, devices):
""" List of devices to be registered. """ """List of devices to be registered."""
with self._devices_to_register_lock: with self._devices_to_register_lock:
for device in devices: for device in devices:
self._devices_to_register[device.scs_id] = device self._devices_to_register[device.scs_id] = device
self._activate_next_device() self._activate_next_device()
def _activate_next_device(self): def _activate_next_device(self):
""" Starts the activation of the first device. """ """Starts the activation of the first device."""
from scsgate.tasks import GetStatusTask from scsgate.tasks import GetStatusTask
with self._devices_to_register_lock: with self._devices_to_register_lock:
@ -107,7 +104,7 @@ class SCSGate:
self._reactor.append_task(GetStatusTask(target=device.scs_id)) self._reactor.append_task(GetStatusTask(target=device.scs_id))
def is_device_registered(self, device_id): def is_device_registered(self, device_id):
""" Checks whether a device is already registered or not. """ """Checks whether a device is already registered or not."""
with self._devices_to_register_lock: with self._devices_to_register_lock:
if device_id in self._devices_to_register.keys(): if device_id in self._devices_to_register.keys():
return False return False
@ -119,20 +116,20 @@ class SCSGate:
return True return True
def start(self): def start(self):
""" Start the scsgate.Reactor. """ """Start the scsgate.Reactor."""
self._reactor.start() self._reactor.start()
def stop(self): def stop(self):
""" Stop the scsgate.Reactor. """ """Stop the scsgate.Reactor."""
self._reactor.stop() self._reactor.stop()
def append_task(self, task): def append_task(self, task):
""" Registers a new task to be executed. """ """Registers a new task to be executed."""
self._reactor.append_task(task) self._reactor.append_task(task)
def setup(hass, config): def setup(hass, config):
""" Setup the SCSGate component. """ """Setup the SCSGate component."""
device = config['scsgate']['device'] device = config['scsgate']['device']
global SCSGATE global SCSGATE

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.shell_command
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Exposes regular shell commands as services. Exposes regular shell commands as services.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
@ -17,7 +15,7 @@ _LOGGER = logging.getLogger(__name__)
def setup(hass, config): def setup(hass, config):
""" Sets up the shell_command component. """ """Sets up the shell_command component."""
conf = config.get(DOMAIN) conf = config.get(DOMAIN)
if not isinstance(conf, dict): if not isinstance(conf, dict):
@ -31,7 +29,7 @@ def setup(hass, config):
return False return False
def service_handler(call): def service_handler(call):
""" Execute a shell command service. """ """Execute a shell command service."""
try: try:
subprocess.call(conf[call.service], shell=True, subprocess.call(conf[call.service], shell=True,
stdout=subprocess.DEVNULL, stdout=subprocess.DEVNULL,

View File

@ -51,7 +51,6 @@ def setup(hass, config):
def statsd_event_listener(event): def statsd_event_listener(event):
"""Listen for new messages on the bus and sends them to StatsD.""" """Listen for new messages on the bus and sends them to StatsD."""
state = event.data.get('new_state') state = event.data.get('new_state')
if state is None: if state is None:

View File

@ -1,6 +1,4 @@
""" """
homeassistant.components.sun
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Provides functionality to keep track of the sun. Provides functionality to keep track of the sun.
For more details about this component, please refer to the documentation at For more details about this component, please refer to the documentation at

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.tellduslive Support for Telldus Live.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Tellduslive Component.
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/tellduslive/ https://home-assistant.io/components/tellduslive/
@ -41,10 +39,10 @@ NETWORK = None
@Throttle(MIN_TIME_BETWEEN_SWITCH_UPDATES) @Throttle(MIN_TIME_BETWEEN_SWITCH_UPDATES)
def request_switches(): def request_switches():
""" make request to online service """ """Make request to online service."""
_LOGGER.debug("Updating switches from Telldus Live") _LOGGER.debug("Updating switches from Telldus Live")
switches = NETWORK.request("devices/list")["device"] switches = NETWORK.request("devices/list")["device"]
# filter out any group of switches # Filter out any group of switches.
switches = {switch["id"]: switch for switch in switches switches = {switch["id"]: switch for switch in switches
if switch["type"] == "device"} if switch["type"] == "device"}
return switches return switches
@ -52,10 +50,10 @@ def request_switches():
@Throttle(MIN_TIME_BETWEEN_SENSOR_UPDATES) @Throttle(MIN_TIME_BETWEEN_SENSOR_UPDATES)
def request_sensors(): def request_sensors():
""" make request to online service """ """Make request to online service."""
_LOGGER.debug("Updating sensors from Telldus Live") _LOGGER.debug("Updating sensors from Telldus Live")
units = NETWORK.request("sensors/list")["sensor"] units = NETWORK.request("sensors/list")["sensor"]
# one unit can contain many sensors # One unit can contain many sensors.
sensors = {unit["id"]+sensor["name"]: dict(unit, data=sensor) sensors = {unit["id"]+sensor["name"]: dict(unit, data=sensor)
for unit in units for unit in units
for sensor in unit["data"]} for sensor in unit["data"]}
@ -63,8 +61,7 @@ def request_sensors():
class TelldusLiveData(object): class TelldusLiveData(object):
""" Gets the latest data and update the states. """ """Gets the latest data and update the states."""
def __init__(self, hass, config): def __init__(self, hass, config):
public_key = config[DOMAIN].get(CONF_PUBLIC_KEY) public_key = config[DOMAIN].get(CONF_PUBLIC_KEY)
private_key = config[DOMAIN].get(CONF_PRIVATE_KEY) private_key = config[DOMAIN].get(CONF_PRIVATE_KEY)
@ -85,18 +82,17 @@ class TelldusLiveData(object):
access_secret=token_secret) access_secret=token_secret)
def validate_session(self): def validate_session(self):
""" Make a dummy request to see if the session is valid """ """Make a dummy request to see if the session is valid."""
response = self.request("user/profile") response = self.request("user/profile")
return response and 'email' in response return response and 'email' in response
def discover(self): def discover(self):
""" Update states, will trigger discover """ """Update states, will trigger discover."""
self.update_sensors() self.update_sensors()
self.update_switches() self.update_switches()
def _discover(self, found_devices, component_name): def _discover(self, found_devices, component_name):
""" Send discovery event if component not yet discovered """ """Send discovery event if component not yet discovered."""
if not len(found_devices): if not len(found_devices):
return return
@ -115,7 +111,7 @@ class TelldusLiveData(object):
ATTR_DISCOVERED: found_devices}) ATTR_DISCOVERED: found_devices})
def request(self, what, **params): def request(self, what, **params):
""" Sends a request to the tellstick live API """ """Sends a request to the Tellstick Live API."""
from tellive.live import const from tellive.live import const
supported_methods = const.TELLSTICK_TURNON \ supported_methods = const.TELLSTICK_TURNON \
@ -149,12 +145,8 @@ class TelldusLiveData(object):
_LOGGER.error("failed to make request to Tellduslive servers") _LOGGER.error("failed to make request to Tellduslive servers")
return None return None
def update_devices(self, def update_devices(self, local_devices, remote_devices, component_name):
local_devices, """Update local device list and discover new devices."""
remote_devices,
component_name):
""" update local device list and discover new devices """
if remote_devices is None: if remote_devices is None:
return local_devices return local_devices
@ -172,48 +164,46 @@ class TelldusLiveData(object):
return remote_devices return remote_devices
def update_sensors(self): def update_sensors(self):
""" update local list of sensors """ """Update local list of sensors."""
self._sensors = self.update_devices(self._sensors, self._sensors = self.update_devices(self._sensors,
request_sensors(), request_sensors(),
"sensor") "sensor")
def update_switches(self): def update_switches(self):
""" update local list of switches """ """Update local list of switches."""
self._switches = self.update_devices(self._switches, self._switches = self.update_devices(self._switches,
request_switches(), request_switches(),
"switch") "switch")
def _check_request(self, what, **params): def _check_request(self, what, **params):
""" Make request, check result if successful """ """Make request, check result if successful."""
response = self.request(what, **params) response = self.request(what, **params)
return response and response.get('status') == 'success' return response and response.get('status') == 'success'
def get_switch(self, switch_id): def get_switch(self, switch_id):
""" return switch representation """ """Return the switch representation."""
return self._switches[switch_id] return self._switches[switch_id]
def get_sensor(self, sensor_id): def get_sensor(self, sensor_id):
""" return sensor representation """ """Return the sensor representation."""
return self._sensors[sensor_id] return self._sensors[sensor_id]
def turn_switch_on(self, switch_id): def turn_switch_on(self, switch_id):
""" Turn switch off. """ """Turn switch off."""
if self._check_request("device/turnOn", id=switch_id): if self._check_request("device/turnOn", id=switch_id):
from tellive.live import const from tellive.live import const
self.get_switch(switch_id)["state"] = const.TELLSTICK_TURNON self.get_switch(switch_id)["state"] = const.TELLSTICK_TURNON
def turn_switch_off(self, switch_id): def turn_switch_off(self, switch_id):
""" Turn switch on. """ """Turn switch on."""
if self._check_request("device/turnOff", id=switch_id): if self._check_request("device/turnOff", id=switch_id):
from tellive.live import const from tellive.live import const
self.get_switch(switch_id)["state"] = const.TELLSTICK_TURNOFF self.get_switch(switch_id)["state"] = const.TELLSTICK_TURNOFF
def setup(hass, config): def setup(hass, config):
""" Setup the Telldus Live component. """ """Setup the Telldus Live component."""
# FIXME: aquire app key and provide authentication using username+password
# fixme: aquire app key and provide authentication
# using username + password
if not validate_config(config, if not validate_config(config,
{DOMAIN: [CONF_PUBLIC_KEY, {DOMAIN: [CONF_PUBLIC_KEY,
CONF_PRIVATE_KEY, CONF_PRIVATE_KEY,

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.updater Support to check for available updates.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Component that checks for available updates.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
at https://home-assistant.io/components/updater/ at https://home-assistant.io/components/updater/
@ -21,10 +19,9 @@ ENTITY_ID = 'updater.updater'
def setup(hass, config): def setup(hass, config):
""" Setup the updater component. """ """Setup the updater component."""
def check_newest_version(_=None): def check_newest_version(_=None):
""" Check if a new version is available and report if one is. """ """Check if a new version is available and report if one is."""
newest = get_newest_version() newest = get_newest_version()
if newest != CURRENT_VERSION and newest is not None: if newest != CURRENT_VERSION and newest is not None:
@ -40,7 +37,7 @@ def setup(hass, config):
def get_newest_version(): def get_newest_version():
""" Get the newest Home Assistant version from PyPI. """ """Get the newest Home Assistant version from PyPI."""
try: try:
req = requests.get(PYPI_URL) req = requests.get(PYPI_URL)

View File

@ -1,7 +1,5 @@
""" """
components.verisure Support for Verisure components.
~~~~~~~~~~~~~~~~~~~
Provides support for verisure 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/verisure/ https://home-assistant.io/components/verisure/
@ -33,8 +31,7 @@ HUB = None
def setup(hass, config): def setup(hass, config):
""" Setup the Verisure component. """ """Setup the Verisure component."""
if not validate_config(config, if not validate_config(config,
{DOMAIN: [CONF_USERNAME, CONF_PASSWORD]}, {DOMAIN: [CONF_USERNAME, CONF_PASSWORD]},
_LOGGER): _LOGGER):
@ -46,7 +43,6 @@ def setup(hass, config):
if not HUB.login(): if not HUB.login():
return False return False
# Load components for the devices in the ISY controller that we support
for comp_name, discovery in ((('sensor', DISCOVER_SENSORS), for comp_name, discovery in ((('sensor', DISCOVER_SENSORS),
('switch', DISCOVER_SWITCHES), ('switch', DISCOVER_SWITCHES),
('alarm_control_panel', DISCOVER_ALARMS), ('alarm_control_panel', DISCOVER_ALARMS),
@ -62,8 +58,7 @@ def setup(hass, config):
# pylint: disable=too-many-instance-attributes # pylint: disable=too-many-instance-attributes
class VerisureHub(object): class VerisureHub(object):
""" Verisure wrapper class """ """A Verisure wrapper class."""
def __init__(self, domain_config, verisure): def __init__(self, domain_config, verisure):
self.alarm_status = {} self.alarm_status = {}
self.lock_status = {} self.lock_status = {}
@ -88,7 +83,7 @@ class VerisureHub(object):
domain_config[CONF_PASSWORD]) domain_config[CONF_PASSWORD])
def login(self): def login(self):
""" Login to MyPages """ """Login to Verisure MyPages."""
try: try:
self.my_pages.login() self.my_pages.login()
except self._verisure.Error as ex: except self._verisure.Error as ex:
@ -98,41 +93,41 @@ class VerisureHub(object):
@Throttle(timedelta(seconds=1)) @Throttle(timedelta(seconds=1))
def update_alarms(self): def update_alarms(self):
""" Updates the status of the alarm. """ """Updates the status of the alarm."""
self.update_component( self.update_component(
self.my_pages.alarm.get, self.my_pages.alarm.get,
self.alarm_status) self.alarm_status)
@Throttle(timedelta(seconds=1)) @Throttle(timedelta(seconds=1))
def update_locks(self): def update_locks(self):
""" Updates the status of the alarm. """ """Updates the status of the locks."""
self.update_component( self.update_component(
self.my_pages.lock.get, self.my_pages.lock.get,
self.lock_status) self.lock_status)
@Throttle(timedelta(seconds=60)) @Throttle(timedelta(seconds=60))
def update_climate(self): def update_climate(self):
""" Updates the status of the smartplugs. """ """Updates the status of the climate units."""
self.update_component( self.update_component(
self.my_pages.climate.get, self.my_pages.climate.get,
self.climate_status) self.climate_status)
@Throttle(timedelta(seconds=60)) @Throttle(timedelta(seconds=60))
def update_mousedetection(self): def update_mousedetection(self):
""" Updates the status of the smartplugs. """ """Updates the status of the mouse detectors."""
self.update_component( self.update_component(
self.my_pages.mousedetection.get, self.my_pages.mousedetection.get,
self.mouse_status) self.mouse_status)
@Throttle(timedelta(seconds=1)) @Throttle(timedelta(seconds=1))
def update_smartplugs(self): def update_smartplugs(self):
""" Updates the status of the smartplugs. """ """Updates the status of the smartplugs."""
self.update_component( self.update_component(
self.my_pages.smartplug.get, self.my_pages.smartplug.get,
self.smartplug_status) self.smartplug_status)
def update_component(self, get_function, status): def update_component(self, get_function, status):
""" Updates the status of verisure components. """ """Updates the status of Verisure components."""
if self._wrong_password_given: if self._wrong_password_given:
_LOGGER.error('Wrong password for Verisure, update config') _LOGGER.error('Wrong password for Verisure, update config')
return return
@ -147,7 +142,7 @@ class VerisureHub(object):
self.reconnect() self.reconnect()
def reconnect(self): def reconnect(self):
""" Reconnect to verisure mypages. """ """Reconnect to Verisure MyPages."""
if self._reconnect_timeout > time.time(): if self._reconnect_timeout > time.time():
return return
if not self._lock.acquire(blocking=False): if not self._lock.acquire(blocking=False):

View File

@ -1,8 +1,5 @@
# -*- coding: utf-8 -*-
""" """
homeassistant.components.weblink Support for links to external web pages.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Adds links to external webpages.
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/weblink/ https://home-assistant.io/components/weblink/
@ -23,8 +20,7 @@ _LOGGER = logging.getLogger(__name__)
def setup(hass, config): def setup(hass, config):
""" Setup weblink component. """ """Setup weblink component."""
links = config.get(DOMAIN) links = config.get(DOMAIN)
for link in links.get('entities'): for link in links.get('entities'):
@ -39,8 +35,7 @@ def setup(hass, config):
class Link(Entity): class Link(Entity):
""" Represent a link. """ """Represent a link."""
def __init__(self, hass, name, url, icon): def __init__(self, hass, name, url, icon):
self.hass = hass self.hass = hass
self._name = name self._name = name
@ -51,15 +46,15 @@ class Link(Entity):
@property @property
def icon(self): def icon(self):
""" Icon to use in the frontend, if any. """ """Return the icon to use in the frontend, if any."""
return self._icon return self._icon
@property @property
def name(self): def name(self):
""" Returns the name of the URL. """ """Return the name of the URL."""
return self._name return self._name
@property @property
def state(self): def state(self):
""" Returns the URL. """ """Return the URL."""
return self._url return self._url

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.wemo Support for WeMo device discovery.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
WeMo device discovery.
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/wemo/ https://home-assistant.io/components/wemo/
@ -18,7 +16,7 @@ DISCOVER_LIGHTS = 'wemo.light'
DISCOVER_MOTION = 'wemo.motion' DISCOVER_MOTION = 'wemo.motion'
DISCOVER_SWITCHES = 'wemo.switch' DISCOVER_SWITCHES = 'wemo.switch'
# mapping from Wemo model_name to service # Mapping from Wemo model_name to service.
WEMO_MODEL_DISPATCH = { WEMO_MODEL_DISPATCH = {
'Bridge': DISCOVER_LIGHTS, 'Bridge': DISCOVER_LIGHTS,
'Insight': DISCOVER_SWITCHES, 'Insight': DISCOVER_SWITCHES,
@ -41,7 +39,7 @@ _LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument, too-many-function-args # pylint: disable=unused-argument, too-many-function-args
def setup(hass, config): def setup(hass, config):
"""Common set up for WeMo devices.""" """Common setup for WeMo devices."""
import pywemo import pywemo
global SUBSCRIPTION_REGISTRY global SUBSCRIPTION_REGISTRY
@ -77,7 +75,7 @@ def setup(hass, config):
_LOGGER.info("Scanning for WeMo devices.") _LOGGER.info("Scanning for WeMo devices.")
devices = [(device.host, device) for device in pywemo.discover_devices()] devices = [(device.host, device) for device in pywemo.discover_devices()]
# Add static devices from the config file # Add static devices from the config file.
devices.extend((address, None) devices.extend((address, None)
for address in config.get(DOMAIN, {}).get('static', [])) for address in config.get(DOMAIN, {}).get('static', []))

View File

@ -1,7 +1,6 @@
""" """
homeassistant.components.wink Support for Wink hubs.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Connects to a Wink hub and loads relevant components to control its devices.
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/wink/ https://home-assistant.io/components/wink/
""" """
@ -27,7 +26,7 @@ DISCOVER_GARAGE_DOORS = "wink.garage_doors"
def setup(hass, config): def setup(hass, config):
""" Sets up the Wink component. """ """Setup the Wink component."""
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
if not validate_config(config, {DOMAIN: [CONF_ACCESS_TOKEN]}, logger): if not validate_config(config, {DOMAIN: [CONF_ACCESS_TOKEN]}, logger):
@ -64,34 +63,33 @@ def setup(hass, config):
class WinkToggleDevice(ToggleEntity): class WinkToggleDevice(ToggleEntity):
""" Represents a Wink toogle (switch) device. """ """Represents a Wink toggle (switch) device."""
def __init__(self, wink): def __init__(self, wink):
self.wink = wink self.wink = wink
@property @property
def unique_id(self): def unique_id(self):
""" Returns the id of this Wink switch. """ """Return the ID of this Wink device."""
return "{}.{}".format(self.__class__, self.wink.device_id()) return "{}.{}".format(self.__class__, self.wink.device_id())
@property @property
def name(self): def name(self):
""" Returns the name of the light if any. """ """Return the name of the device."""
return self.wink.name() return self.wink.name()
@property @property
def is_on(self): def is_on(self):
""" True if light is on. """ """True if decive is on."""
return self.wink.state() return self.wink.state()
def turn_on(self, **kwargs): def turn_on(self, **kwargs):
""" Turns the switch on. """ """Turns the device on."""
self.wink.set_state(True) self.wink.set_state(True)
def turn_off(self): def turn_off(self):
""" Turns the switch off. """ """Turns the device off."""
self.wink.set_state(False) self.wink.set_state(False)
def update(self): def update(self):
""" Update state of the light. """ """Update state of the device."""
self.wink.update_state() self.wink.update_state()

View File

@ -1,8 +1,5 @@
""" """
homeassistant.components.zigbee Support for ZigBee devices.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sets up and provides access to a ZigBee device and contains generic entity
classes.
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/zigbee/ https://home-assistant.io/components/zigbee/

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.zone Support for the definition of zones.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Allows defintion of zones in Home Assistant.
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/zone/ https://home-assistant.io/components/zone/
@ -32,7 +30,7 @@ ICON_HOME = 'mdi:home'
def active_zone(hass, latitude, longitude, radius=0): def active_zone(hass, latitude, longitude, radius=0):
""" Find the active zone for given latitude, longitude. """ """Find the active zone for given latitude, longitude."""
# Sort entity IDs so that we are deterministic if equal distance to 2 zones # Sort entity IDs so that we are deterministic if equal distance to 2 zones
zones = (hass.states.get(entity_id) for entity_id zones = (hass.states.get(entity_id) for entity_id
in sorted(hass.states.entity_ids(DOMAIN))) in sorted(hass.states.entity_ids(DOMAIN)))
@ -62,7 +60,7 @@ def active_zone(hass, latitude, longitude, radius=0):
def in_zone(zone, latitude, longitude, radius=0): def in_zone(zone, latitude, longitude, radius=0):
""" Test if given latitude, longitude is in given zone. """ """Test if given latitude, longitude is in given zone."""
zone_dist = distance( zone_dist = distance(
latitude, longitude, latitude, longitude,
zone.attributes[ATTR_LATITUDE], zone.attributes[ATTR_LONGITUDE]) zone.attributes[ATTR_LATITUDE], zone.attributes[ATTR_LONGITUDE])
@ -71,7 +69,7 @@ def in_zone(zone, latitude, longitude, radius=0):
def setup(hass, config): def setup(hass, config):
""" Setup zone. """ """Setup zone."""
entities = set() entities = set()
for key in extract_domain_configs(config, DOMAIN): for key in extract_domain_configs(config, DOMAIN):
@ -108,7 +106,7 @@ def setup(hass, config):
class Zone(Entity): class Zone(Entity):
""" Represents a Zone in Home Assistant. """ """Represents a Zone."""
# pylint: disable=too-many-arguments, too-many-instance-attributes # pylint: disable=too-many-arguments, too-many-instance-attributes
def __init__(self, hass, name, latitude, longitude, radius, icon, passive): def __init__(self, hass, name, latitude, longitude, radius, icon, passive):
self.hass = hass self.hass = hass
@ -121,19 +119,22 @@ class Zone(Entity):
@property @property
def name(self): def name(self):
""" Return the name of the zone."""
return self._name return self._name
@property @property
def state(self): def state(self):
""" The state property really does nothing for a zone. """ """Return the state property really does nothing for a zone."""
return STATE return STATE
@property @property
def icon(self): def icon(self):
"""Return the icon if any."""
return self._icon return self._icon
@property @property
def state_attributes(self): def state_attributes(self):
""" Return the state attributes of the zone."""
data = { data = {
ATTR_HIDDEN: True, ATTR_HIDDEN: True,
ATTR_LATITUDE: self._latitude, ATTR_LATITUDE: self._latitude,

View File

@ -1,7 +1,5 @@
""" """
homeassistant.components.zwave Support for Z-Wave.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Connects Home Assistant to a Z-Wave network.
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/zwave/ https://home-assistant.io/components/zwave/
@ -56,8 +54,8 @@ TYPE_BOOL = "Bool"
TYPE_DECIMAL = "Decimal" TYPE_DECIMAL = "Decimal"
# list of tuple (DOMAIN, discovered service, supported command # List of tuple (DOMAIN, discovered service, supported command classes,
# classes, value type) # value type).
DISCOVERY_COMPONENTS = [ DISCOVERY_COMPONENTS = [
('sensor', ('sensor',
DISCOVER_SENSORS, DISCOVER_SENSORS,
@ -93,28 +91,28 @@ NETWORK = None
def _obj_to_dict(obj): def _obj_to_dict(obj):
""" Converts an obj into a hash for debug. """ """Converts an obj into a hash for debug."""
return {key: getattr(obj, key) for key return {key: getattr(obj, key) for key
in dir(obj) in dir(obj)
if key[0] != '_' and not hasattr(getattr(obj, key), '__call__')} if key[0] != '_' and not hasattr(getattr(obj, key), '__call__')}
def _node_name(node): def _node_name(node):
""" Returns the name of the node. """ """Returns the name of the node."""
return node.name or "{} {}".format( return node.name or "{} {}".format(
node.manufacturer_name, node.product_name) node.manufacturer_name, node.product_name)
def _value_name(value): def _value_name(value):
""" Returns the name of the value. """ """Returns the name of the value."""
return "{} {}".format(_node_name(value.node), value.label) return "{} {}".format(_node_name(value.node), value.label)
def _object_id(value): def _object_id(value):
""" Returns the object_id of the device value. """Returns the object_id of the device value.
The object_id contains node_id and value instance id The object_id contains node_id and value instance id
to not collide with other entity_ids""" to not collide with other entity_ids.
"""
object_id = "{}_{}".format(slugify(_value_name(value)), object_id = "{}_{}".format(slugify(_value_name(value)),
value.node.node_id) value.node.node_id)
@ -126,7 +124,7 @@ def _object_id(value):
def nice_print_node(node): def nice_print_node(node):
""" Prints a nice formatted node to the output (debug method). """ """Prints a nice formatted node to the output (debug method)."""
node_dict = _obj_to_dict(node) node_dict = _obj_to_dict(node)
node_dict['values'] = {value_id: _obj_to_dict(value) node_dict['values'] = {value_id: _obj_to_dict(value)
for value_id, value in node.values.items()} for value_id, value in node.values.items()}
@ -138,8 +136,7 @@ def nice_print_node(node):
def get_config_value(node, value_index): def get_config_value(node, value_index):
""" Returns the current config value for a specific index. """ """Returns the current configuration value for a specific index."""
try: try:
for value in node.values.values(): for value in node.values.values():
# 112 == config command class # 112 == config command class
@ -193,8 +190,7 @@ def setup(hass, config):
dispatcher.connect(log_all, weak=False) dispatcher.connect(log_all, weak=False)
def value_added(node, value): def value_added(node, value):
""" Called when a value is added to a node on the network. """ """Called when a value is added to a node on the network."""
for (component, for (component,
discovery_service, discovery_service,
command_ids, command_ids,
@ -230,7 +226,7 @@ def setup(hass, config):
}) })
def scene_activated(node, scene_id): def scene_activated(node, scene_id):
""" Called when a scene is activated on any node in the network. """ """Called when a scene is activated on any node in the network."""
name = _node_name(node) name = _node_name(node)
object_id = "{}_{}".format(slugify(name), node.node_id) object_id = "{}_{}".format(slugify(name), node.node_id)
@ -245,19 +241,19 @@ def setup(hass, config):
scene_activated, ZWaveNetwork.SIGNAL_SCENE_EVENT, weak=False) scene_activated, ZWaveNetwork.SIGNAL_SCENE_EVENT, weak=False)
def add_node(event): def add_node(event):
""" Switch into inclusion mode """ """Switch into inclusion mode."""
NETWORK.controller.begin_command_add_device() NETWORK.controller.begin_command_add_device()
def remove_node(event): def remove_node(event):
""" Switch into exclusion mode""" """Switch into exclusion mode."""
NETWORK.controller.begin_command_remove_device() NETWORK.controller.begin_command_remove_device()
def stop_zwave(event): def stop_zwave(event):
""" Stop Z-wave. """ """Stop Z-wave."""
NETWORK.stop() NETWORK.stop()
def start_zwave(event): def start_zwave(event):
""" Called when Home Assistant starts up. """ """Startup """
NETWORK.start() NETWORK.start()
polling_interval = convert( polling_interval = convert(
@ -267,7 +263,7 @@ def setup(hass, config):
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zwave) hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zwave)
# register add / remove node services for zwave sticks without # Register add / remove node services for Z-Wave sticks without
# hardware inclusion button # hardware inclusion button
hass.services.register(DOMAIN, SERVICE_ADD_NODE, add_node) hass.services.register(DOMAIN, SERVICE_ADD_NODE, add_node)
hass.services.register(DOMAIN, SERVICE_REMOVE_NODE, remove_node) hass.services.register(DOMAIN, SERVICE_REMOVE_NODE, remove_node)
@ -278,37 +274,37 @@ def setup(hass, config):
class ZWaveDeviceEntity: class ZWaveDeviceEntity:
""" Represents a ZWave node entity within Home Assistant. """ """Represents a Z-Wave node entity."""
def __init__(self, value, domain): def __init__(self, value, domain):
self._value = value self._value = value
self.entity_id = "{}.{}".format(domain, self._object_id()) self.entity_id = "{}.{}".format(domain, self._object_id())
@property @property
def should_poll(self): def should_poll(self):
""" False because we will push our own state to HA when changed. """ """No polling needed."""
return False return False
@property @property
def unique_id(self): def unique_id(self):
""" Returns a unique id. """ """Returns a unique id."""
return "ZWAVE-{}-{}".format(self._value.node.node_id, return "ZWAVE-{}-{}".format(self._value.node.node_id,
self._value.object_id) self._value.object_id)
@property @property
def name(self): def name(self):
""" Returns the name of the device. """ """Returns the name of the device."""
return _value_name(self._value) return _value_name(self._value)
def _object_id(self): def _object_id(self):
""" Returns the object_id of the device value. """
The object_id contains node_id and value instance id Returns the object_id of the device value. The object_id contains
to not collide with other entity_ids""" node_id and value instance id to not collide with other entity_ids.
"""
return _object_id(self._value) return _object_id(self._value)
@property @property
def device_state_attributes(self): def device_state_attributes(self):
""" Returns device specific state attributes. """ """Return device specific state attributes."""
attrs = { attrs = {
ATTR_NODE_ID: self._value.node.node_id, ATTR_NODE_ID: self._value.node.node_id,
} }