diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 9369246b68e..7d41c3dbf56 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -7,7 +7,7 @@ import ConfigParser import logging import homeassistant as ha -from homeassistant.components import general +import homeassistant.components as components # pylint: disable=too-many-branches,too-many-locals,too-many-statements @@ -134,7 +134,7 @@ def from_config_file(config_path): add_status("Downloader", downloader.setup( bus, get_opt("downloader", "download_dir"))) - add_status("General", general.setup(bus)) + add_status("Core components", components.setup(bus)) if has_section('browser'): add_status("Browser", load_module('browser').setup(bus)) diff --git a/homeassistant/components/__init__.py b/homeassistant/components/__init__.py index 168823c7b0f..6e51235d812 100644 --- a/homeassistant/components/__init__.py +++ b/homeassistant/components/__init__.py @@ -14,3 +14,101 @@ format ".". Each component should publish services only under its own domain. """ + +import importlib + +import homeassistant as ha +import homeassistant.util as util + +ATTR_ENTITY_ID = 'entity_id' + +STATE_ON = 'on' +STATE_OFF = 'off' +STATE_NOT_HOME = 'not_home' +STATE_HOME = 'home' + +SERVICE_TURN_ON = 'turn_on' +SERVICE_TURN_OFF = 'turn_off' + +_LOADED_MOD = {} + + +def _get_module(module): + """ Helper function to load a module. """ + try: + 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 is_on(statemachine, entity_id=None): + """ Loads up the module to call the is_on method. + If there is no entity id given we will check all. """ + entity_ids = [entity_id] if entity_id else statemachine.entity_ids + + for entity_id in entity_ids: + 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 diff --git a/homeassistant/components/chromecast.py b/homeassistant/components/chromecast.py index 018f2deae06..54fd8223cd1 100644 --- a/homeassistant/components/chromecast.py +++ b/homeassistant/components/chromecast.py @@ -8,7 +8,7 @@ import logging import homeassistant as ha import homeassistant.util as util -from homeassistant.components import general +import homeassistant.components as components DOMAIN = 'chromecast' @@ -55,12 +55,12 @@ def setup(bus, statemachine, host): entity = ENTITY_ID_FORMAT.format(util.slugify(device.friendly_name)) - if not bus.has_service(DOMAIN, general.SERVICE_TURN_OFF): + if not bus.has_service(DOMAIN, components.SERVICE_TURN_OFF): def _turn_off_service(service): """ Service to exit any running app on the specified ChromeCast and shows idle screen. Will quit all ChromeCasts if nothing specified. """ - entity_id = service.data.get(general.ATTR_ENTITY_ID) + entity_id = service.data.get(components.ATTR_ENTITY_ID) entity_ids = [entity_id] if entity_id \ else util.filter_entity_ids(statemachine.entity_ids, DOMAIN) @@ -75,7 +75,7 @@ def setup(bus, statemachine, host): # KeyError: ATTR_HOST did not exist pass - bus.register_service(DOMAIN, general.SERVICE_TURN_OFF, + bus.register_service(DOMAIN, components.SERVICE_TURN_OFF, _turn_off_service) bus.register_service(DOMAIN, "start_fireplace", diff --git a/homeassistant/components/device_sun_light_trigger.py b/homeassistant/components/device_sun_light_trigger.py index 6370d59b510..3d39fcda1a2 100644 --- a/homeassistant/components/device_sun_light_trigger.py +++ b/homeassistant/components/device_sun_light_trigger.py @@ -10,8 +10,8 @@ from datetime import datetime, timedelta import homeassistant as ha import homeassistant.util as util - -from . import light, sun, device_tracker, general, group +import homeassistant.components as components +from . import light, sun, device_tracker, group LIGHT_TRANSITION_TIME = timedelta(minutes=15) @@ -92,7 +92,7 @@ def setup(bus, statemachine, light_group=None): # Specific device came home ? if (entity != device_tracker.ENTITY_ID_ALL_DEVICES and - new_state.state == general.STATE_HOME): + new_state.state == components.STATE_HOME): # These variables are needed for the elif check now = datetime.now() @@ -130,7 +130,7 @@ def setup(bus, statemachine, light_group=None): # Did all devices leave the house? elif (entity == device_tracker.ENTITY_ID_ALL_DEVICES and - new_state.state == general.STATE_NOT_HOME and lights_are_on): + new_state.state == components.STATE_NOT_HOME and lights_are_on): logger.info( "Everyone has left but there are devices on. Turning them off") @@ -140,11 +140,11 @@ def setup(bus, statemachine, light_group=None): # Track home coming of each seperate device for entity in device_entity_ids: ha.track_state_change(bus, entity, _handle_device_state_change, - general.STATE_NOT_HOME, general.STATE_HOME) + components.STATE_NOT_HOME, components.STATE_HOME) # Track when all devices are gone to shut down lights ha.track_state_change(bus, device_tracker.ENTITY_ID_ALL_DEVICES, - _handle_device_state_change, general.STATE_HOME, - general.STATE_NOT_HOME) + _handle_device_state_change, components.STATE_HOME, + components.STATE_NOT_HOME) return True diff --git a/homeassistant/components/device_tracker.py b/homeassistant/components/device_tracker.py index e5de41933b4..e9e37582133 100644 --- a/homeassistant/components/device_tracker.py +++ b/homeassistant/components/device_tracker.py @@ -16,7 +16,9 @@ import requests import homeassistant as ha import homeassistant.util as util -from homeassistant.components import general, group +import homeassistant.components as components + +from homeassistant.components import group DOMAIN = "device_tracker" @@ -43,7 +45,7 @@ def is_on(statemachine, entity_id=None): """ Returns if any or specified device is home. """ entity = entity_id or ENTITY_ID_ALL_DEVICES - return statemachine.is_state(entity, general.STATE_HOME) + return statemachine.is_state(entity, components.STATE_HOME) # pylint: disable=too-many-instance-attributes @@ -110,7 +112,7 @@ class DeviceTracker(object): known_dev[device]['last_seen'] = now self.statemachine.set_state( - known_dev[device]['entity_id'], general.STATE_HOME) + known_dev[device]['entity_id'], components.STATE_HOME) # 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 @@ -120,7 +122,7 @@ class DeviceTracker(object): if (now - known_dev[device]['last_seen'] > self.error_scanning): self.statemachine.set_state(known_dev[device]['entity_id'], - general.STATE_NOT_HOME) + components.STATE_NOT_HOME) # 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 diff --git a/homeassistant/components/general.py b/homeassistant/components/general.py deleted file mode 100644 index b764da83e0a..00000000000 --- a/homeassistant/components/general.py +++ /dev/null @@ -1,103 +0,0 @@ -""" -homeassistant.components.general -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -This component contains a service to shut down all devices. -""" -import importlib - -import homeassistant as ha -import homeassistant.util as util - -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 _get_module(module): - """ Helper function to load a module. """ - try: - 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 is_on(statemachine, entity_id=None): - """ 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 - - for entity_id in entity_ids: - 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 diff --git a/homeassistant/components/group.py b/homeassistant/components/group.py index 9c94c4f8b0c..edfe797df39 100644 --- a/homeassistant/components/group.py +++ b/homeassistant/components/group.py @@ -8,7 +8,7 @@ Provides functionality to group devices that can be turned on or off. import logging import homeassistant as ha -from homeassistant.components import general as gen +import homeassistant.components as components DOMAIN = "group" @@ -17,8 +17,8 @@ ENTITY_ID_FORMAT = DOMAIN + ".{}" STATE_ATTR_ENTITY_IDS = "entity_ids" _GROUP_TYPES = { - "on_off": (gen.STATE_ON, gen.STATE_OFF), - "home_not_home": (gen.STATE_HOME, gen.STATE_NOT_HOME) + "on_off": (components.STATE_ON, components.STATE_OFF), + "home_not_home": (components.STATE_HOME, components.STATE_NOT_HOME) } @@ -141,28 +141,28 @@ def setup(bus, statemachine, name, entity_ids): # 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): + if not bus.has_service(DOMAIN, components.SERVICE_TURN_ON): def _turn_group_on_service(service): - """ Call general.turn_on for each entity_id from this group. """ + """ Call components.turn_on for each entity_id from this group. """ for entity_id in get_entity_ids(statemachine, service.data.get( - gen.ATTR_ENTITY_ID)): + components.ATTR_ENTITY_ID)): - gen.turn_on(bus, entity_id) + components.turn_on(bus, entity_id) - bus.register_service(DOMAIN, gen.SERVICE_TURN_ON, + bus.register_service(DOMAIN, components.SERVICE_TURN_ON, _turn_group_on_service) - if not bus.has_service(DOMAIN, gen.SERVICE_TURN_OFF): + if not bus.has_service(DOMAIN, components.SERVICE_TURN_OFF): def _turn_group_off_service(service): - """ Call general.turn_off for each entity_id from this group. """ + """ Call components.turn_off for each entity_id in this group. """ for entity_id in get_entity_ids(statemachine, service.data.get( - gen.ATTR_ENTITY_ID)): + components.ATTR_ENTITY_ID)): - gen.turn_off(bus, entity_id) + components.turn_off(bus, entity_id) - bus.register_service(DOMAIN, gen.SERVICE_TURN_OFF, + bus.register_service(DOMAIN, components.SERVICE_TURN_OFF, _turn_group_off_service) statemachine.set_state(group_entity_id, group_state, state_attr) diff --git a/homeassistant/components/light.py b/homeassistant/components/light.py index 74b5880e57d..61461002375 100644 --- a/homeassistant/components/light.py +++ b/homeassistant/components/light.py @@ -10,7 +10,8 @@ from datetime import datetime, timedelta import homeassistant as ha import homeassistant.util as util -from homeassistant.components import general, group +import homeassistant.components as components +from homeassistant.components import group DOMAIN = "light" @@ -27,7 +28,7 @@ def is_on(statemachine, entity_id=None): """ Returns if the lights are on based on the statemachine. """ entity_id = entity_id or ENTITY_ID_ALL_LIGHTS - return statemachine.is_state(entity_id, general.STATE_ON) + return statemachine.is_state(entity_id, components.STATE_ON) # pylint: disable=unused-argument @@ -36,12 +37,12 @@ def turn_on(bus, entity_id=None, transition_seconds=None): data = {} if entity_id: - data[general.ATTR_ENTITY_ID] = entity_id + data[components.ATTR_ENTITY_ID] = entity_id if transition_seconds: data["transition_seconds"] = transition_seconds - bus.call_service(DOMAIN, general.SERVICE_TURN_ON, data) + bus.call_service(DOMAIN, components.SERVICE_TURN_ON, data) # pylint: disable=unused-argument @@ -50,12 +51,12 @@ def turn_off(bus, entity_id=None, transition_seconds=None): data = {} if entity_id: - data[general.ATTR_ENTITY_ID] = entity_id + data[components.ATTR_ENTITY_ID] = entity_id if transition_seconds: data["transition_seconds"] = transition_seconds - bus.call_service(DOMAIN, general.SERVICE_TURN_OFF, data) + bus.call_service(DOMAIN, components.SERVICE_TURN_OFF, data) def setup(bus, statemachine, light_control): @@ -87,8 +88,9 @@ def setup(bus, statemachine, light_control): status = {light_id: light_control.is_light_on(light_id) for light_id in light_control.light_ids} - for light_id, state in status.items(): - new_state = general.STATE_ON if state else general.STATE_OFF + for light_id, is_light_on in status.items(): + new_state = (components.STATE_ON if is_light_on + else components.STATE_OFF) statemachine.set_state(entity_ids[light_id], new_state) @@ -101,12 +103,12 @@ def setup(bus, statemachine, light_control): def handle_light_service(service): """ Hande a turn light on or off service call. """ - entity_id = service.data.get(general.ATTR_ENTITY_ID, None) + entity_id = service.data.get(components.ATTR_ENTITY_ID, None) transition_seconds = service.data.get("transition_seconds", None) object_id = util.split_entity_id(entity_id)[1] if entity_id else None - if service.service == general.SERVICE_TURN_ON: + if service.service == components.SERVICE_TURN_ON: light_control.turn_light_on(object_id, transition_seconds) else: light_control.turn_light_off(object_id, transition_seconds) @@ -114,10 +116,10 @@ def setup(bus, statemachine, light_control): update_light_state(None) # Listen for light on and light off events - bus.register_service(DOMAIN, general.SERVICE_TURN_ON, + bus.register_service(DOMAIN, components.SERVICE_TURN_ON, handle_light_service) - bus.register_service(DOMAIN, general.SERVICE_TURN_OFF, + bus.register_service(DOMAIN, components.SERVICE_TURN_OFF, handle_light_service) return True