Moved stuff away from core. Made component interface more uniform.
This commit is contained in:
parent
b387f9d9d7
commit
0fc3d359cb
13 changed files with 302 additions and 158 deletions
|
@ -20,16 +20,9 @@ MATCH_ALL = '*'
|
||||||
|
|
||||||
DOMAIN = "homeassistant"
|
DOMAIN = "homeassistant"
|
||||||
|
|
||||||
STATE_ON = "on"
|
|
||||||
STATE_OFF = "off"
|
|
||||||
STATE_NOT_HOME = 'device_not_home'
|
|
||||||
STATE_HOME = 'device_home'
|
|
||||||
|
|
||||||
SERVICE_TURN_ON = "turn_on"
|
|
||||||
SERVICE_TURN_OFF = "turn_off"
|
|
||||||
SERVICE_HOMEASSISTANT_STOP = "stop"
|
SERVICE_HOMEASSISTANT_STOP = "stop"
|
||||||
|
|
||||||
EVENT_HOMEASSISTANT_START = "homeassistant.start"
|
EVENT_HOMEASSISTANT_START = "homeassistant_start"
|
||||||
EVENT_STATE_CHANGED = "state_changed"
|
EVENT_STATE_CHANGED = "state_changed"
|
||||||
EVENT_TIME_CHANGED = "time_changed"
|
EVENT_TIME_CHANGED = "time_changed"
|
||||||
|
|
||||||
|
@ -78,21 +71,6 @@ def _matcher(subject, pattern):
|
||||||
return MATCH_ALL == pattern or subject in pattern
|
return MATCH_ALL == pattern or subject in pattern
|
||||||
|
|
||||||
|
|
||||||
def split_entity_id(entity_id):
|
|
||||||
""" Splits a state entity_id into domain, object_id. """
|
|
||||||
return entity_id.split(".", 1)
|
|
||||||
|
|
||||||
|
|
||||||
def filter_entity_ids(entity_ids, domain_filter=None, strip_domain=False):
|
|
||||||
""" Filter a list of entities based on domain. Setting strip_domain
|
|
||||||
will only return the object_ids. """
|
|
||||||
return [
|
|
||||||
split_entity_id(entity_id)[1] if strip_domain else entity_id
|
|
||||||
for entity_id in entity_ids if
|
|
||||||
not domain_filter or entity_id.startswith(domain_filter)
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def track_state_change(bus, entity_id, action, from_state=None, to_state=None):
|
def track_state_change(bus, entity_id, action, from_state=None, to_state=None):
|
||||||
""" Helper method to track specific state changes. """
|
""" Helper method to track specific state changes. """
|
||||||
from_state = _process_match_param(from_state)
|
from_state = _process_match_param(from_state)
|
||||||
|
|
|
@ -134,7 +134,7 @@ def from_config_file(config_path):
|
||||||
add_status("Downloader", downloader.setup(
|
add_status("Downloader", downloader.setup(
|
||||||
bus, get_opt("downloader", "download_dir")))
|
bus, get_opt("downloader", "download_dir")))
|
||||||
|
|
||||||
add_status("General", general.setup(bus, statemachine))
|
add_status("General", general.setup(bus))
|
||||||
|
|
||||||
if has_section('browser'):
|
if has_section('browser'):
|
||||||
add_status("Browser", load_module('browser').setup(bus))
|
add_status("Browser", load_module('browser').setup(bus))
|
||||||
|
|
|
@ -6,46 +6,46 @@ Provides functionality to interact with Chromecasts.
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
from homeassistant.external import pychromecast
|
|
||||||
|
|
||||||
import homeassistant as ha
|
import homeassistant as ha
|
||||||
import homeassistant.util as util
|
import homeassistant.util as util
|
||||||
|
from homeassistant.components import general
|
||||||
|
|
||||||
|
DOMAIN = 'chromecast'
|
||||||
|
|
||||||
DOMAIN = "chromecast"
|
SERVICE_YOUTUBE_VIDEO = 'play_youtube_video'
|
||||||
|
|
||||||
SERVICE_YOUTUBE_VIDEO = "play_youtube_video"
|
|
||||||
|
|
||||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||||
STATE_NO_APP = "none"
|
STATE_NO_APP = 'no_app'
|
||||||
|
|
||||||
ATTR_FRIENDLY_NAME = "friendly_name"
|
ATTR_FRIENDLY_NAME = 'friendly_name'
|
||||||
ATTR_HOST = "host"
|
ATTR_HOST = 'host'
|
||||||
ATTR_STATE = "state"
|
ATTR_STATE = 'state'
|
||||||
ATTR_OPTIONS = "options"
|
ATTR_OPTIONS = 'options'
|
||||||
|
|
||||||
|
|
||||||
def turn_off(statemachine, cc_id=None):
|
def is_on(statemachine, entity_id=None):
|
||||||
""" Exits any running app on the specified ChromeCast and shows
|
""" Returns true if specified ChromeCast entity_id is on.
|
||||||
idle screen. Will quit all ChromeCasts if nothing specified. """
|
Will check all chromecasts if no entity_id specified. """
|
||||||
|
|
||||||
entity_ids = [ENTITY_ID_FORMAT.format(cc_id)] if cc_id \
|
entity_ids = [entity_id] if entity_id \
|
||||||
else ha.filter_entity_ids(statemachine.entity_ids, DOMAIN)
|
else util.filter_entity_ids(statemachine.entity_ids, DOMAIN)
|
||||||
|
|
||||||
for entity_id in entity_ids:
|
return any(not statemachine.is_state(entity_id, STATE_NO_APP)
|
||||||
state = statemachine.get_state(entity_id)
|
for entity_id in entity_ids)
|
||||||
|
|
||||||
if (state and
|
|
||||||
(state.state != STATE_NO_APP or
|
|
||||||
state.state != pychromecast.APP_ID_HOME)):
|
|
||||||
|
|
||||||
pychromecast.quit_app(state.attributes[ATTR_HOST])
|
|
||||||
|
|
||||||
|
|
||||||
def setup(bus, statemachine, host):
|
def setup(bus, statemachine, host):
|
||||||
""" Listen for chromecast events. """
|
""" Listen for chromecast events. """
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
try:
|
||||||
|
from homeassistant.external import pychromecast
|
||||||
|
except ImportError:
|
||||||
|
logger.exception(("Failed to import pychromecast. "
|
||||||
|
"Did you maybe not cloned the git submodules?"))
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
logger.info("Getting device status")
|
logger.info("Getting device status")
|
||||||
device = pychromecast.get_device_status(host)
|
device = pychromecast.get_device_status(host)
|
||||||
|
|
||||||
|
@ -53,13 +53,30 @@ def setup(bus, statemachine, host):
|
||||||
logger.error("Could not find Chromecast")
|
logger.error("Could not find Chromecast")
|
||||||
return False
|
return False
|
||||||
|
|
||||||
entity = ENTITY_ID_FORMAT.format(util.slugify(
|
entity = ENTITY_ID_FORMAT.format(util.slugify(device.friendly_name))
|
||||||
device.friendly_name))
|
|
||||||
|
|
||||||
bus.register_service(DOMAIN, ha.SERVICE_TURN_OFF,
|
if not bus.has_service(DOMAIN, general.SERVICE_TURN_OFF):
|
||||||
lambda service:
|
def _turn_off_service(service):
|
||||||
turn_off(statemachine,
|
""" Service to exit any running app on the specified ChromeCast and
|
||||||
service.data.get("cc_id", None)))
|
shows idle screen. Will quit all ChromeCasts if nothing specified.
|
||||||
|
"""
|
||||||
|
entity_id = service.data.get(general.ATTR_ENTITY_ID)
|
||||||
|
|
||||||
|
entity_ids = [entity_id] if entity_id \
|
||||||
|
else util.filter_entity_ids(statemachine.entity_ids, DOMAIN)
|
||||||
|
|
||||||
|
for entity_id in entity_ids:
|
||||||
|
state = statemachine.get_state(entity_id)
|
||||||
|
|
||||||
|
try:
|
||||||
|
pychromecast.quit_app(state.attributes[ATTR_HOST])
|
||||||
|
except (AttributeError, KeyError):
|
||||||
|
# AttributeError: state returned None
|
||||||
|
# KeyError: ATTR_HOST did not exist
|
||||||
|
pass
|
||||||
|
|
||||||
|
bus.register_service(DOMAIN, general.SERVICE_TURN_OFF,
|
||||||
|
_turn_off_service)
|
||||||
|
|
||||||
bus.register_service(DOMAIN, "start_fireplace",
|
bus.register_service(DOMAIN, "start_fireplace",
|
||||||
lambda service:
|
lambda service:
|
||||||
|
@ -74,7 +91,7 @@ def setup(bus, statemachine, host):
|
||||||
pychromecast.play_youtube_video(
|
pychromecast.play_youtube_video(
|
||||||
host, service.data['video']))
|
host, service.data['video']))
|
||||||
|
|
||||||
def update_chromecast_state(time): # pylint: disable=unused-argument
|
def _update_chromecast_state(time): # pylint: disable=unused-argument
|
||||||
""" Retrieve state of Chromecast and update statemachine. """
|
""" Retrieve state of Chromecast and update statemachine. """
|
||||||
logger.info("Updating app status")
|
logger.info("Updating app status")
|
||||||
status = pychromecast.get_app_status(host)
|
status = pychromecast.get_app_status(host)
|
||||||
|
@ -92,8 +109,8 @@ def setup(bus, statemachine, host):
|
||||||
else:
|
else:
|
||||||
statemachine.set_state(entity, STATE_NO_APP, {ATTR_HOST: host})
|
statemachine.set_state(entity, STATE_NO_APP, {ATTR_HOST: host})
|
||||||
|
|
||||||
ha.track_time_change(bus, update_chromecast_state)
|
ha.track_time_change(bus, _update_chromecast_state)
|
||||||
|
|
||||||
update_chromecast_state(None)
|
_update_chromecast_state(None)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -9,6 +9,7 @@ import logging
|
||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
import homeassistant as ha
|
import homeassistant as ha
|
||||||
|
import homeassistant.util as util
|
||||||
|
|
||||||
from . import light, sun, device_tracker, general, group
|
from . import light, sun, device_tracker, general, group
|
||||||
|
|
||||||
|
@ -22,7 +23,7 @@ def setup(bus, statemachine, light_group=None):
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
device_entity_ids = ha.filter_entity_ids(statemachine.entity_ids,
|
device_entity_ids = util.filter_entity_ids(statemachine.entity_ids,
|
||||||
device_tracker.DOMAIN)
|
device_tracker.DOMAIN)
|
||||||
|
|
||||||
if not device_entity_ids:
|
if not device_entity_ids:
|
||||||
|
@ -33,7 +34,7 @@ def setup(bus, statemachine, light_group=None):
|
||||||
light_group = light_group or light.GROUP_NAME_ALL_LIGHTS
|
light_group = light_group or light.GROUP_NAME_ALL_LIGHTS
|
||||||
|
|
||||||
# Get the light IDs from the specified group
|
# Get the light IDs from the specified group
|
||||||
light_ids = ha.filter_entity_ids(
|
light_ids = util.filter_entity_ids(
|
||||||
group.get_entity_ids(statemachine, light_group), light.DOMAIN)
|
group.get_entity_ids(statemachine, light_group), light.DOMAIN)
|
||||||
|
|
||||||
if not light_ids:
|
if not light_ids:
|
||||||
|
@ -55,7 +56,7 @@ def setup(bus, statemachine, light_group=None):
|
||||||
def turn_light_on_before_sunset(light_id):
|
def turn_light_on_before_sunset(light_id):
|
||||||
""" Helper function to turn on lights slowly if there
|
""" Helper function to turn on lights slowly if there
|
||||||
are devices home and the light is not on yet. """
|
are devices home and the light is not on yet. """
|
||||||
if (device_tracker.is_home(statemachine) and
|
if (device_tracker.is_on(statemachine) and
|
||||||
not light.is_on(statemachine, light_id)):
|
not light.is_on(statemachine, light_id)):
|
||||||
|
|
||||||
light.turn_on(bus, light_id, LIGHT_TRANSITION_TIME.seconds)
|
light.turn_on(bus, light_id, LIGHT_TRANSITION_TIME.seconds)
|
||||||
|
@ -80,18 +81,18 @@ def setup(bus, statemachine, light_group=None):
|
||||||
|
|
||||||
# If the sun is already above horizon
|
# If the sun is already above horizon
|
||||||
# schedule the time-based pre-sun set event
|
# schedule the time-based pre-sun set event
|
||||||
if sun.is_up(statemachine):
|
if sun.is_on(statemachine):
|
||||||
handle_sun_rising(None, None, None)
|
handle_sun_rising(None, None, None)
|
||||||
|
|
||||||
def handle_device_state_change(entity, old_state, new_state):
|
def _handle_device_state_change(entity, old_state, new_state):
|
||||||
""" Function to handle tracked device state changes. """
|
""" Function to handle tracked device state changes. """
|
||||||
lights_are_on = group.is_on(statemachine, light_group)
|
lights_are_on = group.is_on(statemachine, light_group)
|
||||||
|
|
||||||
light_needed = not (lights_are_on or sun.is_up(statemachine))
|
light_needed = not (lights_are_on or sun.is_on(statemachine))
|
||||||
|
|
||||||
# Specific device came home ?
|
# Specific device came home ?
|
||||||
if (entity != device_tracker.ENTITY_ID_ALL_DEVICES and
|
if (entity != device_tracker.ENTITY_ID_ALL_DEVICES and
|
||||||
new_state.state == ha.STATE_HOME):
|
new_state.state == general.STATE_HOME):
|
||||||
|
|
||||||
# These variables are needed for the elif check
|
# These variables are needed for the elif check
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
|
@ -104,6 +105,8 @@ def setup(bus, statemachine, light_group=None):
|
||||||
"Home coming event for {}. Turning lights on".
|
"Home coming event for {}. Turning lights on".
|
||||||
format(entity))
|
format(entity))
|
||||||
|
|
||||||
|
# Turn on lights directly instead of calling group.turn_on
|
||||||
|
# So we skip fetching the entity ids again.
|
||||||
for light_id in light_ids:
|
for light_id in light_ids:
|
||||||
light.turn_on(bus, light_id)
|
light.turn_on(bus, light_id)
|
||||||
|
|
||||||
|
@ -127,21 +130,21 @@ def setup(bus, statemachine, light_group=None):
|
||||||
|
|
||||||
# Did all devices leave the house?
|
# Did all devices leave the house?
|
||||||
elif (entity == device_tracker.ENTITY_ID_ALL_DEVICES and
|
elif (entity == device_tracker.ENTITY_ID_ALL_DEVICES and
|
||||||
new_state.state == ha.STATE_NOT_HOME and lights_are_on):
|
new_state.state == general.STATE_NOT_HOME and lights_are_on):
|
||||||
|
|
||||||
logger.info(
|
logger.info(
|
||||||
"Everyone has left but there are devices on. Turning them off")
|
"Everyone has left but there are devices on. Turning them off")
|
||||||
|
|
||||||
general.shutdown_devices(bus, statemachine)
|
light.turn_off(bus, statemachine)
|
||||||
|
|
||||||
# Track home coming of each seperate device
|
# Track home coming of each seperate device
|
||||||
for entity in device_entity_ids:
|
for entity in device_entity_ids:
|
||||||
ha.track_state_change(bus, entity, handle_device_state_change,
|
ha.track_state_change(bus, entity, _handle_device_state_change,
|
||||||
ha.STATE_NOT_HOME, ha.STATE_HOME)
|
general.STATE_NOT_HOME, general.STATE_HOME)
|
||||||
|
|
||||||
# Track when all devices are gone to shut down lights
|
# Track when all devices are gone to shut down lights
|
||||||
ha.track_state_change(bus, device_tracker.ENTITY_ID_ALL_DEVICES,
|
ha.track_state_change(bus, device_tracker.ENTITY_ID_ALL_DEVICES,
|
||||||
handle_device_state_change, ha.STATE_HOME,
|
_handle_device_state_change, general.STATE_HOME,
|
||||||
ha.STATE_NOT_HOME)
|
general.STATE_NOT_HOME)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -16,9 +16,7 @@ import requests
|
||||||
|
|
||||||
import homeassistant as ha
|
import homeassistant as ha
|
||||||
import homeassistant.util as util
|
import homeassistant.util as util
|
||||||
import homeassistant.components.group as group
|
from homeassistant.components import general, group
|
||||||
|
|
||||||
import homeassistant.external.pynetgear as pynetgear
|
|
||||||
|
|
||||||
DOMAIN = "device_tracker"
|
DOMAIN = "device_tracker"
|
||||||
|
|
||||||
|
@ -41,12 +39,11 @@ MIN_TIME_BETWEEN_SCANS = timedelta(seconds=5)
|
||||||
KNOWN_DEVICES_FILE = "known_devices.csv"
|
KNOWN_DEVICES_FILE = "known_devices.csv"
|
||||||
|
|
||||||
|
|
||||||
def is_home(statemachine, device_id=None):
|
def is_on(statemachine, entity_id=None):
|
||||||
""" Returns if any or specified device is home. """
|
""" Returns if any or specified device is home. """
|
||||||
entity = ENTITY_ID_FORMAT.format(device_id) if device_id \
|
entity = entity_id or ENTITY_ID_ALL_DEVICES
|
||||||
else ENTITY_ID_ALL_DEVICES
|
|
||||||
|
|
||||||
return statemachine.is_state(entity, ha.STATE_HOME)
|
return statemachine.is_state(entity, general.STATE_HOME)
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-many-instance-attributes
|
# pylint: disable=too-many-instance-attributes
|
||||||
|
@ -100,30 +97,30 @@ class DeviceTracker(object):
|
||||||
|
|
||||||
now = datetime.now()
|
now = datetime.now()
|
||||||
|
|
||||||
temp_tracking_devices = [device for device in self.known_devices
|
known_dev = self.known_devices
|
||||||
if self.known_devices[device]['track']]
|
|
||||||
|
temp_tracking_devices = [device for device in known_dev
|
||||||
|
if known_dev[device]['track']]
|
||||||
|
|
||||||
for device in found_devices:
|
for device in found_devices:
|
||||||
# Are we tracking this device?
|
# Are we tracking this device?
|
||||||
if device in temp_tracking_devices:
|
if device in temp_tracking_devices:
|
||||||
temp_tracking_devices.remove(device)
|
temp_tracking_devices.remove(device)
|
||||||
|
|
||||||
self.known_devices[device]['last_seen'] = now
|
known_dev[device]['last_seen'] = now
|
||||||
|
|
||||||
self.statemachine.set_state(
|
self.statemachine.set_state(
|
||||||
self.known_devices[device]['entity_id'], ha.STATE_HOME)
|
known_dev[device]['entity_id'], general.STATE_HOME)
|
||||||
|
|
||||||
# For all devices we did not find, set state to NH
|
# For all devices we did not find, set state to NH
|
||||||
# But only if they have been gone for longer then the error time span
|
# But only if they have been gone for longer then the error time span
|
||||||
# Because we do not want to have stuff happening when the device does
|
# Because we do not want to have stuff happening when the device does
|
||||||
# not show up for 1 scan beacuse of reboot etc
|
# not show up for 1 scan beacuse of reboot etc
|
||||||
for device in temp_tracking_devices:
|
for device in temp_tracking_devices:
|
||||||
if (now - self.known_devices[device]['last_seen'] >
|
if (now - known_dev[device]['last_seen'] > self.error_scanning):
|
||||||
self.error_scanning):
|
|
||||||
|
|
||||||
self.statemachine.set_state(
|
self.statemachine.set_state(known_dev[device]['entity_id'],
|
||||||
self.known_devices[device]['entity_id'],
|
general.STATE_NOT_HOME)
|
||||||
ha.STATE_NOT_HOME)
|
|
||||||
|
|
||||||
# If we come along any unknown devices we will write them to the
|
# If we come along any unknown devices we will write them to the
|
||||||
# known devices file but only if we did not encounter an invalid
|
# known devices file but only if we did not encounter an invalid
|
||||||
|
@ -131,7 +128,7 @@ class DeviceTracker(object):
|
||||||
if not self.invalid_known_devices_file:
|
if not self.invalid_known_devices_file:
|
||||||
|
|
||||||
unknown_devices = [device for device in found_devices
|
unknown_devices = [device for device in found_devices
|
||||||
if device not in self.known_devices]
|
if device not in known_dev]
|
||||||
|
|
||||||
if unknown_devices:
|
if unknown_devices:
|
||||||
try:
|
try:
|
||||||
|
@ -151,13 +148,12 @@ class DeviceTracker(object):
|
||||||
|
|
||||||
for device in unknown_devices:
|
for device in unknown_devices:
|
||||||
# See if the device scanner knows the name
|
# See if the device scanner knows the name
|
||||||
temp_name = \
|
# else defaults to unknown device
|
||||||
self.device_scanner.get_device_name(device)
|
name = (self.device_scanner.get_device_name(device)
|
||||||
|
or "unknown_device")
|
||||||
name = temp_name if temp_name else "unknown_device"
|
|
||||||
|
|
||||||
writer.writerow((device, name, 0))
|
writer.writerow((device, name, 0))
|
||||||
self.known_devices[device] = {'name': name,
|
known_dev[device] = {'name': name,
|
||||||
'track': False}
|
'track': False}
|
||||||
|
|
||||||
except IOError:
|
except IOError:
|
||||||
|
@ -380,17 +376,28 @@ class NetgearDeviceScanner(object):
|
||||||
""" This class queries a Netgear wireless router using the SOAP-api. """
|
""" This class queries a Netgear wireless router using the SOAP-api. """
|
||||||
|
|
||||||
def __init__(self, host, username, password):
|
def __init__(self, host, username, password):
|
||||||
self._api = pynetgear.Netgear(host, username, password)
|
|
||||||
|
|
||||||
self.logger = logging.getLogger(__name__)
|
self.logger = logging.getLogger(__name__)
|
||||||
self.lock = threading.Lock()
|
|
||||||
|
|
||||||
self.date_updated = None
|
self.date_updated = None
|
||||||
self.last_results = []
|
self.last_results = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
import homeassistant.external.pynetgear as pynetgear
|
||||||
|
except ImportError:
|
||||||
|
self.logger.exception(
|
||||||
|
("Netgear:Failed to import pynetgear. "
|
||||||
|
"Did you maybe not cloned the git submodules?"))
|
||||||
|
|
||||||
|
self.success_init = False
|
||||||
|
|
||||||
|
return
|
||||||
|
|
||||||
|
self._api = pynetgear.Netgear(host, username, password)
|
||||||
|
self.lock = threading.Lock()
|
||||||
|
|
||||||
self.logger.info("Netgear:Logging in")
|
self.logger.info("Netgear:Logging in")
|
||||||
if self._api.login():
|
if self._api.login():
|
||||||
self.success_init = self._update_info()
|
self.success_init = True
|
||||||
|
self._update_info()
|
||||||
|
|
||||||
else:
|
else:
|
||||||
self.logger.error("Netgear:Failed to Login")
|
self.logger.error("Netgear:Failed to Login")
|
||||||
|
@ -423,6 +430,8 @@ class NetgearDeviceScanner(object):
|
||||||
def _update_info(self):
|
def _update_info(self):
|
||||||
""" Retrieves latest information from the Netgear router.
|
""" Retrieves latest information from the Netgear router.
|
||||||
Returns boolean if scanning successful. """
|
Returns boolean if scanning successful. """
|
||||||
|
if not self.success_init:
|
||||||
|
return
|
||||||
|
|
||||||
with self.lock:
|
with self.lock:
|
||||||
# if date_updated is None or the date is too old we scan for
|
# if date_updated is None or the date is too old we scan for
|
||||||
|
@ -436,7 +445,7 @@ class NetgearDeviceScanner(object):
|
||||||
|
|
||||||
self.date_updated = datetime.now()
|
self.date_updated = datetime.now()
|
||||||
|
|
||||||
return True
|
return
|
||||||
|
|
||||||
else:
|
else:
|
||||||
return True
|
return
|
||||||
|
|
|
@ -31,7 +31,7 @@ def setup(bus, download_path):
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def download_file(service):
|
def _download_file(service):
|
||||||
""" Downloads file specified in the url. """
|
""" Downloads file specified in the url. """
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
@ -78,6 +78,6 @@ def setup(bus, download_path):
|
||||||
format(service.data['url']))
|
format(service.data['url']))
|
||||||
|
|
||||||
bus.register_service(DOMAIN, SERVICE_DOWNLOAD_FILE,
|
bus.register_service(DOMAIN, SERVICE_DOWNLOAD_FILE,
|
||||||
download_file)
|
_download_file)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -4,23 +4,100 @@ homeassistant.components.general
|
||||||
|
|
||||||
This component contains a service to shut down all devices.
|
This component contains a service to shut down all devices.
|
||||||
"""
|
"""
|
||||||
|
import importlib
|
||||||
|
|
||||||
import homeassistant as ha
|
import homeassistant as ha
|
||||||
from . import chromecast, light
|
import homeassistant.util as util
|
||||||
|
|
||||||
SERVICE_SHUTDOWN_DEVICES = "shutdown_devices"
|
ATTR_ENTITY_ID = 'entity_id'
|
||||||
|
|
||||||
|
STATE_ON = "on"
|
||||||
|
STATE_OFF = "off"
|
||||||
|
STATE_NOT_HOME = 'device_not_home'
|
||||||
|
STATE_HOME = 'device_home'
|
||||||
|
|
||||||
|
SERVICE_TURN_ON = "turn_on"
|
||||||
|
SERVICE_TURN_OFF = "turn_off"
|
||||||
|
|
||||||
|
_LOADED_MOD = {}
|
||||||
|
|
||||||
|
|
||||||
def shutdown_devices(bus, statemachine):
|
def _get_module(module):
|
||||||
""" Tries to shutdown all devices that are currently on. """
|
""" Helper function to load a module. """
|
||||||
chromecast.turn_off(statemachine)
|
try:
|
||||||
light.turn_off(bus)
|
return _LOADED_MOD[module]
|
||||||
|
|
||||||
|
except KeyError:
|
||||||
|
# if module key did not exist in loaded dict
|
||||||
|
try:
|
||||||
|
module = _LOADED_MOD[module] = importlib.import_module(
|
||||||
|
'homeassistant.components.'+module)
|
||||||
|
|
||||||
|
return module
|
||||||
|
|
||||||
|
except ImportError:
|
||||||
|
# If module does not exist
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
def setup(bus, statemachine):
|
def is_on(statemachine, entity_id=None):
|
||||||
""" Setup services related to homeassistant. """
|
""" Loads up the module to call the turn_on method.
|
||||||
|
If there is no entity id given we will check all. """
|
||||||
|
entity_ids = [entity_id] if entity_id else statemachine.entity_ids
|
||||||
|
|
||||||
bus.register_service(ha.DOMAIN, SERVICE_SHUTDOWN_DEVICES,
|
for entity_id in entity_ids:
|
||||||
lambda service: shutdown_devices(bus, statemachine))
|
domain = util.split_entity_id(entity_id)[0]
|
||||||
|
|
||||||
|
try:
|
||||||
|
if _get_module(domain).is_on(statemachine, entity_id):
|
||||||
|
return True
|
||||||
|
|
||||||
|
except AttributeError:
|
||||||
|
# method is_on does not exist within module
|
||||||
|
pass
|
||||||
|
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def turn_on(bus, entity_id=None):
|
||||||
|
""" Turns specified entity on if possible. """
|
||||||
|
# If there is no entity_id we do not know which domain to call.
|
||||||
|
if not entity_id:
|
||||||
|
return
|
||||||
|
|
||||||
|
domain = util.split_entity_id(entity_id)[0]
|
||||||
|
|
||||||
|
try:
|
||||||
|
bus.call_service(domain, SERVICE_TURN_ON, {ATTR_ENTITY_ID: entity_id})
|
||||||
|
except ha.ServiceDoesNotExistError:
|
||||||
|
# turn_on service does not exist
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def turn_off(bus, entity_id=None):
|
||||||
|
""" Turns specified entity off. """
|
||||||
|
# If there is no entity_id we do not know which domain to call.
|
||||||
|
if not entity_id:
|
||||||
|
return
|
||||||
|
|
||||||
|
domain = util.split_entity_id(entity_id)[0]
|
||||||
|
|
||||||
|
try:
|
||||||
|
bus.call_service(domain, SERVICE_TURN_OFF, {ATTR_ENTITY_ID: entity_id})
|
||||||
|
except ha.ServiceDoesNotExistError:
|
||||||
|
# turn_off service does not exist
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
def setup(bus):
|
||||||
|
""" Setup general services related to homeassistant. """
|
||||||
|
|
||||||
|
bus.register_service(ha.DOMAIN, SERVICE_TURN_OFF,
|
||||||
|
lambda service:
|
||||||
|
turn_off(bus, service.data.get(ATTR_ENTITY_ID)))
|
||||||
|
|
||||||
|
bus.register_service(ha.DOMAIN, SERVICE_TURN_ON,
|
||||||
|
lambda service:
|
||||||
|
turn_on(bus, service.data.get(ATTR_ENTITY_ID)))
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -8,6 +8,7 @@ Provides functionality to group devices that can be turned on or off.
|
||||||
import logging
|
import logging
|
||||||
|
|
||||||
import homeassistant as ha
|
import homeassistant as ha
|
||||||
|
from homeassistant.components import general as gen
|
||||||
|
|
||||||
DOMAIN = "group"
|
DOMAIN = "group"
|
||||||
|
|
||||||
|
@ -16,8 +17,8 @@ ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
||||||
STATE_ATTR_ENTITY_IDS = "entity_ids"
|
STATE_ATTR_ENTITY_IDS = "entity_ids"
|
||||||
|
|
||||||
_GROUP_TYPES = {
|
_GROUP_TYPES = {
|
||||||
"on_off": (ha.STATE_ON, ha.STATE_OFF),
|
"on_off": (gen.STATE_ON, gen.STATE_OFF),
|
||||||
"home_not_home": (ha.STATE_HOME, ha.STATE_NOT_HOME)
|
"home_not_home": (gen.STATE_HOME, gen.STATE_NOT_HOME)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -30,9 +31,9 @@ def _get_group_type(state):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
def is_on(statemachine, group):
|
def is_on(statemachine, entity_id):
|
||||||
""" Returns if the group state is in its ON-state. """
|
""" Returns if the group state is in its ON-state. """
|
||||||
state = statemachine.get_state(group)
|
state = statemachine.get_state(entity_id)
|
||||||
|
|
||||||
if state:
|
if state:
|
||||||
group_type = _get_group_type(state.state)
|
group_type = _get_group_type(state.state)
|
||||||
|
@ -46,17 +47,18 @@ def is_on(statemachine, group):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def get_entity_ids(statemachine, group):
|
def get_entity_ids(statemachine, entity_id):
|
||||||
""" Get the entity ids that make up this group. """
|
""" Get the entity ids that make up this group. """
|
||||||
try:
|
try:
|
||||||
return statemachine.get_state(group).attributes[STATE_ATTR_ENTITY_IDS]
|
return \
|
||||||
|
statemachine.get_state(entity_id).attributes[STATE_ATTR_ENTITY_IDS]
|
||||||
except (AttributeError, KeyError):
|
except (AttributeError, KeyError):
|
||||||
# AttributeError if state did not exist
|
# AttributeError if state did not exist
|
||||||
# KeyError if key did not exist in attributes
|
# KeyError if key did not exist in attributes
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-many-branches
|
# pylint: disable=too-many-branches, too-many-locals
|
||||||
def setup(bus, statemachine, name, entity_ids):
|
def setup(bus, statemachine, name, entity_ids):
|
||||||
""" 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. """
|
||||||
|
@ -136,6 +138,33 @@ def setup(bus, statemachine, name, entity_ids):
|
||||||
for entity_id in entity_ids:
|
for entity_id in entity_ids:
|
||||||
ha.track_state_change(bus, entity_id, _update_group_state)
|
ha.track_state_change(bus, entity_id, _update_group_state)
|
||||||
|
|
||||||
|
# group.setup is called to setup each group. Only the first time will we
|
||||||
|
# register a turn_on and turn_off method for groups.
|
||||||
|
|
||||||
|
if not bus.has_service(DOMAIN, gen.SERVICE_TURN_ON):
|
||||||
|
def _turn_group_on_service(service):
|
||||||
|
""" Call general.turn_on for each entity_id from this group. """
|
||||||
|
for entity_id in get_entity_ids(statemachine,
|
||||||
|
service.data.get(
|
||||||
|
gen.ATTR_ENTITY_ID)):
|
||||||
|
|
||||||
|
gen.turn_on(bus, entity_id)
|
||||||
|
|
||||||
|
bus.register_service(DOMAIN, gen.SERVICE_TURN_ON,
|
||||||
|
_turn_group_on_service)
|
||||||
|
|
||||||
|
if not bus.has_service(DOMAIN, gen.SERVICE_TURN_OFF):
|
||||||
|
def _turn_group_off_service(service):
|
||||||
|
""" Call general.turn_off for each entity_id from this group. """
|
||||||
|
for entity_id in get_entity_ids(statemachine,
|
||||||
|
service.data.get(
|
||||||
|
gen.ATTR_ENTITY_ID)):
|
||||||
|
|
||||||
|
gen.turn_off(bus, entity_id)
|
||||||
|
|
||||||
|
bus.register_service(DOMAIN, gen.SERVICE_TURN_OFF,
|
||||||
|
_turn_group_off_service)
|
||||||
|
|
||||||
statemachine.set_state(group_entity_id, group_state, state_attr)
|
statemachine.set_state(group_entity_id, group_state, state_attr)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -592,6 +592,10 @@ class RequestHandler(BaseHTTPRequestHandler):
|
||||||
|
|
||||||
self._message("Service {}/{} called.".format(domain, service))
|
self._message("Service {}/{} called.".format(domain, service))
|
||||||
|
|
||||||
|
except ha.ServiceDoesNotExistError:
|
||||||
|
# If the service does not exist
|
||||||
|
self._message('Service does not exist', HTTP_BAD_REQUEST)
|
||||||
|
|
||||||
except KeyError:
|
except KeyError:
|
||||||
# Occurs if domain or service does not exist in data
|
# Occurs if domain or service does not exist in data
|
||||||
self._message("No domain or service received.", HTTP_BAD_REQUEST)
|
self._message("No domain or service received.", HTTP_BAD_REQUEST)
|
||||||
|
|
|
@ -10,7 +10,7 @@ from datetime import datetime, timedelta
|
||||||
|
|
||||||
import homeassistant as ha
|
import homeassistant as ha
|
||||||
import homeassistant.util as util
|
import homeassistant.util as util
|
||||||
import homeassistant.components.group as group
|
from homeassistant.components import general, group
|
||||||
|
|
||||||
DOMAIN = "light"
|
DOMAIN = "light"
|
||||||
|
|
||||||
|
@ -27,33 +27,35 @@ def is_on(statemachine, entity_id=None):
|
||||||
""" Returns if the lights are on based on the statemachine. """
|
""" Returns if the lights are on based on the statemachine. """
|
||||||
entity_id = entity_id or ENTITY_ID_ALL_LIGHTS
|
entity_id = entity_id or ENTITY_ID_ALL_LIGHTS
|
||||||
|
|
||||||
return statemachine.is_state(entity_id, ha.STATE_ON)
|
return statemachine.is_state(entity_id, general.STATE_ON)
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=unused-argument
|
||||||
def turn_on(bus, entity_id=None, transition_seconds=None):
|
def turn_on(bus, entity_id=None, transition_seconds=None):
|
||||||
""" Turns all or specified light on. """
|
""" Turns all or specified light on. """
|
||||||
data = {}
|
data = {}
|
||||||
|
|
||||||
if entity_id:
|
if entity_id:
|
||||||
data["light_id"] = ha.split_entity_id(entity_id)[1]
|
data[general.ATTR_ENTITY_ID] = entity_id
|
||||||
|
|
||||||
if transition_seconds:
|
if transition_seconds:
|
||||||
data["transition_seconds"] = transition_seconds
|
data["transition_seconds"] = transition_seconds
|
||||||
|
|
||||||
bus.call_service(DOMAIN, ha.SERVICE_TURN_ON, data)
|
bus.call_service(DOMAIN, general.SERVICE_TURN_ON, data)
|
||||||
|
|
||||||
|
|
||||||
|
# pylint: disable=unused-argument
|
||||||
def turn_off(bus, entity_id=None, transition_seconds=None):
|
def turn_off(bus, entity_id=None, transition_seconds=None):
|
||||||
""" Turns all or specified light off. """
|
""" Turns all or specified light off. """
|
||||||
data = {}
|
data = {}
|
||||||
|
|
||||||
if entity_id:
|
if entity_id:
|
||||||
data["light_id"] = ha.split_entity_id(entity_id)[1]
|
data[general.ATTR_ENTITY_ID] = entity_id
|
||||||
|
|
||||||
if transition_seconds:
|
if transition_seconds:
|
||||||
data["transition_seconds"] = transition_seconds
|
data["transition_seconds"] = transition_seconds
|
||||||
|
|
||||||
bus.call_service(DOMAIN, ha.SERVICE_TURN_OFF, data)
|
bus.call_service(DOMAIN, general.SERVICE_TURN_OFF, data)
|
||||||
|
|
||||||
|
|
||||||
def setup(bus, statemachine, light_control):
|
def setup(bus, statemachine, light_control):
|
||||||
|
@ -61,6 +63,13 @@ def setup(bus, statemachine, light_control):
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
entity_ids = {light_id: ENTITY_ID_FORMAT.format(light_id) for light_id
|
||||||
|
in light_control.light_ids}
|
||||||
|
|
||||||
|
if not entity_ids:
|
||||||
|
logger.error("Light:Found no lights to track")
|
||||||
|
return
|
||||||
|
|
||||||
def update_light_state(time): # pylint: disable=unused-argument
|
def update_light_state(time): # pylint: disable=unused-argument
|
||||||
""" Track the state of the lights. """
|
""" Track the state of the lights. """
|
||||||
try:
|
try:
|
||||||
|
@ -79,39 +88,36 @@ def setup(bus, statemachine, light_control):
|
||||||
for light_id in light_control.light_ids}
|
for light_id in light_control.light_ids}
|
||||||
|
|
||||||
for light_id, state in status.items():
|
for light_id, state in status.items():
|
||||||
entity_id = ENTITY_ID_FORMAT.format(light_id)
|
new_state = general.STATE_ON if state else general.STATE_OFF
|
||||||
|
|
||||||
new_state = ha.STATE_ON if state else ha.STATE_OFF
|
statemachine.set_state(entity_ids[light_id], new_state)
|
||||||
|
|
||||||
statemachine.set_state(entity_id, new_state)
|
|
||||||
|
|
||||||
ha.track_time_change(bus, update_light_state, second=[0, 30])
|
ha.track_time_change(bus, update_light_state, second=[0, 30])
|
||||||
|
|
||||||
update_light_state(None)
|
update_light_state(None)
|
||||||
|
|
||||||
# Track the all lights state
|
# Track the all lights state
|
||||||
entity_ids = [ENTITY_ID_FORMAT.format(light_id) for light_id
|
group.setup(bus, statemachine, GROUP_NAME_ALL_LIGHTS, entity_ids.values())
|
||||||
in light_control.light_ids]
|
|
||||||
|
|
||||||
group.setup(bus, statemachine, GROUP_NAME_ALL_LIGHTS, entity_ids)
|
|
||||||
|
|
||||||
def handle_light_service(service):
|
def handle_light_service(service):
|
||||||
""" Hande a turn light on or off service call. """
|
""" Hande a turn light on or off service call. """
|
||||||
light_id = service.data.get("light_id", None)
|
entity_id = service.data.get(general.ATTR_ENTITY_ID, None)
|
||||||
transition_seconds = service.data.get("transition_seconds", None)
|
transition_seconds = service.data.get("transition_seconds", None)
|
||||||
|
|
||||||
if service.service == ha.SERVICE_TURN_ON:
|
object_id = util.split_entity_id(entity_id)[1] if entity_id else None
|
||||||
light_control.turn_light_on(light_id, transition_seconds)
|
|
||||||
|
if service.service == general.SERVICE_TURN_ON:
|
||||||
|
light_control.turn_light_on(object_id, transition_seconds)
|
||||||
else:
|
else:
|
||||||
light_control.turn_light_off(light_id, transition_seconds)
|
light_control.turn_light_off(object_id, transition_seconds)
|
||||||
|
|
||||||
update_light_state(None)
|
update_light_state(None)
|
||||||
|
|
||||||
# Listen for light on and light off events
|
# Listen for light on and light off events
|
||||||
bus.register_service(DOMAIN, ha.SERVICE_TURN_ON,
|
bus.register_service(DOMAIN, general.SERVICE_TURN_ON,
|
||||||
handle_light_service)
|
handle_light_service)
|
||||||
|
|
||||||
bus.register_service(DOMAIN, ha.SERVICE_TURN_OFF,
|
bus.register_service(DOMAIN, general.SERVICE_TURN_OFF,
|
||||||
handle_light_service)
|
handle_light_service)
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
|
@ -10,7 +10,7 @@ from datetime import timedelta
|
||||||
import homeassistant as ha
|
import homeassistant as ha
|
||||||
import homeassistant.util as util
|
import homeassistant.util as util
|
||||||
|
|
||||||
ENTITY_ID = "weather.sun"
|
ENTITY_ID = "sun.sun"
|
||||||
|
|
||||||
STATE_ABOVE_HORIZON = "above_horizon"
|
STATE_ABOVE_HORIZON = "above_horizon"
|
||||||
STATE_BELOW_HORIZON = "below_horizon"
|
STATE_BELOW_HORIZON = "below_horizon"
|
||||||
|
@ -19,9 +19,11 @@ STATE_ATTR_NEXT_RISING = "next_rising"
|
||||||
STATE_ATTR_NEXT_SETTING = "next_setting"
|
STATE_ATTR_NEXT_SETTING = "next_setting"
|
||||||
|
|
||||||
|
|
||||||
def is_up(statemachine):
|
def is_on(statemachine, entity_id=None):
|
||||||
""" Returns if the sun is currently up based on the statemachine. """
|
""" Returns if the sun is currently up based on the statemachine. """
|
||||||
return statemachine.is_state(ENTITY_ID, STATE_ABOVE_HORIZON)
|
entity_id = entity_id or ENTITY_ID
|
||||||
|
|
||||||
|
return statemachine.is_state(entity_id, STATE_ABOVE_HORIZON)
|
||||||
|
|
||||||
|
|
||||||
def next_setting(statemachine):
|
def next_setting(statemachine):
|
||||||
|
|
|
@ -6,7 +6,7 @@ A module containing drop in replacements for core parts that will interface
|
||||||
with a remote instance of home assistant.
|
with a remote instance of home assistant.
|
||||||
|
|
||||||
If a connection error occurs while communicating with the API a
|
If a connection error occurs while communicating with the API a
|
||||||
HomeAssistantException will be raised.
|
HomeAssistantError will be raised.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import threading
|
import threading
|
||||||
|
@ -44,7 +44,7 @@ def _setup_call_api(host, port, api_password):
|
||||||
|
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
logging.getLogger(__name__).exception("Error connecting to server")
|
logging.getLogger(__name__).exception("Error connecting to server")
|
||||||
raise ha.HomeAssistantException("Error connecting to server")
|
raise ha.HomeAssistantError("Error connecting to server")
|
||||||
|
|
||||||
return _call_api
|
return _call_api
|
||||||
|
|
||||||
|
@ -85,17 +85,17 @@ class Bus(ha.Bus):
|
||||||
return data['services']
|
return data['services']
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ha.HomeAssistantException(
|
raise ha.HomeAssistantError(
|
||||||
"Got unexpected result (3): {}.".format(req.text))
|
"Got unexpected result (3): {}.".format(req.text))
|
||||||
|
|
||||||
except ValueError: # If req.json() can't parse the json
|
except ValueError: # If req.json() can't parse the json
|
||||||
self.logger.exception("Bus:Got unexpected result")
|
self.logger.exception("Bus:Got unexpected result")
|
||||||
raise ha.HomeAssistantException(
|
raise ha.HomeAssistantError(
|
||||||
"Got unexpected result: {}".format(req.text))
|
"Got unexpected result: {}".format(req.text))
|
||||||
|
|
||||||
except KeyError: # If not all expected keys are in the returned JSON
|
except KeyError: # If not all expected keys are in the returned JSON
|
||||||
self.logger.exception("Bus:Got unexpected result (2)")
|
self.logger.exception("Bus:Got unexpected result (2)")
|
||||||
raise ha.HomeAssistantException(
|
raise ha.HomeAssistantError(
|
||||||
"Got unexpected result (2): {}".format(req.text))
|
"Got unexpected result (2): {}".format(req.text))
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
@ -110,17 +110,17 @@ class Bus(ha.Bus):
|
||||||
return data['event_listeners']
|
return data['event_listeners']
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ha.HomeAssistantException(
|
raise ha.HomeAssistantError(
|
||||||
"Got unexpected result (3): {}.".format(req.text))
|
"Got unexpected result (3): {}.".format(req.text))
|
||||||
|
|
||||||
except ValueError: # If req.json() can't parse the json
|
except ValueError: # If req.json() can't parse the json
|
||||||
self.logger.exception("Bus:Got unexpected result")
|
self.logger.exception("Bus:Got unexpected result")
|
||||||
raise ha.HomeAssistantException(
|
raise ha.HomeAssistantError(
|
||||||
"Got unexpected result: {}".format(req.text))
|
"Got unexpected result: {}".format(req.text))
|
||||||
|
|
||||||
except KeyError: # If not all expected keys are in the returned JSON
|
except KeyError: # If not all expected keys are in the returned JSON
|
||||||
self.logger.exception("Bus:Got unexpected result (2)")
|
self.logger.exception("Bus:Got unexpected result (2)")
|
||||||
raise ha.HomeAssistantException(
|
raise ha.HomeAssistantError(
|
||||||
"Got unexpected result (2): {}".format(req.text))
|
"Got unexpected result (2): {}".format(req.text))
|
||||||
|
|
||||||
def call_service(self, domain, service, service_data=None):
|
def call_service(self, domain, service, service_data=None):
|
||||||
|
@ -141,7 +141,11 @@ class Bus(ha.Bus):
|
||||||
req.status_code, req.text)
|
req.status_code, req.text)
|
||||||
|
|
||||||
self.logger.error("Bus:{}".format(error))
|
self.logger.error("Bus:{}".format(error))
|
||||||
raise ha.HomeAssistantException(error)
|
|
||||||
|
if req.status_code == 400:
|
||||||
|
raise ha.ServiceDoesNotExistError(error)
|
||||||
|
else:
|
||||||
|
raise ha.HomeAssistantError(error)
|
||||||
|
|
||||||
def register_service(self, domain, service, service_callback):
|
def register_service(self, domain, service, service_callback):
|
||||||
""" Not implemented for remote bus.
|
""" Not implemented for remote bus.
|
||||||
|
@ -166,7 +170,7 @@ class Bus(ha.Bus):
|
||||||
req.status_code, req.text)
|
req.status_code, req.text)
|
||||||
|
|
||||||
self.logger.error("Bus:{}".format(error))
|
self.logger.error("Bus:{}".format(error))
|
||||||
raise ha.HomeAssistantException(error)
|
raise ha.HomeAssistantError(error)
|
||||||
|
|
||||||
def listen_event(self, event_type, listener):
|
def listen_event(self, event_type, listener):
|
||||||
""" Not implemented for remote bus.
|
""" Not implemented for remote bus.
|
||||||
|
@ -251,11 +255,11 @@ class StateMachine(ha.StateMachine):
|
||||||
req.status_code, req.text)
|
req.status_code, req.text)
|
||||||
|
|
||||||
self.logger.error("StateMachine:{}".format(error))
|
self.logger.error("StateMachine:{}".format(error))
|
||||||
raise ha.HomeAssistantException(error)
|
raise ha.HomeAssistantError(error)
|
||||||
|
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
self.logger.exception("StateMachine:Error connecting to server")
|
self.logger.exception("StateMachine:Error connecting to server")
|
||||||
raise ha.HomeAssistantException("Error connecting to server")
|
raise ha.HomeAssistantError("Error connecting to server")
|
||||||
|
|
||||||
finally:
|
finally:
|
||||||
self.lock.release()
|
self.lock.release()
|
||||||
|
@ -277,19 +281,19 @@ class StateMachine(ha.StateMachine):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
else:
|
else:
|
||||||
raise ha.HomeAssistantException(
|
raise ha.HomeAssistantError(
|
||||||
"Got unexpected result (3): {}.".format(req.text))
|
"Got unexpected result (3): {}.".format(req.text))
|
||||||
|
|
||||||
except requests.exceptions.ConnectionError:
|
except requests.exceptions.ConnectionError:
|
||||||
self.logger.exception("StateMachine:Error connecting to server")
|
self.logger.exception("StateMachine:Error connecting to server")
|
||||||
raise ha.HomeAssistantException("Error connecting to server")
|
raise ha.HomeAssistantError("Error connecting to server")
|
||||||
|
|
||||||
except ValueError: # If req.json() can't parse the json
|
except ValueError: # If req.json() can't parse the json
|
||||||
self.logger.exception("StateMachine:Got unexpected result")
|
self.logger.exception("StateMachine:Got unexpected result")
|
||||||
raise ha.HomeAssistantException(
|
raise ha.HomeAssistantError(
|
||||||
"Got unexpected result: {}".format(req.text))
|
"Got unexpected result: {}".format(req.text))
|
||||||
|
|
||||||
except KeyError: # If not all expected keys are in the returned JSON
|
except KeyError: # If not all expected keys are in the returned JSON
|
||||||
self.logger.exception("StateMachine:Got unexpected result (2)")
|
self.logger.exception("StateMachine:Got unexpected result (2)")
|
||||||
raise ha.HomeAssistantException(
|
raise ha.HomeAssistantError(
|
||||||
"Got unexpected result (2): {}".format(req.text))
|
"Got unexpected result (2): {}".format(req.text))
|
||||||
|
|
|
@ -38,3 +38,18 @@ def str_to_datetime(dt_str):
|
||||||
return datetime.datetime.strptime(dt_str, DATE_STR_FORMAT)
|
return datetime.datetime.strptime(dt_str, DATE_STR_FORMAT)
|
||||||
except ValueError: # If dt_str did not match our format
|
except ValueError: # If dt_str did not match our format
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def split_entity_id(entity_id):
|
||||||
|
""" Splits a state entity_id into domain, object_id. """
|
||||||
|
return entity_id.split(".", 1)
|
||||||
|
|
||||||
|
|
||||||
|
def filter_entity_ids(entity_ids, domain_filter=None, strip_domain=False):
|
||||||
|
""" Filter a list of entities based on domain. Setting strip_domain
|
||||||
|
will only return the object_ids. """
|
||||||
|
return [
|
||||||
|
split_entity_id(entity_id)[1] if strip_domain else entity_id
|
||||||
|
for entity_id in entity_ids if
|
||||||
|
not domain_filter or entity_id.startswith(domain_filter)
|
||||||
|
]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue