1
mirror of https://github.com/home-assistant/core synced 2024-09-25 00:41:32 +02:00
ha-core/homeassistant/bootstrap.py
2015-02-28 20:31:26 +01:00

167 lines
4.9 KiB
Python

"""
homeassistant.bootstrap
~~~~~~~~~~~~~~~~~~~~~~~
Provides methods to bootstrap a home assistant instance.
Each method will return a tuple (bus, statemachine).
After bootstrapping you can add your own components or
start by calling homeassistant.start_home_assistant(bus)
"""
import os
import configparser
import yaml
import io
import logging
from collections import defaultdict
import homeassistant
import homeassistant.loader as loader
import homeassistant.components as core_components
import homeassistant.components.group as group
from homeassistant.const import EVENT_COMPONENT_LOADED
_LOGGER = logging.getLogger(__name__)
ATTR_COMPONENT = "component"
def setup_component(hass, domain, config=None):
""" Setup a component for Home Assistant. """
# Check if already loaded
if domain in hass.components:
return
_ensure_loader_prepared(hass)
if config is None:
config = defaultdict(dict)
component = loader.get_component(domain)
try:
if component.setup(hass, config):
hass.components.append(component.DOMAIN)
# Assumption: if a component does not depend on groups
# it communicates with devices
if group.DOMAIN not in component.DEPENDENCIES:
hass.pool.add_worker()
hass.bus.fire(
EVENT_COMPONENT_LOADED, {ATTR_COMPONENT: component.DOMAIN})
return True
else:
_LOGGER.error("component %s failed to initialize", domain)
except Exception: # pylint: disable=broad-except
_LOGGER.exception("Error during setup of component %s", domain)
return False
# pylint: disable=too-many-branches, too-many-statements
def from_config_dict(config, hass=None):
"""
Tries to configure Home Assistant from a config dict.
Dynamically loads required components and its dependencies.
"""
if hass is None:
hass = homeassistant.HomeAssistant()
enable_logging(hass)
_ensure_loader_prepared(hass)
# Make a copy because we are mutating it.
# Convert it to defaultdict so components can always have config dict
# Convert values to dictionaries if they are None
config = defaultdict(
dict, {key: value or {} for key, value in config.items()})
# Filter out the repeating and common config section [homeassistant]
components = (key for key in config.keys()
if ' ' not in key and key != homeassistant.DOMAIN)
if not core_components.setup(hass, config):
_LOGGER.error("Home Assistant core failed to initialize. "
"Further initialization aborted.")
return hass
_LOGGER.info("Home Assistant core initialized")
# Setup the components
for domain in loader.load_order_components(components):
setup_component(hass, domain, config)
return hass
def from_config_file(config_path, hass=None):
"""
Reads the configuration file and tries to start all the required
functionality. Will add functionality to 'hass' parameter if given,
instantiates a new Home Assistant object if 'hass' is not given.
"""
if hass is None:
hass = homeassistant.HomeAssistant()
# Set config dir to directory holding config file
hass.config_dir = os.path.abspath(os.path.dirname(config_path))
config_dict = {}
# check config file type
if os.path.splitext(config_path)[1] == '.yaml':
# Read yaml
config_dict = yaml.load(io.open(config_path, 'r'))
else:
# Read config
config = configparser.ConfigParser()
config.read(config_path)
for section in config.sections():
config_dict[section] = {}
for key, val in config.items(section):
config_dict[section][key] = val
return from_config_dict(config_dict, hass)
def enable_logging(hass):
""" Setup the logging for home assistant. """
logging.basicConfig(level=logging.INFO)
# Log errors to a file if we have write access to file or config dir
err_log_path = hass.get_config_path("home-assistant.log")
err_path_exists = os.path.isfile(err_log_path)
# Check if we can write to the error log if it exists or that
# we can create files in the containing directory if not.
if (err_path_exists and os.access(err_log_path, os.W_OK)) or \
(not err_path_exists and os.access(hass.config_dir, os.W_OK)):
err_handler = logging.FileHandler(
err_log_path, mode='w', delay=True)
err_handler.setLevel(logging.WARNING)
err_handler.setFormatter(
logging.Formatter('%(asctime)s %(name)s: %(message)s',
datefmt='%H:%M %d-%m-%y'))
logging.getLogger('').addHandler(err_handler)
else:
_LOGGER.error(
"Unable to setup error log %s (access denied)", err_log_path)
def _ensure_loader_prepared(hass):
""" Ensure Home Assistant loader is prepared. """
if not loader.PREPARED:
loader.prepare(hass)