Logging is more efficient

This commit is contained in:
Paulus Schoutsen 2014-11-08 13:57:08 -08:00
parent c3c1383ae6
commit 1e136a2416
15 changed files with 136 additions and 158 deletions

View file

@ -50,6 +50,8 @@ POOL_NUM_THREAD = 4
# Pattern for validating entity IDs (format: <domain>.<entity>)
ENTITY_ID_PATTERN = re.compile(r"^(?P<domain>\w+)\.(?P<entity>\w+)$")
_LOGGER = logging.getLogger(__name__)
class HomeAssistant(object):
""" 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):
""" Creates a worker pool to be used. """
logger = logging.getLogger(__name__)
def job_handler(job):
""" 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
# Catch any exception our service/event_listener might throw
# 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):
""" Callback to be called when the pool queue gets too big. """
log_error = logger.error
log_error(
"WorkerPool:All {} threads are busy and {} jobs pending".format(
thread_count, pending_jobs_count))
_LOGGER.error(
"WorkerPool:All %d threads are busy and %d jobs pending",
thread_count, pending_jobs_count)
for start, job in current_jobs:
log_error("WorkerPool:Current job from {}: {}".format(
util.datetime_to_str(start), job))
_LOGGER.error("WorkerPool:Current job from %s: %s",
util.datetime_to_str(start), job)
return util.ThreadPool(thread_count, job_handler, busy_callback)
@ -323,7 +323,6 @@ class EventBus(object):
def __init__(self, pool=None):
self._listeners = {}
self._logger = logging.getLogger(__name__)
self._lock = threading.Lock()
self._pool = pool or create_worker_pool()
@ -347,7 +346,7 @@ class EventBus(object):
event = Event(event_type, event_data, origin)
self._logger.info("Bus:Handling {}".format(event))
_LOGGER.info("Bus:Handling %s", event)
if not listeners:
return
@ -602,7 +601,7 @@ class Timer(threading.Thread):
def run(self):
""" Start the timer. """
logging.getLogger(__name__).info("Timer:starting")
_LOGGER.info("Timer:starting")
last_fired_on_second = -1

View file

@ -117,8 +117,8 @@ def from_config_dict(config, hass=None):
if dep not in validated]
logger.error(
"Could not validate all dependencies for {}: {}".format(
domain, ", ".join(missing_deps)))
"Could not validate all dependencies for %s: %s",
domain, ", ".join(missing_deps))
break
@ -139,14 +139,12 @@ def from_config_dict(config, hass=None):
try:
if component.setup(hass, config):
logger.info("component {} initialized".format(domain))
logger.info("component %s initialized", domain)
else:
logger.error(
"component {} failed to initialize".format(domain))
logger.error("component %s failed to initialize", domain)
except Exception: # pylint: disable=broad-except
logger.exception(
"Error during setup of component {}".format(domain))
logger.exception("Error during setup of component %s", domain)
else:
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_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 \
(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:
logging.getLogger(__name__).error(
"Unable to setup error log {} (access denied)".format(
err_log_path))
"Unable to setup error log %s (access denied)", err_log_path)
# Read config
config = configparser.ConfigParser()

View file

@ -48,7 +48,7 @@ SERVICE_MEDIA_PAUSE = "media_pause"
SERVICE_MEDIA_NEXT_TRACK = "media_next_track"
SERVICE_MEDIA_PREV_TRACK = "media_prev_track"
__LOGGER = logging.getLogger(__name__)
_LOGGER = logging.getLogger(__name__)
def is_on(hass, entity_id=None):
@ -72,7 +72,8 @@ def is_on(hass, entity_id=None):
except AttributeError:
# 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
@ -123,6 +124,9 @@ def setup(hass, config):
# Generic turn on/off method requires entity id
if not entity_ids:
_LOGGER.error(
"homeassistant/%s cannot be called without entity_id",
service.service)
return
# Group entity_ids by domain. groupby requires sorted data.

View file

@ -21,7 +21,7 @@ def setup(hass, config):
hass.services.register(DOMAIN, SERVICE_BROWSE_URL,
lambda service:
webbrowser.open(
service.data.get('url',
'https://www.google.com')))
service.data.get(
'url', 'https://www.google.com')))
return True

View file

@ -118,11 +118,9 @@ def setup(hass, config):
if light_needed:
logger.info(
"Home coming event for {}. Turning lights on".
format(entity))
"Home coming event for %s. Turning lights on", entity)
light.turn_on(hass, light_ids,
profile=light_profile)
light.turn_on(hass, light_ids, profile=light_profile)
# Are we in the time span were we would turn on the lights
# if someone would be home?

View file

@ -43,6 +43,8 @@ KNOWN_DEVICES_FILE = "known_devices.csv"
CONF_HTTP_ID = "http_id"
_LOGGER = logging.getLogger(__name__)
def is_on(hass, entity_id=None):
""" Returns if any or specified device is home. """
@ -54,17 +56,15 @@ def is_on(hass, entity_id=None):
def setup(hass, config):
""" Sets up the device tracker. """
logger = logging.getLogger(__name__)
# We have flexible requirements for device tracker so
# we cannot use util.validate_config
conf = config[DOMAIN]
if ha.CONF_TYPE not in conf:
logger.error(
'Missing required configuration item in {}: {}'.format(
DOMAIN, ha.CONF_TYPE))
_LOGGER.error(
'Missing required configuration item in %s: %s',
DOMAIN, ha.CONF_TYPE)
return False
@ -84,18 +84,18 @@ def setup(hass, config):
scanner = LuciDeviceScanner
else:
logger.error('Found unknown router type {}'.format(router_type))
_LOGGER.error('Found unknown router type %s', router_type)
return False
if not util.validate_config(config, {DOMAIN: fields}, logger):
if not util.validate_config(config, {DOMAIN: fields}, _LOGGER):
return False
device_scanner = scanner(conf)
if not device_scanner.success_init:
logger.error(
"Failed to initialize device scanner for {}".format(router_type))
_LOGGER.error("Failed to initialize device scanner for %s",
router_type)
return False
@ -115,8 +115,6 @@ class DeviceTracker(object):
self.error_scanning = TIME_SPAN_FOR_ERROR_IN_SCANNING
self.logger = logging.getLogger(__name__)
self.lock = threading.Lock()
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)
with open(known_dev_path, 'a') as outp:
self.logger.info((
"DeviceTracker:Found {} new devices,"
_LOGGER.info((
"Found {} new devices,"
" updating {}").format(len(unknown_devices),
known_dev_path))
@ -228,8 +226,8 @@ class DeviceTracker(object):
'picture': ""}
except IOError:
self.logger.exception((
"DeviceTracker:Error updating {}"
_LOGGER.exception((
"Error updating {}"
"with {} new devices").format(known_dev_path,
len(unknown_devices)))
@ -292,9 +290,9 @@ class DeviceTracker(object):
known_devices[device] = row
if not known_devices:
self.logger.warning(
"No devices to track. Please update {}.".format(
self.path_known_devices_file))
_LOGGER.warning(
"No devices to track. Please update %s.",
self.path_known_devices_file)
# Remove entities that are no longer maintained
new_entity_ids = set([known_devices[device]['entity_id']
@ -304,25 +302,22 @@ class DeviceTracker(object):
for entity_id in \
self.device_entity_ids - new_entity_ids:
self.logger.info(
"DeviceTracker:Removing entity {}".format(
entity_id))
_LOGGER.info("Removing entity %s", entity_id)
self.states.remove(entity_id)
# File parsed, warnings given if necessary
# entities cleaned up, make it available
self.known_devices = known_devices
self.logger.info(
"DeviceTracker:Loaded devices from {}".format(
self.path_known_devices_file))
_LOGGER.info("Loaded devices from %s",
self.path_known_devices_file)
except KeyError:
self.invalid_known_devices_file = True
self.logger.warning((
"Invalid known devices file: {}. "
"We won't update it with new found devices."
).format(self.path_known_devices_file))
_LOGGER.warning(
("Invalid known devices file: %s. "
"We won't update it with new found devices."),
self.path_known_devices_file)
finally:
self.lock.release()
@ -349,7 +344,7 @@ class TomatoDeviceScanner(object):
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.date_updated = None
@ -390,7 +385,7 @@ class TomatoDeviceScanner(object):
if not self.date_updated or \
datetime.now() - self.date_updated > MIN_TIME_BETWEEN_SCANS:
self.logger.info("Tomato:Scanning")
self.logger.info("Scanning")
try:
response = requests.Session().send(self.req, timeout=3)
@ -415,7 +410,7 @@ class TomatoDeviceScanner(object):
elif response.status_code == 401:
# Authentication error
self.logger.exception((
"Tomato:Failed to authenticate, "
"Failed to authenticate, "
"please check your username and password"))
return False
@ -424,7 +419,7 @@ class TomatoDeviceScanner(object):
# We get this if we could not connect to the router or
# an invalid http_id was supplied
self.logger.exception((
"Tomato:Failed to connect to the router"
"Failed to connect to the router"
" or invalid http_id supplied"))
return False
@ -433,14 +428,14 @@ class TomatoDeviceScanner(object):
# We get this if we could not connect to the router or
# an invalid http_id was supplied
self.logger.exception(
"Tomato:Connection to the router timed out")
"Connection to the router timed out")
return False
except ValueError:
# If json decoder could not parse the response
self.logger.exception(
"Tomato:Failed to parse response from router")
"Failed to parse response from router")
return False
@ -462,15 +457,17 @@ class NetgearDeviceScanner(object):
host = config['host']
username, password = config['username'], config['password']
self.logger = logging.getLogger(__name__)
self.logger = logging.getLogger("{}.{}".format(__name__, "Netgear"))
self.date_updated = None
self.last_results = []
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
except ImportError:
self.logger.exception(
("Netgear:Failed to import pynetgear. "
("Failed to import pynetgear. "
"Did you maybe not run `git submodule init` "
"and `git submodule update`?"))
@ -481,7 +478,7 @@ class NetgearDeviceScanner(object):
self._api = pynetgear.Netgear(host, username, password)
self.lock = threading.Lock()
self.logger.info("Netgear:Logging in")
self.logger.info("Logging in")
if self._api.login():
self.success_init = True
self._update_info()
@ -526,7 +523,7 @@ class NetgearDeviceScanner(object):
if not self.date_updated or \
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()
@ -557,7 +554,7 @@ class LuciDeviceScanner(object):
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.date_updated = None
@ -596,7 +593,7 @@ class LuciDeviceScanner(object):
"please check your username and password")
return
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):
""" Get authentication token for the given host+username+password """

View file

@ -44,15 +44,15 @@ def setup(hass, config):
if not os.path.isdir(download_path):
logger.error(
"Download path {} does not exist. File Downloader not active.".
format(download_path))
"Download path %s does not exist. File Downloader not active.",
download_path)
return False
def download_file(service):
""" 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.")
return
@ -114,18 +114,16 @@ def setup(hass, config):
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:
for chunk in req.iter_content(1024):
fil.write(chunk)
logger.info("Downloading of {} done".format(
url))
logger.info("Downloading of %s done", url)
except requests.exceptions.ConnectionError:
logger.exception("ConnectionError occured for {}".
format(url))
logger.exception("ConnectionError occured for %s", url)
# Remove file if we started downloading but failed
if final_path and os.path.isfile(final_path):

View file

@ -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
several states. Supports ON/OFF and DEVICE_HOME/DEVICE_NOT_HOME. """
logger = logging.getLogger(__name__)
# In case an iterable is passed in
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
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))
# 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))
if errors:
logger.error("Error setting up group {}: {}".format(
name, ", ".join(errors)))
logging.getLogger(__name__).error(
"Error setting up group %s: %s", name, ", ".join(errors))
return False

View file

@ -110,12 +110,14 @@ CONF_SERVER_HOST = "server_host"
CONF_SERVER_PORT = "server_port"
CONF_DEVELOPMENT = "development"
_LOGGER = logging.getLogger(__name__)
def setup(hass, config):
""" Sets up the HTTP API and debug interface. """
if not util.validate_config(config, {DOMAIN: [CONF_API_PASSWORD]},
logging.getLogger(__name__)):
_LOGGER):
return False
api_password = config[DOMAIN]['api_password']
@ -156,22 +158,17 @@ class HomeAssistantHTTPServer(ThreadingMixIn, HTTPServer):
self.hass = hass
self.api_password = api_password
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
self.event_forwarder = None
if development:
self.logger.info("running frontend in development mode")
_LOGGER.info("running frontend in development mode")
def start(self):
""" Starts the server. """
self.logger.info(
"Web interface starting at http://{}:{}".format(
*self.server_address))
_LOGGER.info(
"Starting web interface at http://%s:%d", *self.server_address)
self.serve_forever()
@ -256,8 +253,8 @@ class RequestHandler(SimpleHTTPRequestHandler):
try:
data.update(json.loads(body_content))
except ValueError:
self.server.logger.exception(
"Exception parsing JSON: {}".format(body_content))
_LOGGER.exception("Exception parsing JSON: %s",
body_content)
self._message(
"Error parsing JSON", HTTP_UNPROCESSABLE_ENTITY)
@ -598,9 +595,6 @@ class RequestHandler(SimpleHTTPRequestHandler):
""" Helper method to return a message to the caller. """
if self.use_json:
self._write_json({'message': message}, status_code=status_code)
elif status_code == HTTP_OK:
self.server.flash_message = message
self._redirect('/')
else:
self.send_error(status_code, message)

View file

@ -153,7 +153,7 @@ def setup(hass, config):
light_init = HueLightControl
else:
logger.error("Found unknown light type: {}".format(light_type))
logger.error("Unknown light type specified: %s", light_type)
return False
@ -172,7 +172,7 @@ def setup(hass, config):
# We have not seen this light before, set it up
# 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_FORMAT.format(util.slugify(name)),
@ -251,8 +251,7 @@ def setup(hass, config):
# ValueError if not 4 values per row
# ValueError if convert to float/int failed
logger.error(
"Error parsing light profiles from {}".format(
profile_path))
"Error parsing light profiles from %s", profile_path)
return False
@ -357,15 +356,16 @@ class HueLightControl(object):
""" Class to interface with the Hue light system. """
def __init__(self, hass, config):
logger = logging.getLogger(__name__)
logger = logging.getLogger("{}.{}".format(__name__, "HueLightControl"))
host = config.get(ha.CONF_HOST, None)
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
except ImportError:
logger.exception(
"HueLightControl:Error while importing dependency phue.")
logger.exception("Error while importing dependency phue.")
self.success_init = False
@ -377,8 +377,8 @@ class HueLightControl(object):
PHUE_CONFIG_FILE))
except socket.error: # Error connecting using Phue
logger.exception((
"HueLightControl:Error while connecting to the bridge. "
"Is phue registered?"))
"Error while connecting to the bridge. "
"Did you follow the instructions to set it up?"))
self.success_init = False
@ -389,7 +389,7 @@ class HueLightControl(object):
self._update_lights()
if len(self._lights) == 0:
logger.error("HueLightControl:Could not find any lights. ")
logger.error("Could not find any lights. ")
self.success_init = False
else:
@ -409,7 +409,7 @@ class HueLightControl(object):
def get_name(self, light_id):
""" 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()
return self._lights.get(light_id)

View file

@ -91,9 +91,8 @@ def setup(hass, config):
new_state = STATE_BELOW_HORIZON
next_change = next_rising_dt
logger.info(
"{}. Next change: {}".format(new_state,
next_change.strftime("%H:%M")))
logger.info("%s. Next change: %s",
new_state, next_change.strftime("%H:%M"))
state_attributes = {
STATE_ATTR_NEXT_RISING: util.datetime_to_str(next_rising_dt),

View file

@ -54,6 +54,8 @@ def setup(hass, config):
logger = logging.getLogger(__name__)
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
except ImportError:
logger.exception((

View file

@ -63,7 +63,7 @@ def get_component(comp_name):
if path in AVAILABLE_COMPONENTS]
if not potential_paths:
_LOGGER.error("Failed to find component {}".format(comp_name))
_LOGGER.error("Failed to find component %s", comp_name)
return None
@ -71,15 +71,14 @@ def get_component(comp_name):
comp = _get_component(path)
if comp is not None:
_LOGGER.info("Loaded component {} from {}".format(
comp_name, path))
_LOGGER.info("Loaded component %s from %s", comp_name, path)
_COMPONENT_CACHE[comp_name] = comp
return comp
# 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
@ -91,8 +90,8 @@ def _get_component(module):
comp = importlib.import_module(module)
except ImportError:
_LOGGER.exception(("Error loading {}. Make sure all "
"dependencies are installed").format(module))
_LOGGER.exception(("Error loading %s. Make sure all "
"dependencies are installed"), module)
return None
@ -109,8 +108,8 @@ def _get_component(module):
errors.append("missing setup method")
if errors:
_LOGGER.error("Found invalid component {}: {}".format(
module, ", ".join(errors)))
_LOGGER.error("Found invalid component %s: %s",
module, ", ".join(errors))
return None

View file

@ -35,6 +35,8 @@ URL_API_EVENT_FORWARD = "/api/event_forwarding"
METHOD_GET = "get"
METHOD_POST = "post"
_LOGGER = logging.getLogger(__name__)
# pylint: disable=no-init, invalid-name
class APIStatus(enum.Enum):
@ -84,12 +86,12 @@ class API(object):
method, url, data=data, timeout=5, headers=self._headers)
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")
except requests.exceptions.Timeout:
error = "Timeout when talking to {}".format(self.host)
logging.getLogger(__name__).exception(error)
_LOGGER.exception(error)
raise ha.HomeAssistantError(error)
@ -159,7 +161,6 @@ class EventForwarder(object):
def __init__(self, hass, restrict_origin=None):
self.hass = hass
self.restrict_origin = restrict_origin
self.logger = logging.getLogger(__name__)
# We use a tuple (host, port) as key to ensure
# that we do not forward to the same host twice
@ -205,7 +206,7 @@ class EventForwarder(object):
return
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):
@ -217,8 +218,6 @@ class StateMachine(ha.StateMachine):
def __init__(self, bus, api):
super().__init__(None)
self.logger = logging.getLogger(__name__)
self._api = api
self.mirror()
@ -232,7 +231,7 @@ class StateMachine(ha.StateMachine):
def mirror(self):
""" Discards current data and mirrors the remote state machine. """
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):
""" Listens for state changed events and applies them. """
@ -298,7 +297,7 @@ def disconnect_remote_events(from_api, to_api):
pass
def get_event_listeners(api, logger=None):
def get_event_listeners(api):
""" List of events that is being listened for. """
try:
req = api(METHOD_GET, URL_API_EVENTS)
@ -307,28 +306,26 @@ def get_event_listeners(api, logger=None):
except (ha.HomeAssistantError, ValueError):
# ValueError if req.json() can't parse the json
if logger:
logger.exception("Bus:Got unexpected result")
_LOGGER.exception("Unexpected result retrieving event listeners")
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. """
try:
req = api(METHOD_POST, URL_API_EVENTS_EVENT.format(event_type), data)
if req.status_code != 200 and logger:
logger.error(
"Error firing event: {} - {}".format(
req.status_code, req.text))
if req.status_code != 200:
_LOGGER.error("Error firing event: %d - %d",
req.status_code, req.text)
except ha.HomeAssistantError:
pass
def get_state(api, entity_id, logger=None):
def get_state(api, entity_id):
""" Queries given API for state of entity_id. """
try:
@ -342,13 +339,12 @@ def get_state(api, entity_id, logger=None):
except (ha.HomeAssistantError, ValueError):
# ValueError if req.json() can't parse the json
if logger:
logger.exception("Error getting state")
_LOGGER.exception("Error fetching state")
return None
def get_states(api, logger=None):
def get_states(api):
""" Queries given API for all states. """
try:
@ -360,13 +356,12 @@ def get_states(api, logger=None):
except (ha.HomeAssistantError, ValueError, AttributeError):
# ValueError if req.json() can't parse the json
if logger:
logger.exception("Error getting state")
_LOGGER.exception("Error fetching states")
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. """
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),
data)
if req.status_code != 201 and logger:
logger.error(
"Error changing state: {} - {}".format(
req.status_code, req.text))
if req.status_code != 201:
_LOGGER.error("Error changing state: %d - %s",
req.status_code, req.text)
except ha.HomeAssistantError:
if logger:
logger.exception("Error setting state to server")
_LOGGER.exception("Error setting state")
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. """
cur_state = get_state(api, entity_id, logger)
cur_state = get_state(api, entity_id)
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
a list of strings "services".
@ -408,24 +401,21 @@ def get_services(api, logger=None):
except (ha.HomeAssistantError, ValueError):
# ValueError if req.json() can't parse the json
if logger:
logger.exception("ServiceRegistry:Got unexpected result")
_LOGGER.exception("Got unexpected services result")
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. """
try:
req = api(METHOD_POST,
URL_API_SERVICES_SERVICE.format(domain, service),
service_data)
if req.status_code != 200 and logger:
logger.error(
"Error calling service: {} - {}".format(
req.status_code, req.text))
if req.status_code != 200:
_LOGGER.error("Error calling service: %d - %s",
req.status_code, req.text)
except ha.HomeAssistantError:
if logger:
logger.exception("Error setting state to server")
_LOGGER.exception("Error calling service")

View file

@ -238,7 +238,8 @@ class ThreadPool(object):
self.work_queue.put(PriorityQueueItem(priority, job))
# 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
self.busy_warning_limit *= 2