Logging is more efficient
This commit is contained in:
parent
c3c1383ae6
commit
1e136a2416
15 changed files with 136 additions and 158 deletions
|
@ -50,6 +50,8 @@ POOL_NUM_THREAD = 4
|
||||||
# Pattern for validating entity IDs (format: <domain>.<entity>)
|
# Pattern for validating entity IDs (format: <domain>.<entity>)
|
||||||
ENTITY_ID_PATTERN = re.compile(r"^(?P<domain>\w+)\.(?P<entity>\w+)$")
|
ENTITY_ID_PATTERN = re.compile(r"^(?P<domain>\w+)\.(?P<entity>\w+)$")
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
class HomeAssistant(object):
|
class HomeAssistant(object):
|
||||||
""" Core class to route all communication to right components. """
|
""" Core class to route all communication to right components. """
|
||||||
|
@ -256,7 +258,6 @@ class JobPriority(util.OrderedEnum):
|
||||||
|
|
||||||
def create_worker_pool(thread_count=POOL_NUM_THREAD):
|
def create_worker_pool(thread_count=POOL_NUM_THREAD):
|
||||||
""" Creates a worker pool to be used. """
|
""" Creates a worker pool to be used. """
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
def job_handler(job):
|
def job_handler(job):
|
||||||
""" Called whenever a job is available to do. """
|
""" Called whenever a job is available to do. """
|
||||||
|
@ -266,19 +267,18 @@ def create_worker_pool(thread_count=POOL_NUM_THREAD):
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
# Catch any exception our service/event_listener might throw
|
# Catch any exception our service/event_listener might throw
|
||||||
# We do not want to crash our ThreadPool
|
# We do not want to crash our ThreadPool
|
||||||
logger.exception("BusHandler:Exception doing job")
|
_LOGGER.exception("BusHandler:Exception doing job")
|
||||||
|
|
||||||
def busy_callback(current_jobs, pending_jobs_count):
|
def busy_callback(current_jobs, pending_jobs_count):
|
||||||
""" Callback to be called when the pool queue gets too big. """
|
""" Callback to be called when the pool queue gets too big. """
|
||||||
log_error = logger.error
|
|
||||||
|
|
||||||
log_error(
|
_LOGGER.error(
|
||||||
"WorkerPool:All {} threads are busy and {} jobs pending".format(
|
"WorkerPool:All %d threads are busy and %d jobs pending",
|
||||||
thread_count, pending_jobs_count))
|
thread_count, pending_jobs_count)
|
||||||
|
|
||||||
for start, job in current_jobs:
|
for start, job in current_jobs:
|
||||||
log_error("WorkerPool:Current job from {}: {}".format(
|
_LOGGER.error("WorkerPool:Current job from %s: %s",
|
||||||
util.datetime_to_str(start), job))
|
util.datetime_to_str(start), job)
|
||||||
|
|
||||||
return util.ThreadPool(thread_count, job_handler, busy_callback)
|
return util.ThreadPool(thread_count, job_handler, busy_callback)
|
||||||
|
|
||||||
|
@ -323,7 +323,6 @@ class EventBus(object):
|
||||||
|
|
||||||
def __init__(self, pool=None):
|
def __init__(self, pool=None):
|
||||||
self._listeners = {}
|
self._listeners = {}
|
||||||
self._logger = logging.getLogger(__name__)
|
|
||||||
self._lock = threading.Lock()
|
self._lock = threading.Lock()
|
||||||
self._pool = pool or create_worker_pool()
|
self._pool = pool or create_worker_pool()
|
||||||
|
|
||||||
|
@ -347,7 +346,7 @@ class EventBus(object):
|
||||||
|
|
||||||
event = Event(event_type, event_data, origin)
|
event = Event(event_type, event_data, origin)
|
||||||
|
|
||||||
self._logger.info("Bus:Handling {}".format(event))
|
_LOGGER.info("Bus:Handling %s", event)
|
||||||
|
|
||||||
if not listeners:
|
if not listeners:
|
||||||
return
|
return
|
||||||
|
@ -602,7 +601,7 @@ class Timer(threading.Thread):
|
||||||
def run(self):
|
def run(self):
|
||||||
""" Start the timer. """
|
""" Start the timer. """
|
||||||
|
|
||||||
logging.getLogger(__name__).info("Timer:starting")
|
_LOGGER.info("Timer:starting")
|
||||||
|
|
||||||
last_fired_on_second = -1
|
last_fired_on_second = -1
|
||||||
|
|
||||||
|
|
|
@ -117,8 +117,8 @@ def from_config_dict(config, hass=None):
|
||||||
if dep not in validated]
|
if dep not in validated]
|
||||||
|
|
||||||
logger.error(
|
logger.error(
|
||||||
"Could not validate all dependencies for {}: {}".format(
|
"Could not validate all dependencies for %s: %s",
|
||||||
domain, ", ".join(missing_deps)))
|
domain, ", ".join(missing_deps))
|
||||||
|
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -139,14 +139,12 @@ def from_config_dict(config, hass=None):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if component.setup(hass, config):
|
if component.setup(hass, config):
|
||||||
logger.info("component {} initialized".format(domain))
|
logger.info("component %s initialized", domain)
|
||||||
else:
|
else:
|
||||||
logger.error(
|
logger.error("component %s failed to initialize", domain)
|
||||||
"component {} failed to initialize".format(domain))
|
|
||||||
|
|
||||||
except Exception: # pylint: disable=broad-except
|
except Exception: # pylint: disable=broad-except
|
||||||
logger.exception(
|
logger.exception("Error during setup of component %s", domain)
|
||||||
"Error during setup of component {}".format(domain))
|
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error(("Home Assistant core failed to initialize. "
|
logger.error(("Home Assistant core failed to initialize. "
|
||||||
|
@ -175,6 +173,8 @@ def from_config_file(config_path, hass=None, enable_logging=True):
|
||||||
err_log_path = hass.get_config_path("home-assistant.log")
|
err_log_path = hass.get_config_path("home-assistant.log")
|
||||||
err_path_exists = os.path.isfile(err_log_path)
|
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 containgin directory if not.
|
||||||
if (err_path_exists and os.access(err_log_path, os.W_OK)) or \
|
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)):
|
(not err_path_exists and os.access(hass.config_dir, os.W_OK)):
|
||||||
|
|
||||||
|
@ -189,8 +189,7 @@ def from_config_file(config_path, hass=None, enable_logging=True):
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logging.getLogger(__name__).error(
|
logging.getLogger(__name__).error(
|
||||||
"Unable to setup error log {} (access denied)".format(
|
"Unable to setup error log %s (access denied)", err_log_path)
|
||||||
err_log_path))
|
|
||||||
|
|
||||||
# Read config
|
# Read config
|
||||||
config = configparser.ConfigParser()
|
config = configparser.ConfigParser()
|
||||||
|
|
|
@ -48,7 +48,7 @@ SERVICE_MEDIA_PAUSE = "media_pause"
|
||||||
SERVICE_MEDIA_NEXT_TRACK = "media_next_track"
|
SERVICE_MEDIA_NEXT_TRACK = "media_next_track"
|
||||||
SERVICE_MEDIA_PREV_TRACK = "media_prev_track"
|
SERVICE_MEDIA_PREV_TRACK = "media_prev_track"
|
||||||
|
|
||||||
__LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def is_on(hass, entity_id=None):
|
def is_on(hass, entity_id=None):
|
||||||
|
@ -72,7 +72,8 @@ def is_on(hass, entity_id=None):
|
||||||
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
# module is None or method is_on does not exist
|
# module is None or method is_on does not exist
|
||||||
pass
|
_LOGGER.exception("Failed to call %s.is_on for %s",
|
||||||
|
module, entity_id)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -123,6 +124,9 @@ def setup(hass, config):
|
||||||
|
|
||||||
# Generic turn on/off method requires entity id
|
# Generic turn on/off method requires entity id
|
||||||
if not entity_ids:
|
if not entity_ids:
|
||||||
|
_LOGGER.error(
|
||||||
|
"homeassistant/%s cannot be called without entity_id",
|
||||||
|
service.service)
|
||||||
return
|
return
|
||||||
|
|
||||||
# Group entity_ids by domain. groupby requires sorted data.
|
# Group entity_ids by domain. groupby requires sorted data.
|
||||||
|
|
|
@ -21,7 +21,7 @@ def setup(hass, config):
|
||||||
hass.services.register(DOMAIN, SERVICE_BROWSE_URL,
|
hass.services.register(DOMAIN, SERVICE_BROWSE_URL,
|
||||||
lambda service:
|
lambda service:
|
||||||
webbrowser.open(
|
webbrowser.open(
|
||||||
service.data.get('url',
|
service.data.get(
|
||||||
'https://www.google.com')))
|
'url', 'https://www.google.com')))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -118,11 +118,9 @@ def setup(hass, config):
|
||||||
if light_needed:
|
if light_needed:
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"Home coming event for {}. Turning lights on".
|
"Home coming event for %s. Turning lights on", entity)
|
||||||
format(entity))
|
|
||||||
|
|
||||||
light.turn_on(hass, light_ids,
|
light.turn_on(hass, light_ids, profile=light_profile)
|
||||||
profile=light_profile)
|
|
||||||
|
|
||||||
# Are we in the time span were we would turn on the lights
|
# Are we in the time span were we would turn on the lights
|
||||||
# if someone would be home?
|
# if someone would be home?
|
||||||
|
|
|
@ -43,6 +43,8 @@ KNOWN_DEVICES_FILE = "known_devices.csv"
|
||||||
|
|
||||||
CONF_HTTP_ID = "http_id"
|
CONF_HTTP_ID = "http_id"
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def is_on(hass, entity_id=None):
|
def is_on(hass, entity_id=None):
|
||||||
""" Returns if any or specified device is home. """
|
""" Returns if any or specified device is home. """
|
||||||
|
@ -54,17 +56,15 @@ def is_on(hass, entity_id=None):
|
||||||
def setup(hass, config):
|
def setup(hass, config):
|
||||||
""" Sets up the device tracker. """
|
""" Sets up the device tracker. """
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
# We have flexible requirements for device tracker so
|
# We have flexible requirements for device tracker so
|
||||||
# we cannot use util.validate_config
|
# we cannot use util.validate_config
|
||||||
|
|
||||||
conf = config[DOMAIN]
|
conf = config[DOMAIN]
|
||||||
|
|
||||||
if ha.CONF_TYPE not in conf:
|
if ha.CONF_TYPE not in conf:
|
||||||
logger.error(
|
_LOGGER.error(
|
||||||
'Missing required configuration item in {}: {}'.format(
|
'Missing required configuration item in %s: %s',
|
||||||
DOMAIN, ha.CONF_TYPE))
|
DOMAIN, ha.CONF_TYPE)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -84,18 +84,18 @@ def setup(hass, config):
|
||||||
scanner = LuciDeviceScanner
|
scanner = LuciDeviceScanner
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error('Found unknown router type {}'.format(router_type))
|
_LOGGER.error('Found unknown router type %s', router_type)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if not util.validate_config(config, {DOMAIN: fields}, logger):
|
if not util.validate_config(config, {DOMAIN: fields}, _LOGGER):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
device_scanner = scanner(conf)
|
device_scanner = scanner(conf)
|
||||||
|
|
||||||
if not device_scanner.success_init:
|
if not device_scanner.success_init:
|
||||||
logger.error(
|
_LOGGER.error("Failed to initialize device scanner for %s",
|
||||||
"Failed to initialize device scanner for {}".format(router_type))
|
router_type)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -115,8 +115,6 @@ class DeviceTracker(object):
|
||||||
|
|
||||||
self.error_scanning = TIME_SPAN_FOR_ERROR_IN_SCANNING
|
self.error_scanning = TIME_SPAN_FOR_ERROR_IN_SCANNING
|
||||||
|
|
||||||
self.logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
self.lock = threading.Lock()
|
self.lock = threading.Lock()
|
||||||
|
|
||||||
self.path_known_devices_file = hass.get_config_path(KNOWN_DEVICES_FILE)
|
self.path_known_devices_file = hass.get_config_path(KNOWN_DEVICES_FILE)
|
||||||
|
@ -205,8 +203,8 @@ class DeviceTracker(object):
|
||||||
is_new_file = not os.path.isfile(known_dev_path)
|
is_new_file = not os.path.isfile(known_dev_path)
|
||||||
|
|
||||||
with open(known_dev_path, 'a') as outp:
|
with open(known_dev_path, 'a') as outp:
|
||||||
self.logger.info((
|
_LOGGER.info((
|
||||||
"DeviceTracker:Found {} new devices,"
|
"Found {} new devices,"
|
||||||
" updating {}").format(len(unknown_devices),
|
" updating {}").format(len(unknown_devices),
|
||||||
known_dev_path))
|
known_dev_path))
|
||||||
|
|
||||||
|
@ -228,8 +226,8 @@ class DeviceTracker(object):
|
||||||
'picture': ""}
|
'picture': ""}
|
||||||
|
|
||||||
except IOError:
|
except IOError:
|
||||||
self.logger.exception((
|
_LOGGER.exception((
|
||||||
"DeviceTracker:Error updating {}"
|
"Error updating {}"
|
||||||
"with {} new devices").format(known_dev_path,
|
"with {} new devices").format(known_dev_path,
|
||||||
len(unknown_devices)))
|
len(unknown_devices)))
|
||||||
|
|
||||||
|
@ -292,9 +290,9 @@ class DeviceTracker(object):
|
||||||
known_devices[device] = row
|
known_devices[device] = row
|
||||||
|
|
||||||
if not known_devices:
|
if not known_devices:
|
||||||
self.logger.warning(
|
_LOGGER.warning(
|
||||||
"No devices to track. Please update {}.".format(
|
"No devices to track. Please update %s.",
|
||||||
self.path_known_devices_file))
|
self.path_known_devices_file)
|
||||||
|
|
||||||
# Remove entities that are no longer maintained
|
# Remove entities that are no longer maintained
|
||||||
new_entity_ids = set([known_devices[device]['entity_id']
|
new_entity_ids = set([known_devices[device]['entity_id']
|
||||||
|
@ -304,25 +302,22 @@ class DeviceTracker(object):
|
||||||
for entity_id in \
|
for entity_id in \
|
||||||
self.device_entity_ids - new_entity_ids:
|
self.device_entity_ids - new_entity_ids:
|
||||||
|
|
||||||
self.logger.info(
|
_LOGGER.info("Removing entity %s", entity_id)
|
||||||
"DeviceTracker:Removing entity {}".format(
|
|
||||||
entity_id))
|
|
||||||
self.states.remove(entity_id)
|
self.states.remove(entity_id)
|
||||||
|
|
||||||
# File parsed, warnings given if necessary
|
# File parsed, warnings given if necessary
|
||||||
# entities cleaned up, make it available
|
# entities cleaned up, make it available
|
||||||
self.known_devices = known_devices
|
self.known_devices = known_devices
|
||||||
|
|
||||||
self.logger.info(
|
_LOGGER.info("Loaded devices from %s",
|
||||||
"DeviceTracker:Loaded devices from {}".format(
|
self.path_known_devices_file)
|
||||||
self.path_known_devices_file))
|
|
||||||
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
self.invalid_known_devices_file = True
|
self.invalid_known_devices_file = True
|
||||||
self.logger.warning((
|
_LOGGER.warning(
|
||||||
"Invalid known devices file: {}. "
|
("Invalid known devices file: %s. "
|
||||||
"We won't update it with new found devices."
|
"We won't update it with new found devices."),
|
||||||
).format(self.path_known_devices_file))
|
self.path_known_devices_file)
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
@ -349,7 +344,7 @@ class TomatoDeviceScanner(object):
|
||||||
|
|
||||||
self.parse_api_pattern = re.compile(r"(?P<param>\w*) = (?P<value>.*);")
|
self.parse_api_pattern = re.compile(r"(?P<param>\w*) = (?P<value>.*);")
|
||||||
|
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger("{}.{}".format(__name__, "Tomato"))
|
||||||
self.lock = threading.Lock()
|
self.lock = threading.Lock()
|
||||||
|
|
||||||
self.date_updated = None
|
self.date_updated = None
|
||||||
|
@ -390,7 +385,7 @@ class TomatoDeviceScanner(object):
|
||||||
if not self.date_updated or \
|
if not self.date_updated or \
|
||||||
datetime.now() - self.date_updated > MIN_TIME_BETWEEN_SCANS:
|
datetime.now() - self.date_updated > MIN_TIME_BETWEEN_SCANS:
|
||||||
|
|
||||||
self.logger.info("Tomato:Scanning")
|
self.logger.info("Scanning")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
response = requests.Session().send(self.req, timeout=3)
|
response = requests.Session().send(self.req, timeout=3)
|
||||||
|
@ -415,7 +410,7 @@ class TomatoDeviceScanner(object):
|
||||||
elif response.status_code == 401:
|
elif response.status_code == 401:
|
||||||
# Authentication error
|
# Authentication error
|
||||||
self.logger.exception((
|
self.logger.exception((
|
||||||
"Tomato:Failed to authenticate, "
|
"Failed to authenticate, "
|
||||||
"please check your username and password"))
|
"please check your username and password"))
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -424,7 +419,7 @@ class TomatoDeviceScanner(object):
|
||||||
# We get this if we could not connect to the router or
|
# We get this if we could not connect to the router or
|
||||||
# an invalid http_id was supplied
|
# an invalid http_id was supplied
|
||||||
self.logger.exception((
|
self.logger.exception((
|
||||||
"Tomato:Failed to connect to the router"
|
"Failed to connect to the router"
|
||||||
" or invalid http_id supplied"))
|
" or invalid http_id supplied"))
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
@ -433,14 +428,14 @@ class TomatoDeviceScanner(object):
|
||||||
# We get this if we could not connect to the router or
|
# We get this if we could not connect to the router or
|
||||||
# an invalid http_id was supplied
|
# an invalid http_id was supplied
|
||||||
self.logger.exception(
|
self.logger.exception(
|
||||||
"Tomato:Connection to the router timed out")
|
"Connection to the router timed out")
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
# If json decoder could not parse the response
|
# If json decoder could not parse the response
|
||||||
self.logger.exception(
|
self.logger.exception(
|
||||||
"Tomato:Failed to parse response from router")
|
"Failed to parse response from router")
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -462,15 +457,17 @@ class NetgearDeviceScanner(object):
|
||||||
host = config['host']
|
host = config['host']
|
||||||
username, password = config['username'], config['password']
|
username, password = config['username'], config['password']
|
||||||
|
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger("{}.{}".format(__name__, "Netgear"))
|
||||||
self.date_updated = None
|
self.date_updated = None
|
||||||
self.last_results = []
|
self.last_results = []
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Pylint does not play nice if not every folders has an __init__.py
|
||||||
|
# pylint: disable=no-name-in-module, import-error
|
||||||
import homeassistant.external.pynetgear.pynetgear as pynetgear
|
import homeassistant.external.pynetgear.pynetgear as pynetgear
|
||||||
except ImportError:
|
except ImportError:
|
||||||
self.logger.exception(
|
self.logger.exception(
|
||||||
("Netgear:Failed to import pynetgear. "
|
("Failed to import pynetgear. "
|
||||||
"Did you maybe not run `git submodule init` "
|
"Did you maybe not run `git submodule init` "
|
||||||
"and `git submodule update`?"))
|
"and `git submodule update`?"))
|
||||||
|
|
||||||
|
@ -481,7 +478,7 @@ class NetgearDeviceScanner(object):
|
||||||
self._api = pynetgear.Netgear(host, username, password)
|
self._api = pynetgear.Netgear(host, username, password)
|
||||||
self.lock = threading.Lock()
|
self.lock = threading.Lock()
|
||||||
|
|
||||||
self.logger.info("Netgear:Logging in")
|
self.logger.info("Logging in")
|
||||||
if self._api.login():
|
if self._api.login():
|
||||||
self.success_init = True
|
self.success_init = True
|
||||||
self._update_info()
|
self._update_info()
|
||||||
|
@ -526,7 +523,7 @@ class NetgearDeviceScanner(object):
|
||||||
if not self.date_updated or \
|
if not self.date_updated or \
|
||||||
datetime.now() - self.date_updated > MIN_TIME_BETWEEN_SCANS:
|
datetime.now() - self.date_updated > MIN_TIME_BETWEEN_SCANS:
|
||||||
|
|
||||||
self.logger.info("Netgear:Scanning")
|
self.logger.info("Scanning")
|
||||||
|
|
||||||
self.last_results = self._api.get_attached_devices()
|
self.last_results = self._api.get_attached_devices()
|
||||||
|
|
||||||
|
@ -557,7 +554,7 @@ class LuciDeviceScanner(object):
|
||||||
|
|
||||||
self.parse_api_pattern = re.compile(r"(?P<param>\w*) = (?P<value>.*);")
|
self.parse_api_pattern = re.compile(r"(?P<param>\w*) = (?P<value>.*);")
|
||||||
|
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger("{}.{}".format(__name__, "Luci"))
|
||||||
self.lock = threading.Lock()
|
self.lock = threading.Lock()
|
||||||
|
|
||||||
self.date_updated = None
|
self.date_updated = None
|
||||||
|
@ -596,7 +593,7 @@ class LuciDeviceScanner(object):
|
||||||
"please check your username and password")
|
"please check your username and password")
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
self.logger.error("Invalid response from luci: {}".format(res))
|
self.logger.error("Invalid response from luci: %s", res)
|
||||||
|
|
||||||
def get_token(self, host, username, password):
|
def get_token(self, host, username, password):
|
||||||
""" Get authentication token for the given host+username+password """
|
""" Get authentication token for the given host+username+password """
|
||||||
|
|
|
@ -44,15 +44,15 @@ def setup(hass, config):
|
||||||
if not os.path.isdir(download_path):
|
if not os.path.isdir(download_path):
|
||||||
|
|
||||||
logger.error(
|
logger.error(
|
||||||
"Download path {} does not exist. File Downloader not active.".
|
"Download path %s does not exist. File Downloader not active.",
|
||||||
format(download_path))
|
download_path)
|
||||||
|
|
||||||
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 not ATTR_URL 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
|
||||||
|
|
||||||
|
@ -114,18 +114,16 @@ def setup(hass, config):
|
||||||
|
|
||||||
final_path = "{}_{}.{}".format(path, tries, ext)
|
final_path = "{}_{}.{}".format(path, tries, ext)
|
||||||
|
|
||||||
logger.info("{} -> {}".format(url, final_path))
|
logger.info("%s -> %s", url, final_path)
|
||||||
|
|
||||||
with open(final_path, 'wb') as fil:
|
with open(final_path, 'wb') as fil:
|
||||||
for chunk in req.iter_content(1024):
|
for chunk in req.iter_content(1024):
|
||||||
fil.write(chunk)
|
fil.write(chunk)
|
||||||
|
|
||||||
logger.info("Downloading of {} done".format(
|
logger.info("Downloading of %s done", url)
|
||||||
url))
|
|
||||||
|
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
logger.exception("ConnectionError occured for {}".
|
logger.exception("ConnectionError occured for %s", url)
|
||||||
format(url))
|
|
||||||
|
|
||||||
# Remove file if we started downloading but failed
|
# Remove file if we started downloading but failed
|
||||||
if final_path and os.path.isfile(final_path):
|
if final_path and os.path.isfile(final_path):
|
||||||
|
|
|
@ -106,8 +106,6 @@ def setup_group(hass, name, entity_ids, user_defined=True):
|
||||||
""" Sets up a group state that is the combined state of
|
""" Sets up a group state that is the combined state of
|
||||||
several states. Supports ON/OFF and DEVICE_HOME/DEVICE_NOT_HOME. """
|
several states. Supports ON/OFF and DEVICE_HOME/DEVICE_NOT_HOME. """
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
# In case an iterable is passed in
|
# In case an iterable is passed in
|
||||||
entity_ids = list(entity_ids)
|
entity_ids = list(entity_ids)
|
||||||
|
|
||||||
|
@ -145,7 +143,7 @@ def setup_group(hass, name, entity_ids, user_defined=True):
|
||||||
# Check if entity is valid state
|
# Check if entity is valid state
|
||||||
elif state.state != group_off and state.state != group_on:
|
elif state.state != group_off and state.state != group_on:
|
||||||
|
|
||||||
errors.append("State of {} is {} (expected: {}, {})".format(
|
errors.append("State of {} is {} (expected: {} or {})".format(
|
||||||
entity_id, state.state, group_off, group_on))
|
entity_id, state.state, group_off, group_on))
|
||||||
|
|
||||||
# Keep track of the group state to init later on
|
# Keep track of the group state to init later on
|
||||||
|
@ -156,8 +154,8 @@ def setup_group(hass, name, entity_ids, user_defined=True):
|
||||||
errors.append('Unable to determine group type for {}'.format(name))
|
errors.append('Unable to determine group type for {}'.format(name))
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
logger.error("Error setting up group {}: {}".format(
|
logging.getLogger(__name__).error(
|
||||||
name, ", ".join(errors)))
|
"Error setting up group %s: %s", name, ", ".join(errors))
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
|
@ -110,12 +110,14 @@ CONF_SERVER_HOST = "server_host"
|
||||||
CONF_SERVER_PORT = "server_port"
|
CONF_SERVER_PORT = "server_port"
|
||||||
CONF_DEVELOPMENT = "development"
|
CONF_DEVELOPMENT = "development"
|
||||||
|
|
||||||
|
_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. """
|
||||||
|
|
||||||
if not util.validate_config(config, {DOMAIN: [CONF_API_PASSWORD]},
|
if not util.validate_config(config, {DOMAIN: [CONF_API_PASSWORD]},
|
||||||
logging.getLogger(__name__)):
|
_LOGGER):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
api_password = config[DOMAIN]['api_password']
|
api_password = config[DOMAIN]['api_password']
|
||||||
|
@ -156,22 +158,17 @@ class HomeAssistantHTTPServer(ThreadingMixIn, HTTPServer):
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.api_password = api_password
|
self.api_password = api_password
|
||||||
self.development = development
|
self.development = development
|
||||||
self.logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
# To store flash messages between sessions
|
|
||||||
self.flash_message = None
|
|
||||||
|
|
||||||
# We will lazy init this one if needed
|
# We will lazy init this one if needed
|
||||||
self.event_forwarder = None
|
self.event_forwarder = None
|
||||||
|
|
||||||
if development:
|
if development:
|
||||||
self.logger.info("running frontend in development mode")
|
_LOGGER.info("running frontend in development mode")
|
||||||
|
|
||||||
def start(self):
|
def start(self):
|
||||||
""" Starts the server. """
|
""" Starts the server. """
|
||||||
self.logger.info(
|
_LOGGER.info(
|
||||||
"Web interface starting at http://{}:{}".format(
|
"Starting web interface at http://%s:%d", *self.server_address)
|
||||||
*self.server_address))
|
|
||||||
|
|
||||||
self.serve_forever()
|
self.serve_forever()
|
||||||
|
|
||||||
|
@ -256,8 +253,8 @@ class RequestHandler(SimpleHTTPRequestHandler):
|
||||||
try:
|
try:
|
||||||
data.update(json.loads(body_content))
|
data.update(json.loads(body_content))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
self.server.logger.exception(
|
_LOGGER.exception("Exception parsing JSON: %s",
|
||||||
"Exception parsing JSON: {}".format(body_content))
|
body_content)
|
||||||
|
|
||||||
self._message(
|
self._message(
|
||||||
"Error parsing JSON", HTTP_UNPROCESSABLE_ENTITY)
|
"Error parsing JSON", HTTP_UNPROCESSABLE_ENTITY)
|
||||||
|
@ -598,9 +595,6 @@ class RequestHandler(SimpleHTTPRequestHandler):
|
||||||
""" Helper method to return a message to the caller. """
|
""" Helper method to return a message to the caller. """
|
||||||
if self.use_json:
|
if self.use_json:
|
||||||
self._write_json({'message': message}, status_code=status_code)
|
self._write_json({'message': message}, status_code=status_code)
|
||||||
elif status_code == HTTP_OK:
|
|
||||||
self.server.flash_message = message
|
|
||||||
self._redirect('/')
|
|
||||||
else:
|
else:
|
||||||
self.send_error(status_code, message)
|
self.send_error(status_code, message)
|
||||||
|
|
||||||
|
|
|
@ -153,7 +153,7 @@ def setup(hass, config):
|
||||||
light_init = HueLightControl
|
light_init = HueLightControl
|
||||||
|
|
||||||
else:
|
else:
|
||||||
logger.error("Found unknown light type: {}".format(light_type))
|
logger.error("Unknown light type specified: %s", light_type)
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -172,7 +172,7 @@ def setup(hass, config):
|
||||||
# We have not seen this light before, set it up
|
# We have not seen this light before, set it up
|
||||||
|
|
||||||
# Create entity id
|
# Create entity id
|
||||||
logger.info("Found new light {}".format(name))
|
logger.info("Found new light %s", name)
|
||||||
|
|
||||||
entity_id = util.ensure_unique_string(
|
entity_id = util.ensure_unique_string(
|
||||||
ENTITY_ID_FORMAT.format(util.slugify(name)),
|
ENTITY_ID_FORMAT.format(util.slugify(name)),
|
||||||
|
@ -251,8 +251,7 @@ def setup(hass, config):
|
||||||
# ValueError if not 4 values per row
|
# ValueError if not 4 values per row
|
||||||
# ValueError if convert to float/int failed
|
# ValueError if convert to float/int failed
|
||||||
logger.error(
|
logger.error(
|
||||||
"Error parsing light profiles from {}".format(
|
"Error parsing light profiles from %s", profile_path)
|
||||||
profile_path))
|
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -357,15 +356,16 @@ class HueLightControl(object):
|
||||||
""" Class to interface with the Hue light system. """
|
""" Class to interface with the Hue light system. """
|
||||||
|
|
||||||
def __init__(self, hass, config):
|
def __init__(self, hass, config):
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger("{}.{}".format(__name__, "HueLightControl"))
|
||||||
|
|
||||||
host = config.get(ha.CONF_HOST, None)
|
host = config.get(ha.CONF_HOST, None)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Pylint does not play nice if not every folders has an __init__.py
|
||||||
|
# pylint: disable=no-name-in-module, import-error
|
||||||
import homeassistant.external.phue.phue as phue
|
import homeassistant.external.phue.phue as phue
|
||||||
except ImportError:
|
except ImportError:
|
||||||
logger.exception(
|
logger.exception("Error while importing dependency phue.")
|
||||||
"HueLightControl:Error while importing dependency phue.")
|
|
||||||
|
|
||||||
self.success_init = False
|
self.success_init = False
|
||||||
|
|
||||||
|
@ -377,8 +377,8 @@ class HueLightControl(object):
|
||||||
PHUE_CONFIG_FILE))
|
PHUE_CONFIG_FILE))
|
||||||
except socket.error: # Error connecting using Phue
|
except socket.error: # Error connecting using Phue
|
||||||
logger.exception((
|
logger.exception((
|
||||||
"HueLightControl:Error while connecting to the bridge. "
|
"Error while connecting to the bridge. "
|
||||||
"Is phue registered?"))
|
"Did you follow the instructions to set it up?"))
|
||||||
|
|
||||||
self.success_init = False
|
self.success_init = False
|
||||||
|
|
||||||
|
@ -389,7 +389,7 @@ class HueLightControl(object):
|
||||||
self._update_lights()
|
self._update_lights()
|
||||||
|
|
||||||
if len(self._lights) == 0:
|
if len(self._lights) == 0:
|
||||||
logger.error("HueLightControl:Could not find any lights. ")
|
logger.error("Could not find any lights. ")
|
||||||
|
|
||||||
self.success_init = False
|
self.success_init = False
|
||||||
else:
|
else:
|
||||||
|
@ -409,7 +409,7 @@ class HueLightControl(object):
|
||||||
|
|
||||||
def get_name(self, light_id):
|
def get_name(self, light_id):
|
||||||
""" Return name for specified light_id or None if no name known. """
|
""" Return name for specified light_id or None if no name known. """
|
||||||
if not light_id in self._lights:
|
if light_id not in self._lights:
|
||||||
self._update_lights()
|
self._update_lights()
|
||||||
|
|
||||||
return self._lights.get(light_id)
|
return self._lights.get(light_id)
|
||||||
|
|
|
@ -91,9 +91,8 @@ def setup(hass, config):
|
||||||
new_state = STATE_BELOW_HORIZON
|
new_state = STATE_BELOW_HORIZON
|
||||||
next_change = next_rising_dt
|
next_change = next_rising_dt
|
||||||
|
|
||||||
logger.info(
|
logger.info("%s. Next change: %s",
|
||||||
"{}. Next change: {}".format(new_state,
|
new_state, next_change.strftime("%H:%M"))
|
||||||
next_change.strftime("%H:%M")))
|
|
||||||
|
|
||||||
state_attributes = {
|
state_attributes = {
|
||||||
STATE_ATTR_NEXT_RISING: util.datetime_to_str(next_rising_dt),
|
STATE_ATTR_NEXT_RISING: util.datetime_to_str(next_rising_dt),
|
||||||
|
|
|
@ -54,6 +54,8 @@ def setup(hass, config):
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
# Pylint does not play nice if not every folders has an __init__.py
|
||||||
|
# pylint: disable=no-name-in-module, import-error
|
||||||
import homeassistant.external.pywemo.pywemo as pywemo
|
import homeassistant.external.pywemo.pywemo as pywemo
|
||||||
except ImportError:
|
except ImportError:
|
||||||
logger.exception((
|
logger.exception((
|
||||||
|
|
|
@ -63,7 +63,7 @@ def get_component(comp_name):
|
||||||
if path in AVAILABLE_COMPONENTS]
|
if path in AVAILABLE_COMPONENTS]
|
||||||
|
|
||||||
if not potential_paths:
|
if not potential_paths:
|
||||||
_LOGGER.error("Failed to find component {}".format(comp_name))
|
_LOGGER.error("Failed to find component %s", comp_name)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -71,15 +71,14 @@ def get_component(comp_name):
|
||||||
comp = _get_component(path)
|
comp = _get_component(path)
|
||||||
|
|
||||||
if comp is not None:
|
if comp is not None:
|
||||||
_LOGGER.info("Loaded component {} from {}".format(
|
_LOGGER.info("Loaded component %s from %s", comp_name, path)
|
||||||
comp_name, path))
|
|
||||||
|
|
||||||
_COMPONENT_CACHE[comp_name] = comp
|
_COMPONENT_CACHE[comp_name] = comp
|
||||||
|
|
||||||
return comp
|
return comp
|
||||||
|
|
||||||
# We did find components but were unable to load them
|
# We did find components but were unable to load them
|
||||||
_LOGGER.error("Unable to load component {}".format(comp_name))
|
_LOGGER.error("Unable to load component %s", comp_name)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -91,8 +90,8 @@ def _get_component(module):
|
||||||
comp = importlib.import_module(module)
|
comp = importlib.import_module(module)
|
||||||
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
_LOGGER.exception(("Error loading {}. Make sure all "
|
_LOGGER.exception(("Error loading %s. Make sure all "
|
||||||
"dependencies are installed").format(module))
|
"dependencies are installed"), module)
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@ -109,8 +108,8 @@ def _get_component(module):
|
||||||
errors.append("missing setup method")
|
errors.append("missing setup method")
|
||||||
|
|
||||||
if errors:
|
if errors:
|
||||||
_LOGGER.error("Found invalid component {}: {}".format(
|
_LOGGER.error("Found invalid component %s: %s",
|
||||||
module, ", ".join(errors)))
|
module, ", ".join(errors))
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
|
@ -35,6 +35,8 @@ URL_API_EVENT_FORWARD = "/api/event_forwarding"
|
||||||
METHOD_GET = "get"
|
METHOD_GET = "get"
|
||||||
METHOD_POST = "post"
|
METHOD_POST = "post"
|
||||||
|
|
||||||
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=no-init, invalid-name
|
# pylint: disable=no-init, invalid-name
|
||||||
class APIStatus(enum.Enum):
|
class APIStatus(enum.Enum):
|
||||||
|
@ -84,12 +86,12 @@ class API(object):
|
||||||
method, url, data=data, timeout=5, headers=self._headers)
|
method, url, data=data, timeout=5, headers=self._headers)
|
||||||
|
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
logging.getLogger(__name__).exception("Error connecting to server")
|
_LOGGER.exception("Error connecting to server")
|
||||||
raise ha.HomeAssistantError("Error connecting to server")
|
raise ha.HomeAssistantError("Error connecting to server")
|
||||||
|
|
||||||
except requests.exceptions.Timeout:
|
except requests.exceptions.Timeout:
|
||||||
error = "Timeout when talking to {}".format(self.host)
|
error = "Timeout when talking to {}".format(self.host)
|
||||||
logging.getLogger(__name__).exception(error)
|
_LOGGER.exception(error)
|
||||||
raise ha.HomeAssistantError(error)
|
raise ha.HomeAssistantError(error)
|
||||||
|
|
||||||
|
|
||||||
|
@ -159,7 +161,6 @@ class EventForwarder(object):
|
||||||
def __init__(self, hass, restrict_origin=None):
|
def __init__(self, hass, restrict_origin=None):
|
||||||
self.hass = hass
|
self.hass = hass
|
||||||
self.restrict_origin = restrict_origin
|
self.restrict_origin = restrict_origin
|
||||||
self.logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
# We use a tuple (host, port) as key to ensure
|
# We use a tuple (host, port) as key to ensure
|
||||||
# that we do not forward to the same host twice
|
# that we do not forward to the same host twice
|
||||||
|
@ -205,7 +206,7 @@ class EventForwarder(object):
|
||||||
return
|
return
|
||||||
|
|
||||||
for api in self._targets.values():
|
for api in self._targets.values():
|
||||||
fire_event(api, event.event_type, event.data, self.logger)
|
fire_event(api, event.event_type, event.data)
|
||||||
|
|
||||||
|
|
||||||
class StateMachine(ha.StateMachine):
|
class StateMachine(ha.StateMachine):
|
||||||
|
@ -217,8 +218,6 @@ class StateMachine(ha.StateMachine):
|
||||||
def __init__(self, bus, api):
|
def __init__(self, bus, api):
|
||||||
super().__init__(None)
|
super().__init__(None)
|
||||||
|
|
||||||
self.logger = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
self._api = api
|
self._api = api
|
||||||
|
|
||||||
self.mirror()
|
self.mirror()
|
||||||
|
@ -232,7 +231,7 @@ class StateMachine(ha.StateMachine):
|
||||||
def mirror(self):
|
def mirror(self):
|
||||||
""" Discards current data and mirrors the remote state machine. """
|
""" Discards current data and mirrors the remote state machine. """
|
||||||
self._states = {state.entity_id: state for state
|
self._states = {state.entity_id: state for state
|
||||||
in get_states(self._api, self.logger)}
|
in get_states(self._api)}
|
||||||
|
|
||||||
def _state_changed_listener(self, event):
|
def _state_changed_listener(self, event):
|
||||||
""" Listens for state changed events and applies them. """
|
""" Listens for state changed events and applies them. """
|
||||||
|
@ -298,7 +297,7 @@ def disconnect_remote_events(from_api, to_api):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def get_event_listeners(api, logger=None):
|
def get_event_listeners(api):
|
||||||
""" List of events that is being listened for. """
|
""" List of events that is being listened for. """
|
||||||
try:
|
try:
|
||||||
req = api(METHOD_GET, URL_API_EVENTS)
|
req = api(METHOD_GET, URL_API_EVENTS)
|
||||||
|
@ -307,28 +306,26 @@ def get_event_listeners(api, logger=None):
|
||||||
|
|
||||||
except (ha.HomeAssistantError, ValueError):
|
except (ha.HomeAssistantError, ValueError):
|
||||||
# ValueError if req.json() can't parse the json
|
# ValueError if req.json() can't parse the json
|
||||||
if logger:
|
_LOGGER.exception("Unexpected result retrieving event listeners")
|
||||||
logger.exception("Bus:Got unexpected result")
|
|
||||||
|
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def fire_event(api, event_type, data=None, logger=None):
|
def fire_event(api, event_type, data=None):
|
||||||
""" Fire an event at remote API. """
|
""" Fire an event at remote API. """
|
||||||
|
|
||||||
try:
|
try:
|
||||||
req = api(METHOD_POST, URL_API_EVENTS_EVENT.format(event_type), data)
|
req = api(METHOD_POST, URL_API_EVENTS_EVENT.format(event_type), data)
|
||||||
|
|
||||||
if req.status_code != 200 and logger:
|
if req.status_code != 200:
|
||||||
logger.error(
|
_LOGGER.error("Error firing event: %d - %d",
|
||||||
"Error firing event: {} - {}".format(
|
req.status_code, req.text)
|
||||||
req.status_code, req.text))
|
|
||||||
|
|
||||||
except ha.HomeAssistantError:
|
except ha.HomeAssistantError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
def get_state(api, entity_id, logger=None):
|
def get_state(api, entity_id):
|
||||||
""" Queries given API for state of entity_id. """
|
""" Queries given API for state of entity_id. """
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -342,13 +339,12 @@ def get_state(api, entity_id, logger=None):
|
||||||
|
|
||||||
except (ha.HomeAssistantError, ValueError):
|
except (ha.HomeAssistantError, ValueError):
|
||||||
# ValueError if req.json() can't parse the json
|
# ValueError if req.json() can't parse the json
|
||||||
if logger:
|
_LOGGER.exception("Error fetching state")
|
||||||
logger.exception("Error getting state")
|
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def get_states(api, logger=None):
|
def get_states(api):
|
||||||
""" Queries given API for all states. """
|
""" Queries given API for all states. """
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -360,13 +356,12 @@ def get_states(api, logger=None):
|
||||||
|
|
||||||
except (ha.HomeAssistantError, ValueError, AttributeError):
|
except (ha.HomeAssistantError, ValueError, AttributeError):
|
||||||
# ValueError if req.json() can't parse the json
|
# ValueError if req.json() can't parse the json
|
||||||
if logger:
|
_LOGGER.exception("Error fetching states")
|
||||||
logger.exception("Error getting state")
|
|
||||||
|
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def set_state(api, entity_id, new_state, attributes=None, logger=None):
|
def set_state(api, entity_id, new_state, attributes=None):
|
||||||
""" Tells API to update state for entity_id. """
|
""" Tells API to update state for entity_id. """
|
||||||
|
|
||||||
attributes = attributes or {}
|
attributes = attributes or {}
|
||||||
|
@ -379,24 +374,22 @@ def set_state(api, entity_id, new_state, attributes=None, logger=None):
|
||||||
URL_API_STATES_ENTITY.format(entity_id),
|
URL_API_STATES_ENTITY.format(entity_id),
|
||||||
data)
|
data)
|
||||||
|
|
||||||
if req.status_code != 201 and logger:
|
if req.status_code != 201:
|
||||||
logger.error(
|
_LOGGER.error("Error changing state: %d - %s",
|
||||||
"Error changing state: {} - {}".format(
|
req.status_code, req.text)
|
||||||
req.status_code, req.text))
|
|
||||||
|
|
||||||
except ha.HomeAssistantError:
|
except ha.HomeAssistantError:
|
||||||
if logger:
|
_LOGGER.exception("Error setting state")
|
||||||
logger.exception("Error setting state to server")
|
|
||||||
|
|
||||||
|
|
||||||
def is_state(api, entity_id, state, logger=None):
|
def is_state(api, entity_id, state):
|
||||||
""" Queries API to see if entity_id is specified state. """
|
""" Queries API to see if entity_id is specified state. """
|
||||||
cur_state = get_state(api, entity_id, logger)
|
cur_state = get_state(api, entity_id)
|
||||||
|
|
||||||
return cur_state and cur_state.state == state
|
return cur_state and cur_state.state == state
|
||||||
|
|
||||||
|
|
||||||
def get_services(api, logger=None):
|
def get_services(api):
|
||||||
"""
|
"""
|
||||||
Returns a list of dicts. Each dict has a string "domain" and
|
Returns a list of dicts. Each dict has a string "domain" and
|
||||||
a list of strings "services".
|
a list of strings "services".
|
||||||
|
@ -408,24 +401,21 @@ def get_services(api, logger=None):
|
||||||
|
|
||||||
except (ha.HomeAssistantError, ValueError):
|
except (ha.HomeAssistantError, ValueError):
|
||||||
# ValueError if req.json() can't parse the json
|
# ValueError if req.json() can't parse the json
|
||||||
if logger:
|
_LOGGER.exception("Got unexpected services result")
|
||||||
logger.exception("ServiceRegistry:Got unexpected result")
|
|
||||||
|
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
|
|
||||||
def call_service(api, domain, service, service_data=None, logger=None):
|
def call_service(api, domain, service, service_data=None):
|
||||||
""" Calls a service at the remote API. """
|
""" Calls a service at the remote API. """
|
||||||
try:
|
try:
|
||||||
req = api(METHOD_POST,
|
req = api(METHOD_POST,
|
||||||
URL_API_SERVICES_SERVICE.format(domain, service),
|
URL_API_SERVICES_SERVICE.format(domain, service),
|
||||||
service_data)
|
service_data)
|
||||||
|
|
||||||
if req.status_code != 200 and logger:
|
if req.status_code != 200:
|
||||||
logger.error(
|
_LOGGER.error("Error calling service: %d - %s",
|
||||||
"Error calling service: {} - {}".format(
|
req.status_code, req.text)
|
||||||
req.status_code, req.text))
|
|
||||||
|
|
||||||
except ha.HomeAssistantError:
|
except ha.HomeAssistantError:
|
||||||
if logger:
|
_LOGGER.exception("Error calling service")
|
||||||
logger.exception("Error setting state to server")
|
|
||||||
|
|
|
@ -238,7 +238,8 @@ class ThreadPool(object):
|
||||||
self.work_queue.put(PriorityQueueItem(priority, job))
|
self.work_queue.put(PriorityQueueItem(priority, job))
|
||||||
|
|
||||||
# check if our queue is getting too big
|
# check if our queue is getting too big
|
||||||
if self.work_queue.qsize() > self.busy_warning_limit:
|
if self.work_queue.qsize() > self.busy_warning_limit \
|
||||||
|
and self.busy_callback is not None:
|
||||||
|
|
||||||
# Increase limit we will issue next warning
|
# Increase limit we will issue next warning
|
||||||
self.busy_warning_limit *= 2
|
self.busy_warning_limit *= 2
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue