mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 12:17:07 +00:00
Refactored device components
This commit is contained in:
parent
f0c6ac1aa3
commit
89100d14c8
@ -52,17 +52,18 @@ import logging
|
||||
import os
|
||||
import csv
|
||||
|
||||
from homeassistant.loader import get_component
|
||||
from homeassistant.helpers.device_component import DeviceComponent
|
||||
|
||||
import homeassistant.util as util
|
||||
from homeassistant.const import (
|
||||
STATE_ON, SERVICE_TURN_ON, SERVICE_TURN_OFF, ATTR_ENTITY_ID)
|
||||
from homeassistant.helpers import (
|
||||
generate_entity_id, extract_entity_ids, config_per_platform)
|
||||
from homeassistant.helpers import extract_entity_ids
|
||||
from homeassistant.components import group, discovery, wink
|
||||
|
||||
|
||||
DOMAIN = "light"
|
||||
DEPENDENCIES = []
|
||||
SCAN_INTERVAL = 30
|
||||
|
||||
GROUP_NAME_ALL_LIGHTS = 'all lights'
|
||||
ENTITY_ID_ALL_LIGHTS = group.ENTITY_ID_FORMAT.format('all_lights')
|
||||
@ -140,6 +141,13 @@ def turn_off(hass, entity_id=None, transition=None):
|
||||
def setup(hass, config):
|
||||
""" Exposes light control via statemachine and services. """
|
||||
|
||||
component = DeviceComponent(
|
||||
_LOGGER, DOMAIN, hass, SCAN_INTERVAL, DISCOVERY_PLATFORMS,
|
||||
GROUP_NAME_ALL_LIGHTS)
|
||||
component.setup(config)
|
||||
|
||||
lights = component.devices
|
||||
|
||||
# Load built-in profiles and custom profiles
|
||||
profile_paths = [os.path.join(os.path.dirname(__file__),
|
||||
LIGHT_PROFILES_FILE),
|
||||
@ -168,55 +176,6 @@ def setup(hass, config):
|
||||
|
||||
return False
|
||||
|
||||
# Dict to track entity_id -> lights
|
||||
lights = {}
|
||||
|
||||
# Track all lights in a group
|
||||
light_group = group.Group(hass, GROUP_NAME_ALL_LIGHTS, user_defined=False)
|
||||
|
||||
def add_lights(new_lights):
|
||||
""" Add lights to the component to track. """
|
||||
for light in new_lights:
|
||||
if light is not None and light not in lights.values():
|
||||
light.hass = hass
|
||||
|
||||
light.entity_id = generate_entity_id(
|
||||
ENTITY_ID_FORMAT, light.name, lights.keys())
|
||||
|
||||
lights[light.entity_id] = light
|
||||
|
||||
light.update_ha_state()
|
||||
|
||||
light_group.update_tracked_entity_ids(lights.keys())
|
||||
|
||||
for p_type, p_config in config_per_platform(config, DOMAIN, _LOGGER):
|
||||
platform = get_component(ENTITY_ID_FORMAT.format(p_type))
|
||||
|
||||
if platform is None:
|
||||
_LOGGER.error("Unknown type specified: %s", p_type)
|
||||
|
||||
platform.setup_platform(hass, p_config, add_lights)
|
||||
|
||||
def update_lights_state(now):
|
||||
""" Update the states of all the lights. """
|
||||
if lights:
|
||||
_LOGGER.info("Updating light states")
|
||||
|
||||
for light in lights.values():
|
||||
if light.should_poll:
|
||||
light.update_ha_state(True)
|
||||
|
||||
update_lights_state(None)
|
||||
|
||||
def light_discovered(service, info):
|
||||
""" Called when a light is discovered. """
|
||||
platform = get_component(
|
||||
ENTITY_ID_FORMAT.format(DISCOVERY_PLATFORMS[service]))
|
||||
|
||||
platform.setup_platform(hass, {}, add_lights, info)
|
||||
|
||||
discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), light_discovered)
|
||||
|
||||
def handle_light_service(service):
|
||||
""" Hande a turn light on or off service call. """
|
||||
# Get and validate data
|
||||
@ -303,9 +262,6 @@ def setup(hass, config):
|
||||
for light in target_lights:
|
||||
light.update_ha_state(True)
|
||||
|
||||
# Update light state every 30 seconds
|
||||
hass.track_time_change(update_lights_state, second=[0, 30])
|
||||
|
||||
# Listen for light on and light off service calls
|
||||
hass.services.register(DOMAIN, SERVICE_TURN_ON,
|
||||
handle_light_service)
|
||||
|
@ -4,68 +4,29 @@ homeassistant.components.sensor
|
||||
Component to interface with various sensors that can be monitored.
|
||||
"""
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
from homeassistant.loader import get_component
|
||||
import homeassistant.util as util
|
||||
from homeassistant.helpers import (
|
||||
platform_devices_from_config, generate_entity_id)
|
||||
from homeassistant.components import discovery, wink, zwave
|
||||
from homeassistant.helpers.device_component import DeviceComponent
|
||||
from homeassistant.components import wink, zwave
|
||||
|
||||
DOMAIN = 'sensor'
|
||||
DEPENDENCIES = []
|
||||
SCAN_INTERVAL = 30
|
||||
|
||||
ENTITY_ID_FORMAT = DOMAIN + '.{}'
|
||||
|
||||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=1)
|
||||
|
||||
# Maps discovered services to their platforms
|
||||
DISCOVERY_PLATFORMS = {
|
||||
wink.DISCOVER_SENSORS: 'wink',
|
||||
zwave.DISCOVER_SENSORS: 'zwave',
|
||||
}
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def setup(hass, config):
|
||||
""" Track states and offer events for sensors. """
|
||||
logger = logging.getLogger(__name__)
|
||||
component = DeviceComponent(
|
||||
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL,
|
||||
DISCOVERY_PLATFORMS)
|
||||
|
||||
sensors = platform_devices_from_config(
|
||||
config, DOMAIN, hass, ENTITY_ID_FORMAT, logger)
|
||||
|
||||
@util.Throttle(MIN_TIME_BETWEEN_SCANS)
|
||||
def update_sensor_states(now):
|
||||
""" Update states of all sensors. """
|
||||
if sensors:
|
||||
for sensor in sensors.values():
|
||||
if sensor.should_poll:
|
||||
sensor.update_ha_state(True)
|
||||
|
||||
update_sensor_states(None)
|
||||
|
||||
def sensor_discovered(service, info):
|
||||
""" Called when a sensor is discovered. """
|
||||
platform = get_component("{}.{}".format(
|
||||
DOMAIN, DISCOVERY_PLATFORMS[service]))
|
||||
|
||||
discovered = platform.devices_discovered(hass, config, info)
|
||||
|
||||
for sensor in discovered:
|
||||
if sensor is not None and sensor not in sensors.values():
|
||||
sensor.hass = hass
|
||||
|
||||
sensor.entity_id = generate_entity_id(
|
||||
ENTITY_ID_FORMAT, sensor.name, sensors.keys())
|
||||
|
||||
sensors[sensor.entity_id] = sensor
|
||||
|
||||
sensor.update_ha_state()
|
||||
|
||||
discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), sensor_discovered)
|
||||
|
||||
# Fire every 3 seconds
|
||||
hass.track_time_change(update_sensor_states, second=range(0, 60, 3))
|
||||
component.setup(config)
|
||||
|
||||
return True
|
||||
|
@ -4,23 +4,13 @@ from homeassistant.const import (
|
||||
TEMP_CELCIUS, ATTR_UNIT_OF_MEASUREMENT, ATTR_FRIENDLY_NAME)
|
||||
|
||||
|
||||
def get_devices(hass, config):
|
||||
""" Find and return Wink sensors. """
|
||||
|
||||
return get_sensors()
|
||||
|
||||
|
||||
def devices_discovered(hass, config, info):
|
||||
""" Called when a device is discovered. """
|
||||
return get_sensors()
|
||||
|
||||
|
||||
def get_sensors():
|
||||
""" Returns the Wink sensors. """
|
||||
return [
|
||||
# pylint: disable=unused-argument
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up the Demo sensors. """
|
||||
add_devices([
|
||||
DemoSensor('Outside Temperature', 15.6, TEMP_CELCIUS),
|
||||
DemoSensor('Outside Humidity', 54, '%'),
|
||||
]
|
||||
])
|
||||
|
||||
|
||||
class DemoSensor(Device):
|
||||
|
@ -8,26 +8,17 @@ from homeassistant.components.wink import WinkSensorDevice
|
||||
from homeassistant.const import CONF_ACCESS_TOKEN
|
||||
|
||||
|
||||
def get_devices(hass, config):
|
||||
""" Find and return Wink sensors. """
|
||||
token = config.get(CONF_ACCESS_TOKEN)
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up the Wink platform. """
|
||||
if discovery_info is None:
|
||||
token = config.get(CONF_ACCESS_TOKEN)
|
||||
|
||||
if token is None:
|
||||
logging.getLogger(__name__).error(
|
||||
"Missing wink access_token - "
|
||||
"get one at https://winkbearertoken.appspot.com/")
|
||||
return []
|
||||
if token is None:
|
||||
logging.getLogger(__name__).error(
|
||||
"Missing wink access_token - "
|
||||
"get one at https://winkbearertoken.appspot.com/")
|
||||
return
|
||||
|
||||
pywink.set_bearer_token(token)
|
||||
pywink.set_bearer_token(token)
|
||||
|
||||
return get_sensors()
|
||||
|
||||
|
||||
def devices_discovered(hass, config, info):
|
||||
""" Called when a device is discovered. """
|
||||
return get_sensors()
|
||||
|
||||
|
||||
def get_sensors():
|
||||
""" Returns the Wink sensors. """
|
||||
return [WinkSensorDevice(sensor) for sensor in pywink.get_sensors()]
|
||||
add_devices(WinkSensorDevice(sensor) for sensor in pywink.get_sensors())
|
||||
|
@ -15,6 +15,23 @@ from homeassistant.const import (
|
||||
TEMP_CELCIUS, TEMP_FAHRENHEIT, ATTR_LOCATION)
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up Z-Wave sensors. """
|
||||
node = zwave.NETWORK.nodes[discovery_info[zwave.ATTR_NODE_ID]]
|
||||
value = node.values[discovery_info[zwave.ATTR_VALUE_ID]]
|
||||
|
||||
value.set_change_verified(False)
|
||||
|
||||
if zwave.NETWORK.controller.node_id not in node.groups[1].associations:
|
||||
node.groups[1].add_association(zwave.NETWORK.controller.node_id)
|
||||
|
||||
if value.command_class == zwave.COMMAND_CLASS_SENSOR_BINARY:
|
||||
return [ZWaveBinarySensor(value)]
|
||||
|
||||
elif value.command_class == zwave.COMMAND_CLASS_SENSOR_MULTILEVEL:
|
||||
return [ZWaveMultilevelSensor(value)]
|
||||
|
||||
|
||||
class ZWaveSensor(Device):
|
||||
""" Represents a Z-Wave sensor. """
|
||||
def __init__(self, sensor_value):
|
||||
@ -116,20 +133,3 @@ class ZWaveMultilevelSensor(ZWaveSensor):
|
||||
return TEMP_FAHRENHEIT
|
||||
else:
|
||||
return unit
|
||||
|
||||
|
||||
def devices_discovered(hass, config, info):
|
||||
""" Called when a device is discovered. """
|
||||
node = zwave.NETWORK.nodes[info[zwave.ATTR_NODE_ID]]
|
||||
value = node.values[info[zwave.ATTR_VALUE_ID]]
|
||||
|
||||
value.set_change_verified(False)
|
||||
|
||||
if zwave.NETWORK.controller.node_id not in node.groups[1].associations:
|
||||
node.groups[1].add_association(zwave.NETWORK.controller.node_id)
|
||||
|
||||
if value.command_class == zwave.COMMAND_CLASS_SENSOR_BINARY:
|
||||
return [ZWaveBinarySensor(value)]
|
||||
|
||||
elif value.command_class == zwave.COMMAND_CLASS_SENSOR_MULTILEVEL:
|
||||
return [ZWaveMultilevelSensor(value)]
|
||||
|
@ -6,16 +6,16 @@ Component to interface with various switches that can be controlled remotely.
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
from homeassistant.loader import get_component
|
||||
import homeassistant.util as util
|
||||
from homeassistant.helpers.device_component import DeviceComponent
|
||||
|
||||
from homeassistant.const import (
|
||||
STATE_ON, SERVICE_TURN_ON, SERVICE_TURN_OFF, ATTR_ENTITY_ID)
|
||||
from homeassistant.helpers import (
|
||||
generate_entity_id, extract_entity_ids, platform_devices_from_config)
|
||||
from homeassistant.helpers import extract_entity_ids
|
||||
from homeassistant.components import group, discovery, wink
|
||||
|
||||
DOMAIN = 'switch'
|
||||
DEPENDENCIES = []
|
||||
SCAN_INTERVAL = 30
|
||||
|
||||
GROUP_NAME_ALL_SWITCHES = 'all switches'
|
||||
ENTITY_ID_ALL_SWITCHES = group.ENTITY_ID_FORMAT.format('all_switches')
|
||||
@ -59,47 +59,12 @@ def turn_off(hass, entity_id=None):
|
||||
|
||||
def setup(hass, config):
|
||||
""" Track states and offer events for switches. """
|
||||
logger = logging.getLogger(__name__)
|
||||
component = DeviceComponent(
|
||||
_LOGGER, DOMAIN, hass, SCAN_INTERVAL, DISCOVERY_PLATFORMS,
|
||||
GROUP_NAME_ALL_SWITCHES)
|
||||
component.setup(config)
|
||||
|
||||
switches = platform_devices_from_config(
|
||||
config, DOMAIN, hass, ENTITY_ID_FORMAT, logger)
|
||||
|
||||
@util.Throttle(MIN_TIME_BETWEEN_SCANS)
|
||||
def update_states(now):
|
||||
""" Update states of all switches. """
|
||||
if switches:
|
||||
logger.info("Updating switch states")
|
||||
|
||||
for switch in switches.values():
|
||||
switch.update_ha_state(True)
|
||||
|
||||
update_states(None)
|
||||
|
||||
# Track all switches in a group
|
||||
switch_group = group.Group(
|
||||
hass, GROUP_NAME_ALL_SWITCHES, switches.keys(), False)
|
||||
|
||||
def switch_discovered(service, info):
|
||||
""" Called when a switch is discovered. """
|
||||
platform = get_component("{}.{}".format(
|
||||
DOMAIN, DISCOVERY_PLATFORMS[service]))
|
||||
|
||||
discovered = platform.devices_discovered(hass, config, info)
|
||||
|
||||
for switch in discovered:
|
||||
if switch is not None and switch not in switches.values():
|
||||
switch.hass = hass
|
||||
|
||||
switch.entity_id = generate_entity_id(
|
||||
ENTITY_ID_FORMAT, switch.name, switches.keys())
|
||||
|
||||
switches[switch.entity_id] = switch
|
||||
|
||||
switch.update_ha_state()
|
||||
|
||||
switch_group.update_tracked_entity_ids(switches.keys())
|
||||
|
||||
discovery.listen(hass, DISCOVERY_PLATFORMS.keys(), switch_discovered)
|
||||
switches = component.devices
|
||||
|
||||
def handle_switch_service(service):
|
||||
""" Handles calls to the switch services. """
|
||||
@ -118,9 +83,6 @@ def setup(hass, config):
|
||||
|
||||
switch.update_ha_state(True)
|
||||
|
||||
# Update state every 30 seconds
|
||||
hass.track_time_change(update_states, second=[0, 30])
|
||||
|
||||
hass.services.register(DOMAIN, SERVICE_TURN_OFF, handle_switch_service)
|
||||
|
||||
hass.services.register(DOMAIN, SERVICE_TURN_ON, handle_switch_service)
|
||||
|
@ -3,22 +3,13 @@ from homeassistant.helpers import ToggleDevice
|
||||
from homeassistant.const import STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME
|
||||
|
||||
|
||||
def get_devices(hass, config):
|
||||
# pylint: disable=unused-argument
|
||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
""" Find and return demo switches. """
|
||||
return get_switches()
|
||||
|
||||
|
||||
def devices_discovered(hass, config, info):
|
||||
""" Called when a device is discovered. """
|
||||
return get_switches()
|
||||
|
||||
|
||||
def get_switches():
|
||||
""" Returns the Wink switches. """
|
||||
return [
|
||||
add_devices_callback([
|
||||
DemoSwitch('Ceiling', STATE_ON),
|
||||
DemoSwitch('AC', STATE_OFF)
|
||||
]
|
||||
])
|
||||
|
||||
|
||||
class DemoSwitch(ToggleDevice):
|
||||
|
@ -7,14 +7,15 @@ from homeassistant.helpers import ToggleDevice
|
||||
import tellcore.constants as tellcore_constants
|
||||
|
||||
|
||||
def get_devices(hass, config):
|
||||
""" Find and return Tellstick switches. """
|
||||
# pylint: disable=unused-argument
|
||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
""" Find and return tellstick switches. """
|
||||
try:
|
||||
import tellcore.telldus as telldus
|
||||
except ImportError:
|
||||
logging.getLogger(__name__).exception(
|
||||
"Failed to import tellcore")
|
||||
return []
|
||||
return
|
||||
|
||||
core = telldus.TelldusCore()
|
||||
switches_and_lights = core.devices()
|
||||
@ -25,7 +26,7 @@ def get_devices(hass, config):
|
||||
if not switch.methods(tellcore_constants.TELLSTICK_DIM):
|
||||
switches.append(TellstickSwitchDevice(switch))
|
||||
|
||||
return switches
|
||||
add_devices_callback(switches)
|
||||
|
||||
|
||||
class TellstickSwitchDevice(ToggleDevice):
|
||||
|
@ -6,50 +6,36 @@ from homeassistant.components.switch import (
|
||||
ATTR_TODAY_MWH, ATTR_CURRENT_POWER_MWH)
|
||||
|
||||
|
||||
def get_devices(hass, config):
|
||||
""" Find and return WeMo switches. """
|
||||
|
||||
pywemo, _ = get_pywemo()
|
||||
|
||||
if pywemo is None:
|
||||
return []
|
||||
|
||||
logging.getLogger(__name__).info("Scanning for WeMo devices")
|
||||
switches = pywemo.discover_devices()
|
||||
|
||||
# Filter out the switches and wrap in WemoSwitch object
|
||||
return [WemoSwitch(switch) for switch in switches
|
||||
if isinstance(switch, pywemo.Switch)]
|
||||
|
||||
|
||||
def devices_discovered(hass, config, info):
|
||||
""" Called when a device is discovered. """
|
||||
_, discovery = get_pywemo()
|
||||
|
||||
if discovery is None:
|
||||
return []
|
||||
|
||||
device = discovery.device_from_description(info)
|
||||
|
||||
return [] if device is None else [WemoSwitch(device)]
|
||||
|
||||
|
||||
def get_pywemo():
|
||||
""" Tries to import PyWemo. """
|
||||
# pylint: disable=unused-argument
|
||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
""" Find and return wemo switches. """
|
||||
try:
|
||||
# pylint: disable=no-name-in-module, import-error
|
||||
import homeassistant.external.pywemo.pywemo as pywemo
|
||||
import homeassistant.external.pywemo.pywemo.discovery as discovery
|
||||
|
||||
return pywemo, discovery
|
||||
|
||||
except ImportError:
|
||||
logging.getLogger(__name__).exception((
|
||||
"Failed to import pywemo. "
|
||||
"Did you maybe not run `git submodule init` "
|
||||
"and `git submodule update`?"))
|
||||
|
||||
return None, None
|
||||
return
|
||||
|
||||
if discovery_info is not None:
|
||||
device = discovery.device_from_description(discovery_info)
|
||||
|
||||
if device:
|
||||
add_devices_callback([device])
|
||||
|
||||
return
|
||||
|
||||
logging.getLogger(__name__).info("Scanning for WeMo devices")
|
||||
switches = pywemo.discover_devices()
|
||||
|
||||
# Filter out the switches and wrap in WemoSwitch object
|
||||
add_devices_callback(
|
||||
[WemoSwitch(switch) for switch in switches
|
||||
if isinstance(switch, pywemo.Switch)])
|
||||
|
||||
|
||||
class WemoSwitch(ToggleDevice):
|
||||
|
@ -8,26 +8,17 @@ from homeassistant.components.wink import WinkToggleDevice
|
||||
from homeassistant.const import CONF_ACCESS_TOKEN
|
||||
|
||||
|
||||
def get_devices(hass, config):
|
||||
""" Find and return Wink switches. """
|
||||
token = config.get(CONF_ACCESS_TOKEN)
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up the Wink platform. """
|
||||
if discovery_info is None:
|
||||
token = config.get(CONF_ACCESS_TOKEN)
|
||||
|
||||
if token is None:
|
||||
logging.getLogger(__name__).error(
|
||||
"Missing wink access_token - "
|
||||
"get one at https://winkbearertoken.appspot.com/")
|
||||
return []
|
||||
if token is None:
|
||||
logging.getLogger(__name__).error(
|
||||
"Missing wink access_token - "
|
||||
"get one at https://winkbearertoken.appspot.com/")
|
||||
return
|
||||
|
||||
pywink.set_bearer_token(token)
|
||||
pywink.set_bearer_token(token)
|
||||
|
||||
return get_switches()
|
||||
|
||||
|
||||
def devices_discovered(hass, config, info):
|
||||
""" Called when a device is discovered. """
|
||||
return get_switches()
|
||||
|
||||
|
||||
def get_switches():
|
||||
""" Returns the Wink switches. """
|
||||
return [WinkToggleDevice(switch) for switch in pywink.get_switches()]
|
||||
add_devices(WinkToggleDevice(switch) for switch in pywink.get_switches())
|
||||
|
@ -5,23 +5,21 @@ homeassistant.components.thermostat
|
||||
Provides functionality to interact with thermostats.
|
||||
"""
|
||||
import logging
|
||||
from datetime import timedelta
|
||||
|
||||
from homeassistant.helpers import (
|
||||
extract_entity_ids, platform_devices_from_config)
|
||||
from homeassistant.helpers.device_component import DeviceComponent
|
||||
|
||||
import homeassistant.util as util
|
||||
from homeassistant.helpers import Device
|
||||
from homeassistant.helpers import Device, extract_entity_ids
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, ATTR_TEMPERATURE, ATTR_UNIT_OF_MEASUREMENT,
|
||||
STATE_ON, STATE_OFF)
|
||||
|
||||
DOMAIN = "thermostat"
|
||||
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
||||
|
||||
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=10)
|
||||
|
||||
DEPENDENCIES = []
|
||||
|
||||
ENTITY_ID_FORMAT = DOMAIN + ".{}"
|
||||
SCAN_INTERVAL = 60
|
||||
|
||||
SERVICE_SET_AWAY_MODE = "set_away_mode"
|
||||
SERVICE_SET_TEMPERATURE = "set_temperature"
|
||||
|
||||
@ -31,22 +29,10 @@ ATTR_AWAY_MODE = "away_mode"
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def turn_away_mode_on(hass, entity_id=None):
|
||||
def set_away_mode(hass, away_mode, entity_id=None):
|
||||
""" Turn all or specified thermostat away mode on. """
|
||||
data = {
|
||||
ATTR_AWAY_MODE: True
|
||||
}
|
||||
|
||||
if entity_id:
|
||||
data[ATTR_ENTITY_ID] = entity_id
|
||||
|
||||
hass.services.call(DOMAIN, SERVICE_SET_AWAY_MODE, data)
|
||||
|
||||
|
||||
def turn_away_mode_off(hass, entity_id=None):
|
||||
""" Turn all or specified thermostat away mode off. """
|
||||
data = {
|
||||
ATTR_AWAY_MODE: False
|
||||
ATTR_AWAY_MODE: away_mode
|
||||
}
|
||||
|
||||
if entity_id:
|
||||
@ -67,27 +53,10 @@ def set_temperature(hass, temperature, entity_id=None):
|
||||
|
||||
def setup(hass, config):
|
||||
""" Setup thermostats. """
|
||||
component = DeviceComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)
|
||||
component.setup(config)
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
thermostats = platform_devices_from_config(
|
||||
config, DOMAIN, hass, ENTITY_ID_FORMAT, _LOGGER)
|
||||
|
||||
if not thermostats:
|
||||
return False
|
||||
|
||||
@util.Throttle(MIN_TIME_BETWEEN_SCANS)
|
||||
def update_state(now):
|
||||
""" Update thermostat state. """
|
||||
logger.info("Updating thermostat state")
|
||||
|
||||
for thermostat in thermostats.values():
|
||||
if thermostat.should_poll:
|
||||
thermostat.update_ha_state(True)
|
||||
|
||||
# Update state every minute
|
||||
hass.track_time_change(update_state, second=[0])
|
||||
update_state(None)
|
||||
thermostats = component.devices
|
||||
|
||||
def thermostat_service(service):
|
||||
""" Handles calls to the services. """
|
||||
|
@ -6,14 +6,12 @@ from homeassistant.components.thermostat import ThermostatDevice
|
||||
from homeassistant.const import TEMP_CELCIUS, TEMP_FAHRENHEIT
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def get_devices(hass, config):
|
||||
""" Gets thermostats. """
|
||||
|
||||
return [
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up the Demo thermostats. """
|
||||
add_devices([
|
||||
DemoThermostat("Nest", 21, TEMP_CELCIUS, False, 19),
|
||||
DemoThermostat("Thermostat", 68, TEMP_FAHRENHEIT, True, 77),
|
||||
]
|
||||
])
|
||||
|
||||
|
||||
# pylint: disable=too-many-arguments
|
||||
|
@ -69,11 +69,11 @@ TOL_TEMP = 0.3
|
||||
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
def get_devices(hass, config):
|
||||
""" Gets thermostats. """
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up the heat control thermostat. """
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
return [HeatControl(hass, config, logger)]
|
||||
add_devices([HeatControl(hass, config, logger)])
|
||||
|
||||
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
|
@ -7,8 +7,9 @@ from homeassistant.components.thermostat import ThermostatDevice
|
||||
from homeassistant.const import (CONF_USERNAME, CONF_PASSWORD, TEMP_CELCIUS)
|
||||
|
||||
|
||||
def get_devices(hass, config):
|
||||
""" Gets Nest thermostats. """
|
||||
# pylint: disable=unused-argument
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
""" Sets up the nest thermostat. """
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
username = config.get(CONF_USERNAME)
|
||||
@ -17,7 +18,7 @@ def get_devices(hass, config):
|
||||
if username is None or password is None:
|
||||
logger.error("Missing required configuration items %s or %s",
|
||||
CONF_USERNAME, CONF_PASSWORD)
|
||||
return []
|
||||
return
|
||||
|
||||
try:
|
||||
import nest
|
||||
@ -26,14 +27,15 @@ def get_devices(hass, config):
|
||||
"Error while importing dependency nest. "
|
||||
"Did you maybe not install the python-nest dependency?")
|
||||
|
||||
return []
|
||||
return
|
||||
|
||||
napi = nest.Nest(username, password)
|
||||
|
||||
return [
|
||||
add_devices([
|
||||
NestThermostat(structure, device)
|
||||
for structure in napi.structures
|
||||
for device in structure.devices]
|
||||
for device in structure.devices
|
||||
])
|
||||
|
||||
|
||||
class NestThermostat(ThermostatDevice):
|
||||
|
107
homeassistant/helpers/device_component.py
Normal file
107
homeassistant/helpers/device_component.py
Normal file
@ -0,0 +1,107 @@
|
||||
"""
|
||||
Provides helpers for components that handle devices.
|
||||
"""
|
||||
from homeassistant.loader import get_component
|
||||
from homeassistant.helpers import generate_entity_id, config_per_platform
|
||||
from homeassistant.components import group, discovery
|
||||
|
||||
|
||||
class DeviceComponent(object):
|
||||
# pylint: disable=too-many-instance-attributes
|
||||
# pylint: disable=too-many-arguments,too-few-public-methods
|
||||
"""
|
||||
Helper class that will help a device component manage its devices.
|
||||
"""
|
||||
def __init__(self, logger, domain, hass, scan_interval,
|
||||
discovery_platforms=None, group_name=None):
|
||||
self.logger = logger
|
||||
self.hass = hass
|
||||
|
||||
self.domain = domain
|
||||
self.entity_id_format = domain + '.{}'
|
||||
self.scan_interval = scan_interval
|
||||
self.discovery_platforms = discovery_platforms
|
||||
self.group_name = group_name
|
||||
|
||||
self.devices = {}
|
||||
self.group = None
|
||||
|
||||
def setup(self, config):
|
||||
"""
|
||||
Sets up a full device component:
|
||||
- Loads the platforms from the config
|
||||
- Will update devices on an interval
|
||||
- Will listen for supported discovered platforms
|
||||
"""
|
||||
|
||||
# only setup group if name is given
|
||||
if self.group_name is None:
|
||||
self.group = None
|
||||
else:
|
||||
self.group = group.Group(self.hass, self.group_name,
|
||||
user_defined=False)
|
||||
|
||||
# Look in config for Domain, Domain 2, Domain 3 etc and load them
|
||||
for p_type, p_config in \
|
||||
config_per_platform(config, self.domain, self.logger):
|
||||
|
||||
self._setup_platform(p_type, p_config)
|
||||
|
||||
self.hass.track_time_change(self._update_device_states,
|
||||
second=range(0, 60, self.scan_interval))
|
||||
|
||||
if self.discovery_platforms:
|
||||
discovery.listen(self.hass, self.discovery_platforms.keys(),
|
||||
self._device_discovered)
|
||||
|
||||
def _update_device_states(self, now):
|
||||
""" Update the states of all the lights. """
|
||||
self.logger.info("Updating %s states", self.domain)
|
||||
|
||||
for device in self.devices.values():
|
||||
if device.should_poll:
|
||||
device.update_ha_state(True)
|
||||
|
||||
def _device_discovered(self, service, info):
|
||||
""" Called when a device is discovered. """
|
||||
if service not in self.discovery_platforms:
|
||||
return
|
||||
|
||||
self._setup_platform(self.discovery_platforms[service], {}, info)
|
||||
|
||||
def _add_devices(self, new_devices):
|
||||
"""
|
||||
Takes in a list of new devices. For each device will see if it already
|
||||
exists. If not, will add it, set it up and push the first state.
|
||||
"""
|
||||
for device in new_devices:
|
||||
if device is not None and device not in self.devices.values():
|
||||
device.hass = self.hass
|
||||
|
||||
device.entity_id = generate_entity_id(
|
||||
self.entity_id_format, device.name, self.devices.keys())
|
||||
|
||||
self.devices[device.entity_id] = device
|
||||
|
||||
device.update_ha_state()
|
||||
|
||||
if self.group is not None:
|
||||
self.group.update_tracked_entity_ids(self.devices.keys())
|
||||
|
||||
def _setup_platform(self, platform_type, config, discovery_info=None):
|
||||
""" Tries to setup a platform for this component. """
|
||||
platform_name = '{}.{}'.format(self.domain, platform_type)
|
||||
platform = get_component(platform_name)
|
||||
|
||||
if platform is None:
|
||||
self.logger.error('Unable to find platform %s', platform_type)
|
||||
return
|
||||
|
||||
try:
|
||||
platform.setup_platform(
|
||||
self.hass, config, self._add_devices, discovery_info)
|
||||
except (AttributeError, TypeError):
|
||||
# AttributeError if setup_platform does not exist
|
||||
# TypeError if wrong number of argumnets for setup_platform
|
||||
self.logger.exception(
|
||||
"Error setting up %s", platform_type)
|
@ -27,8 +27,3 @@ def init(empty=False):
|
||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
""" Returns mock devices. """
|
||||
add_devices_callback(DEVICES)
|
||||
|
||||
|
||||
def get_lights():
|
||||
""" Helper method to get current light objects. """
|
||||
return DEVICES
|
||||
|
@ -24,6 +24,6 @@ def init(empty=False):
|
||||
]
|
||||
|
||||
|
||||
def get_switches(hass, config):
|
||||
""" Returns mock devices. """
|
||||
return DEVICES
|
||||
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
||||
""" Find and return test switches. """
|
||||
add_devices_callback(DEVICES)
|
||||
|
@ -103,7 +103,7 @@ class TestLight(unittest.TestCase):
|
||||
self.assertTrue(
|
||||
light.setup(self.hass, {light.DOMAIN: {CONF_TYPE: 'test'}}))
|
||||
|
||||
dev1, dev2, dev3 = platform.get_lights()
|
||||
dev1, dev2, dev3 = platform.DEVICES
|
||||
|
||||
# Test init
|
||||
self.assertTrue(light.is_on(self.hass, dev1.entity_id))
|
||||
@ -244,7 +244,7 @@ class TestLight(unittest.TestCase):
|
||||
self.hass, {light.DOMAIN: {CONF_TYPE: 'test'}}
|
||||
))
|
||||
|
||||
dev1, dev2, dev3 = platform.get_lights()
|
||||
dev1, dev2, dev3 = platform.DEVICES
|
||||
|
||||
light.turn_on(self.hass, dev1.entity_id, profile='test')
|
||||
|
||||
|
@ -30,7 +30,7 @@ class TestSwitch(unittest.TestCase):
|
||||
|
||||
# Switch 1 is ON, switch 2 is OFF
|
||||
self.switch_1, self.switch_2, self.switch_3 = \
|
||||
platform.get_switches(None, None)
|
||||
platform.DEVICES
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
""" Stop down stuff we started. """
|
||||
|
Loading…
x
Reference in New Issue
Block a user