mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 04:07:08 +00:00
Merge pull request #67 from balloob/ha-config
Add a global config object to Home Assistant
This commit is contained in:
commit
c8401a3c4d
@ -1,8 +1,20 @@
|
||||
homeassistant:
|
||||
# Omitted values in this section will be auto detected using freegeoip.net
|
||||
|
||||
# Location required to calculate the time the sun rises and sets
|
||||
latitude: 32.87336
|
||||
longitude: 117.22743
|
||||
|
||||
# C for Celcius, F for Fahrenheit
|
||||
temperature_unit: C
|
||||
|
||||
# Pick yours from here:
|
||||
# http://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
||||
time_zone: America/Los_Angeles
|
||||
|
||||
# Name of the location where Home Assistant is running
|
||||
name: Home
|
||||
|
||||
http:
|
||||
api_password: mypass
|
||||
# Set to 1 to enable development mode
|
||||
|
@ -15,11 +15,14 @@ import re
|
||||
import datetime as dt
|
||||
import functools as ft
|
||||
|
||||
import requests
|
||||
|
||||
from homeassistant.const import (
|
||||
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
|
||||
SERVICE_HOMEASSISTANT_STOP, EVENT_TIME_CHANGED, EVENT_STATE_CHANGED,
|
||||
EVENT_CALL_SERVICE, ATTR_NOW, ATTR_DOMAIN, ATTR_SERVICE, MATCH_ALL,
|
||||
EVENT_SERVICE_EXECUTED, ATTR_SERVICE_CALL_ID, EVENT_SERVICE_REGISTERED)
|
||||
EVENT_SERVICE_EXECUTED, ATTR_SERVICE_CALL_ID, EVENT_SERVICE_REGISTERED,
|
||||
TEMP_CELCIUS, TEMP_FAHRENHEIT)
|
||||
import homeassistant.util as util
|
||||
|
||||
DOMAIN = "homeassistant"
|
||||
@ -49,6 +52,7 @@ class HomeAssistant(object):
|
||||
self.bus = EventBus(pool)
|
||||
self.services = ServiceRegistry(self.bus, pool)
|
||||
self.states = StateMachine(self.bus)
|
||||
self.config = Config()
|
||||
|
||||
# List of loaded components
|
||||
self.components = []
|
||||
@ -56,12 +60,18 @@ class HomeAssistant(object):
|
||||
# Remote.API object pointing at local API
|
||||
self.local_api = None
|
||||
|
||||
# Directory that holds the configuration
|
||||
self.config_dir = os.path.join(os.getcwd(), 'config')
|
||||
@property
|
||||
def config_dir(self):
|
||||
""" DEPRECATED 3/18/2015. Use hass.config.config_dir """
|
||||
_LOGGER.warning(
|
||||
'hass.config_dir is deprecated. Use hass.config.config_dir')
|
||||
return self.config.config_dir
|
||||
|
||||
def get_config_path(self, path):
|
||||
""" Returns path to the file within the config dir. """
|
||||
return os.path.join(self.config_dir, path)
|
||||
""" DEPRECATED 3/18/2015. Use hass.config.path """
|
||||
_LOGGER.warning(
|
||||
'hass.get_config_path is deprecated. Use hass.config.path')
|
||||
return self.config.path(path)
|
||||
|
||||
def start(self):
|
||||
""" Start home assistant. """
|
||||
@ -836,6 +846,75 @@ class Timer(threading.Thread):
|
||||
self.hass.bus.fire(EVENT_TIME_CHANGED, {ATTR_NOW: now})
|
||||
|
||||
|
||||
class Config(object):
|
||||
""" Configuration settings for Home Assistant. """
|
||||
def __init__(self):
|
||||
self.latitude = None
|
||||
self.longitude = None
|
||||
self.temperature_unit = None
|
||||
self.location_name = None
|
||||
self.time_zone = None
|
||||
|
||||
# Directory that holds the configuration
|
||||
self.config_dir = os.path.join(os.getcwd(), 'config')
|
||||
|
||||
def auto_detect(self):
|
||||
""" Will attempt to detect config of Home Assistant. """
|
||||
# Only detect if location or temp unit missing
|
||||
if None not in (self.latitude, self.longitude, self.temperature_unit):
|
||||
return
|
||||
|
||||
_LOGGER.info('Auto detecting location and temperature unit')
|
||||
|
||||
try:
|
||||
info = requests.get('https://freegeoip.net/json/').json()
|
||||
except requests.RequestException:
|
||||
return
|
||||
|
||||
if self.latitude is None and self.longitude is None:
|
||||
self.latitude = info['latitude']
|
||||
self.longitude = info['longitude']
|
||||
|
||||
if self.temperature_unit is None:
|
||||
# From Wikipedia:
|
||||
# Fahrenheit is used in the Bahamas, Belize, the Cayman Islands,
|
||||
# Palau, and the United States and associated territories of
|
||||
# American Samoa and the U.S. Virgin Islands
|
||||
if info['country_code'] in ('BS', 'BZ', 'KY', 'PW',
|
||||
'US', 'AS', 'VI'):
|
||||
self.temperature_unit = TEMP_FAHRENHEIT
|
||||
else:
|
||||
self.temperature_unit = TEMP_CELCIUS
|
||||
|
||||
if self.location_name is None:
|
||||
self.location_name = info['city']
|
||||
|
||||
if self.time_zone is None:
|
||||
self.time_zone = info['time_zone']
|
||||
|
||||
def path(self, path):
|
||||
""" Returns path to the file within the config dir. """
|
||||
return os.path.join(self.config_dir, path)
|
||||
|
||||
def temperature(self, value, unit):
|
||||
""" Converts temperature to user preferred unit if set. """
|
||||
if not (unit and self.temperature_unit and
|
||||
unit != self.temperature_unit):
|
||||
return value, unit
|
||||
|
||||
try:
|
||||
if unit == TEMP_CELCIUS:
|
||||
# Convert C to F
|
||||
return round(float(value) * 1.8 + 32.0, 1), TEMP_FAHRENHEIT
|
||||
|
||||
# Convert F to C
|
||||
return round((float(value)-32.0)/1.8, 1), TEMP_CELCIUS
|
||||
|
||||
except ValueError:
|
||||
# Could not convert value to float
|
||||
return value, unit
|
||||
|
||||
|
||||
class HomeAssistantError(Exception):
|
||||
""" General Home Assistant exception occured. """
|
||||
pass
|
||||
|
@ -20,7 +20,10 @@ import homeassistant
|
||||
import homeassistant.loader as loader
|
||||
import homeassistant.components as core_components
|
||||
import homeassistant.components.group as group
|
||||
from homeassistant.const import EVENT_COMPONENT_LOADED
|
||||
from homeassistant.const import (
|
||||
EVENT_COMPONENT_LOADED, CONF_LATITUDE, CONF_LONGITUDE,
|
||||
CONF_TEMPERATURE_UNIT, CONF_NAME, CONF_TIME_ZONE, TEMP_CELCIUS,
|
||||
TEMP_FAHRENHEIT)
|
||||
|
||||
_LOGGER = logging.getLogger(__name__)
|
||||
|
||||
@ -73,6 +76,8 @@ def from_config_dict(config, hass=None):
|
||||
if hass is None:
|
||||
hass = homeassistant.HomeAssistant()
|
||||
|
||||
process_ha_core_config(hass, config.get(homeassistant.DOMAIN, {}))
|
||||
|
||||
enable_logging(hass)
|
||||
|
||||
_ensure_loader_prepared(hass)
|
||||
@ -111,8 +116,8 @@ def from_config_file(config_path, hass=None):
|
||||
if hass is None:
|
||||
hass = homeassistant.HomeAssistant()
|
||||
|
||||
# Set config dir to directory holding config file
|
||||
hass.config_dir = os.path.abspath(os.path.dirname(config_path))
|
||||
# Set config dir to directory holding config file
|
||||
hass.config.config_dir = os.path.abspath(os.path.dirname(config_path))
|
||||
|
||||
config_dict = {}
|
||||
# check config file type
|
||||
@ -143,13 +148,13 @@ def enable_logging(hass):
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
|
||||
# Log errors to a file if we have write access to file or config dir
|
||||
err_log_path = hass.get_config_path("home-assistant.log")
|
||||
err_log_path = hass.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 containing 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)):
|
||||
(not err_path_exists and os.access(hass.config.config_dir, os.W_OK)):
|
||||
|
||||
err_handler = logging.FileHandler(
|
||||
err_log_path, mode='w', delay=True)
|
||||
@ -165,6 +170,26 @@ def enable_logging(hass):
|
||||
"Unable to setup error log %s (access denied)", err_log_path)
|
||||
|
||||
|
||||
def process_ha_core_config(hass, config):
|
||||
""" Processes the [homeassistant] section from the config. """
|
||||
for key, attr in ((CONF_LATITUDE, 'latitude'),
|
||||
(CONF_LONGITUDE, 'longitude'),
|
||||
(CONF_NAME, 'location_name'),
|
||||
(CONF_TIME_ZONE, 'time_zone')):
|
||||
if key in config:
|
||||
setattr(hass.config, attr, config[key])
|
||||
|
||||
if CONF_TEMPERATURE_UNIT in config:
|
||||
unit = config[CONF_TEMPERATURE_UNIT]
|
||||
|
||||
if unit == 'C':
|
||||
hass.config.temperature_unit = TEMP_CELCIUS
|
||||
elif unit == 'F':
|
||||
hass.config.temperature_unit = TEMP_FAHRENHEIT
|
||||
|
||||
hass.config.auto_detect()
|
||||
|
||||
|
||||
def _ensure_loader_prepared(hass):
|
||||
""" Ensure Home Assistant loader is prepared. """
|
||||
if not loader.PREPARED:
|
||||
|
@ -10,8 +10,7 @@ import homeassistant as ha
|
||||
import homeassistant.bootstrap as bootstrap
|
||||
import homeassistant.loader as loader
|
||||
from homeassistant.const import (
|
||||
CONF_PLATFORM, ATTR_ENTITY_PICTURE, ATTR_ENTITY_ID,
|
||||
CONF_LATITUDE, CONF_LONGITUDE)
|
||||
CONF_PLATFORM, ATTR_ENTITY_PICTURE, ATTR_ENTITY_ID)
|
||||
|
||||
DOMAIN = "demo"
|
||||
|
||||
@ -33,8 +32,6 @@ def setup(hass, config):
|
||||
hass.states.set('a.Demo_Mode', 'Enabled')
|
||||
|
||||
# Setup sun
|
||||
config[ha.DOMAIN].setdefault(CONF_LATITUDE, '32.87336')
|
||||
config[ha.DOMAIN].setdefault(CONF_LONGITUDE, '-117.22743')
|
||||
loader.get_component('sun').setup(hass, config)
|
||||
|
||||
# Setup demo platforms
|
||||
|
@ -179,7 +179,7 @@ class DeviceTracker(object):
|
||||
# Write new devices to known devices file
|
||||
if not self.invalid_known_devices_file:
|
||||
|
||||
known_dev_path = self.hass.get_config_path(KNOWN_DEVICES_FILE)
|
||||
known_dev_path = self.hass.config.path(KNOWN_DEVICES_FILE)
|
||||
|
||||
try:
|
||||
# If file does not exist we will write the header too
|
||||
@ -214,7 +214,7 @@ class DeviceTracker(object):
|
||||
# pylint: disable=too-many-branches
|
||||
def _read_known_devices_file(self):
|
||||
""" Parse and process the known devices file. """
|
||||
known_dev_path = self.hass.get_config_path(KNOWN_DEVICES_FILE)
|
||||
known_dev_path = self.hass.config.path(KNOWN_DEVICES_FILE)
|
||||
|
||||
# Return if no known devices file exists
|
||||
if not os.path.isfile(known_dev_path):
|
||||
|
@ -148,7 +148,7 @@ def setup(hass, config):
|
||||
# Load built-in profiles and custom profiles
|
||||
profile_paths = [os.path.join(os.path.dirname(__file__),
|
||||
LIGHT_PROFILES_FILE),
|
||||
hass.get_config_path(LIGHT_PROFILES_FILE)]
|
||||
hass.config.path(LIGHT_PROFILES_FILE)]
|
||||
profiles = {}
|
||||
|
||||
for profile_path in profile_paths:
|
||||
|
@ -51,7 +51,8 @@ def setup_bridge(host, hass, add_devices_callback):
|
||||
|
||||
try:
|
||||
bridge = phue.Bridge(
|
||||
host, config_file_path=hass.get_config_path(PHUE_CONFIG_FILE))
|
||||
host,
|
||||
config_file_path=hass.config.path(PHUE_CONFIG_FILE))
|
||||
except ConnectionRefusedError: # Wrong host was given
|
||||
_LOGGER.exception("Error connecting to the Hue bridge at %s", host)
|
||||
|
||||
|
@ -262,7 +262,7 @@ class Recorder(threading.Thread):
|
||||
|
||||
def _setup_connection(self):
|
||||
""" Ensure database is ready to fly. """
|
||||
db_path = self.hass.get_config_path(DB_FILE)
|
||||
db_path = self.hass.config.path(DB_FILE)
|
||||
self.conn = sqlite3.connect(db_path, check_same_thread=False)
|
||||
self.conn.row_factory = sqlite3.Row
|
||||
|
||||
|
@ -74,7 +74,7 @@ def setup(hass, config):
|
||||
schedule.schedule(hass)
|
||||
return True
|
||||
|
||||
with open(hass.get_config_path(_SCHEDULE_FILE)) as schedule_file:
|
||||
with open(hass.config.path(_SCHEDULE_FILE)) as schedule_file:
|
||||
schedule_descriptions = json.load(schedule_file)
|
||||
|
||||
for schedule_description in schedule_descriptions:
|
||||
|
@ -1,25 +1,25 @@
|
||||
""" Support for Wink sensors. """
|
||||
from homeassistant.helpers.device import Device
|
||||
from homeassistant.const import (
|
||||
TEMP_CELCIUS, ATTR_UNIT_OF_MEASUREMENT, ATTR_FRIENDLY_NAME)
|
||||
from homeassistant.const import TEMP_CELCIUS, ATTR_BATTERY_LEVEL
|
||||
|
||||
|
||||
# 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, '%'),
|
||||
DemoSensor('Outside Temperature', 15.6, TEMP_CELCIUS, 12),
|
||||
DemoSensor('Outside Humidity', 54, '%', None),
|
||||
])
|
||||
|
||||
|
||||
class DemoSensor(Device):
|
||||
""" A Demo sensor. """
|
||||
|
||||
def __init__(self, name, state, unit_of_measurement):
|
||||
def __init__(self, name, state, unit_of_measurement, battery):
|
||||
self._name = name
|
||||
self._state = state
|
||||
self._unit_of_measurement = unit_of_measurement
|
||||
self._battery = battery
|
||||
|
||||
@property
|
||||
def should_poll(self):
|
||||
@ -36,10 +36,15 @@ class DemoSensor(Device):
|
||||
""" Returns the state of the device. """
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
""" Unit this state is expressed in. """
|
||||
return self._unit_of_measurement
|
||||
|
||||
@property
|
||||
def state_attributes(self):
|
||||
""" Returns the state attributes. """
|
||||
return {
|
||||
ATTR_FRIENDLY_NAME: self._name,
|
||||
ATTR_UNIT_OF_MEASUREMENT: self._unit_of_measurement,
|
||||
}
|
||||
if self._battery:
|
||||
return {
|
||||
ATTR_BATTERY_LEVEL: self._battery,
|
||||
}
|
||||
|
@ -7,8 +7,7 @@ Shows system monitor values such as: disk, memory and processor use
|
||||
"""
|
||||
|
||||
from homeassistant.helpers.device import Device
|
||||
from homeassistant.const import (
|
||||
ATTR_UNIT_OF_MEASUREMENT, ATTR_FRIENDLY_NAME, STATE_ON, STATE_OFF)
|
||||
from homeassistant.const import STATE_ON, STATE_OFF
|
||||
import psutil
|
||||
import logging
|
||||
|
||||
@ -63,14 +62,6 @@ class SystemMonitorSensor(Device):
|
||||
""" Returns the state of the device. """
|
||||
return self._state
|
||||
|
||||
@property
|
||||
def state_attributes(self):
|
||||
""" Returns the state attributes. """
|
||||
return {
|
||||
ATTR_FRIENDLY_NAME: self.name,
|
||||
ATTR_UNIT_OF_MEASUREMENT: self.unit_of_measurement,
|
||||
}
|
||||
|
||||
def update(self):
|
||||
if self.type == 'disk_use_percent':
|
||||
self._state = psutil.disk_usage(self.argument).percent
|
||||
|
@ -29,8 +29,7 @@ from collections import namedtuple
|
||||
import tellcore.telldus as telldus
|
||||
import tellcore.constants as tellcore_constants
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT, TEMP_CELCIUS)
|
||||
from homeassistant.const import TEMP_CELCIUS
|
||||
from homeassistant.helpers.device import Device
|
||||
import homeassistant.util as util
|
||||
|
||||
@ -100,7 +99,7 @@ class TellstickSensor(Device):
|
||||
def __init__(self, name, sensor, datatype, sensor_info):
|
||||
self.datatype = datatype
|
||||
self.sensor = sensor
|
||||
self.unit = sensor_info.unit or None
|
||||
self.unit_of_measurement = sensor_info.unit or None
|
||||
|
||||
self._name = "{} {}".format(name, sensor_info.name)
|
||||
|
||||
@ -113,15 +112,3 @@ class TellstickSensor(Device):
|
||||
def state(self):
|
||||
""" Returns the state of the device. """
|
||||
return self.sensor.value(self.datatype).value
|
||||
|
||||
@property
|
||||
def state_attributes(self):
|
||||
""" Returns the state attributes. """
|
||||
attrs = {
|
||||
ATTR_FRIENDLY_NAME: self._name,
|
||||
}
|
||||
|
||||
if self.unit:
|
||||
attrs[ATTR_UNIT_OF_MEASUREMENT] = self.unit
|
||||
|
||||
return attrs
|
||||
|
@ -4,8 +4,8 @@ import logging
|
||||
# pylint: disable=no-name-in-module, import-error
|
||||
import homeassistant.external.wink.pywink as pywink
|
||||
|
||||
from homeassistant.components.wink import WinkSensorDevice
|
||||
from homeassistant.const import CONF_ACCESS_TOKEN
|
||||
from homeassistant.helpers.device import Device
|
||||
from homeassistant.const import CONF_ACCESS_TOKEN, STATE_OPEN, STATE_CLOSED
|
||||
|
||||
|
||||
def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
@ -22,3 +22,34 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
||||
pywink.set_bearer_token(token)
|
||||
|
||||
add_devices(WinkSensorDevice(sensor) for sensor in pywink.get_sensors())
|
||||
|
||||
|
||||
class WinkSensorDevice(Device):
|
||||
""" represents a wink sensor within home assistant. """
|
||||
|
||||
def __init__(self, wink):
|
||||
self.wink = wink
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
""" Returns the state. """
|
||||
return STATE_OPEN if self.is_open else STATE_CLOSED
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
""" Returns the id of this wink sensor """
|
||||
return "{}.{}".format(self.__class__, self.wink.deviceId())
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" Returns the name of the sensor if any. """
|
||||
return self.wink.name()
|
||||
|
||||
def update(self):
|
||||
""" Update state of the sensor. """
|
||||
self.wink.updateState()
|
||||
|
||||
@property
|
||||
def is_open(self):
|
||||
""" True if door is open. """
|
||||
return self.wink.state()
|
||||
|
@ -11,7 +11,7 @@ from pydispatch import dispatcher
|
||||
import homeassistant.components.zwave as zwave
|
||||
from homeassistant.helpers.device import Device
|
||||
from homeassistant.const import (
|
||||
ATTR_BATTERY_LEVEL, ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF,
|
||||
ATTR_BATTERY_LEVEL, STATE_ON, STATE_OFF,
|
||||
TEMP_CELCIUS, TEMP_FAHRENHEIT, ATTR_LOCATION)
|
||||
|
||||
|
||||
@ -77,11 +77,6 @@ class ZWaveSensor(Device):
|
||||
if battery_level is not None:
|
||||
attrs[ATTR_BATTERY_LEVEL] = battery_level
|
||||
|
||||
unit = self.unit
|
||||
|
||||
if unit:
|
||||
attrs[ATTR_UNIT_OF_MEASUREMENT] = unit
|
||||
|
||||
location = self._node.location
|
||||
|
||||
if location:
|
||||
@ -90,8 +85,7 @@ class ZWaveSensor(Device):
|
||||
return attrs
|
||||
|
||||
@property
|
||||
def unit(self):
|
||||
""" Unit if sensor has one. """
|
||||
def unit_of_measurement(self):
|
||||
return self._value.units
|
||||
|
||||
def _value_changed(self, value):
|
||||
@ -126,8 +120,7 @@ class ZWaveMultilevelSensor(ZWaveSensor):
|
||||
return value
|
||||
|
||||
@property
|
||||
def unit(self):
|
||||
""" Unit of this sensor. """
|
||||
def unit_of_measurement(self):
|
||||
unit = self._value.units
|
||||
|
||||
if unit == 'C':
|
||||
|
@ -24,9 +24,6 @@ which event (sunset or sunrise) and the offset.
|
||||
import logging
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
import homeassistant as ha
|
||||
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE
|
||||
from homeassistant.helpers import validate_config
|
||||
from homeassistant.util import str_to_datetime, datetime_to_str
|
||||
|
||||
from homeassistant.components.scheduler import ServiceEventListener
|
||||
@ -83,11 +80,6 @@ def setup(hass, config):
|
||||
""" Tracks the state of the sun. """
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
if not validate_config(config,
|
||||
{ha.DOMAIN: [CONF_LATITUDE, CONF_LONGITUDE]},
|
||||
logger):
|
||||
return False
|
||||
|
||||
try:
|
||||
import ephem
|
||||
except ImportError:
|
||||
@ -96,8 +88,8 @@ def setup(hass, config):
|
||||
|
||||
sun = ephem.Sun() # pylint: disable=no-member
|
||||
|
||||
latitude = str(config[ha.DOMAIN][CONF_LATITUDE])
|
||||
longitude = str(config[ha.DOMAIN][CONF_LONGITUDE])
|
||||
latitude = str(hass.config.latitude)
|
||||
longitude = str(hass.config.longitude)
|
||||
|
||||
# Validate latitude and longitude
|
||||
observer = ephem.Observer()
|
||||
|
@ -11,8 +11,7 @@ from homeassistant.helpers.device_component import DeviceComponent
|
||||
import homeassistant.util as util
|
||||
from homeassistant.helpers.device import Device
|
||||
from homeassistant.const import (
|
||||
ATTR_ENTITY_ID, ATTR_TEMPERATURE, ATTR_UNIT_OF_MEASUREMENT,
|
||||
STATE_ON, STATE_OFF)
|
||||
ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF)
|
||||
|
||||
DOMAIN = "thermostat"
|
||||
DEPENDENCIES = []
|
||||
@ -109,11 +108,6 @@ class ThermostatDevice(Device):
|
||||
""" Returns the current state. """
|
||||
return self.target_temperature
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
""" Returns the unit of measurement. """
|
||||
return ""
|
||||
|
||||
@property
|
||||
def device_state_attributes(self):
|
||||
""" Returns device specific state attributes. """
|
||||
@ -123,8 +117,8 @@ class ThermostatDevice(Device):
|
||||
def state_attributes(self):
|
||||
""" Returns optional state attributes. """
|
||||
data = {
|
||||
ATTR_UNIT_OF_MEASUREMENT: self.unit_of_measurement,
|
||||
ATTR_CURRENT_TEMPERATURE: self.current_temperature
|
||||
ATTR_CURRENT_TEMPERATURE: self.hass.config.temperature(
|
||||
self.current_temperature, self.unit_of_measurement)[0]
|
||||
}
|
||||
|
||||
is_away = self.is_away_mode_on
|
||||
|
@ -8,10 +8,9 @@ import homeassistant.external.wink.pywink as pywink
|
||||
|
||||
from homeassistant import bootstrap
|
||||
from homeassistant.loader import get_component
|
||||
from homeassistant.helpers import validate_config, ToggleDevice, Device
|
||||
from homeassistant.helpers import validate_config, ToggleDevice
|
||||
from homeassistant.const import (
|
||||
EVENT_PLATFORM_DISCOVERED, CONF_ACCESS_TOKEN,
|
||||
STATE_OPEN, STATE_CLOSED,
|
||||
ATTR_SERVICE, ATTR_DISCOVERED, ATTR_FRIENDLY_NAME)
|
||||
|
||||
DOMAIN = "wink"
|
||||
@ -53,44 +52,6 @@ def setup(hass, config):
|
||||
return True
|
||||
|
||||
|
||||
class WinkSensorDevice(Device):
|
||||
""" represents a wink sensor within home assistant. """
|
||||
|
||||
def __init__(self, wink):
|
||||
self.wink = wink
|
||||
|
||||
@property
|
||||
def state(self):
|
||||
""" Returns the state. """
|
||||
return STATE_OPEN if self.is_open else STATE_CLOSED
|
||||
|
||||
@property
|
||||
def unique_id(self):
|
||||
""" Returns the id of this wink switch """
|
||||
return "{}.{}".format(self.__class__, self.wink.deviceId())
|
||||
|
||||
@property
|
||||
def name(self):
|
||||
""" Returns the name of the sensor if any. """
|
||||
return self.wink.name()
|
||||
|
||||
@property
|
||||
def state_attributes(self):
|
||||
""" Returns optional state attributes. """
|
||||
return {
|
||||
ATTR_FRIENDLY_NAME: self.wink.name()
|
||||
}
|
||||
|
||||
def update(self):
|
||||
""" Update state of the sensor. """
|
||||
self.wink.updateState()
|
||||
|
||||
@property
|
||||
def is_open(self):
|
||||
""" True if door is open. """
|
||||
return self.wink.state()
|
||||
|
||||
|
||||
class WinkToggleDevice(ToggleDevice):
|
||||
""" represents a Wink switch within home assistant. """
|
||||
|
||||
|
@ -72,7 +72,7 @@ def setup(hass, config):
|
||||
# Setup options
|
||||
options = ZWaveOption(
|
||||
config[DOMAIN].get(CONF_USB_STICK_PATH, DEFAULT_CONF_USB_STICK_PATH),
|
||||
user_path=hass.config_dir)
|
||||
user_path=hass.config.config_dir)
|
||||
|
||||
options.set_console_output(use_debug)
|
||||
options.lock()
|
||||
|
@ -8,6 +8,9 @@ DEVICE_DEFAULT_NAME = "Unnamed Device"
|
||||
# #### CONFIG ####
|
||||
CONF_LATITUDE = "latitude"
|
||||
CONF_LONGITUDE = "longitude"
|
||||
CONF_TEMPERATURE_UNIT = "temperature_unit"
|
||||
CONF_NAME = "name"
|
||||
CONF_TIME_ZONE = "time_zone"
|
||||
|
||||
CONF_PLATFORM = "platform"
|
||||
CONF_HOST = "host"
|
||||
|
@ -8,7 +8,8 @@ Provides ABC for devices in HA.
|
||||
from homeassistant import NoEntitySpecifiedError
|
||||
|
||||
from homeassistant.const import (
|
||||
ATTR_FRIENDLY_NAME, STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME)
|
||||
ATTR_FRIENDLY_NAME, ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF,
|
||||
DEVICE_DEFAULT_NAME, TEMP_CELCIUS, TEMP_FAHRENHEIT)
|
||||
|
||||
|
||||
class Device(object):
|
||||
@ -46,6 +47,11 @@ class Device(object):
|
||||
""" Returns the state attributes. """
|
||||
return {}
|
||||
|
||||
@property
|
||||
def unit_of_measurement(self):
|
||||
""" Unit of measurement of this entity if any. """
|
||||
return None
|
||||
|
||||
# DEPRECATION NOTICE:
|
||||
# Device is moving from getters to properties.
|
||||
# For now the new properties will call the old functions
|
||||
@ -82,12 +88,25 @@ class Device(object):
|
||||
if force_refresh:
|
||||
self.update()
|
||||
|
||||
state = str(self.state)
|
||||
attr = self.state_attributes or {}
|
||||
|
||||
if ATTR_FRIENDLY_NAME not in attr and self.name:
|
||||
attr[ATTR_FRIENDLY_NAME] = self.name
|
||||
|
||||
return self.hass.states.set(self.entity_id, self.state, attr)
|
||||
if ATTR_UNIT_OF_MEASUREMENT not in attr and self.unit_of_measurement:
|
||||
attr[ATTR_UNIT_OF_MEASUREMENT] = self.unit_of_measurement
|
||||
|
||||
# Convert temperature if we detect one
|
||||
if attr.get(ATTR_UNIT_OF_MEASUREMENT) in (TEMP_CELCIUS,
|
||||
TEMP_FAHRENHEIT):
|
||||
|
||||
state, attr[ATTR_UNIT_OF_MEASUREMENT] = \
|
||||
self.hass.config.temperature(
|
||||
state, attr[ATTR_UNIT_OF_MEASUREMENT])
|
||||
state = str(state)
|
||||
|
||||
return self.hass.states.set(self.entity_id, state, attr)
|
||||
|
||||
def __eq__(self, other):
|
||||
return (isinstance(other, Device) and
|
||||
|
@ -46,11 +46,11 @@ def prepare(hass):
|
||||
pkgutil.iter_modules(components.__path__, 'homeassistant.components.'))
|
||||
|
||||
# Look for available custom components
|
||||
custom_path = hass.get_config_path("custom_components")
|
||||
custom_path = hass.config.path("custom_components")
|
||||
|
||||
if os.path.isdir(custom_path):
|
||||
# Ensure we can load custom components using Pythons import
|
||||
sys.path.insert(0, hass.config_dir)
|
||||
sys.path.insert(0, hass.config.config_dir)
|
||||
|
||||
# We cannot use the same approach as for built-in components because
|
||||
# custom components might only contain a platform for a component.
|
||||
|
@ -14,7 +14,6 @@ import logging
|
||||
import json
|
||||
import enum
|
||||
import urllib.parse
|
||||
import os
|
||||
|
||||
import requests
|
||||
|
||||
@ -115,10 +114,9 @@ class HomeAssistant(ha.HomeAssistant):
|
||||
self.bus = EventBus(remote_api, pool)
|
||||
self.services = ha.ServiceRegistry(self.bus, pool)
|
||||
self.states = StateMachine(self.bus, self.remote_api)
|
||||
self.config = ha.Config()
|
||||
self.components = []
|
||||
|
||||
self.config_dir = os.path.join(os.getcwd(), 'config')
|
||||
|
||||
def start(self):
|
||||
# Ensure a local API exists to connect with remote
|
||||
if self.local_api is None:
|
||||
|
@ -14,7 +14,7 @@ from homeassistant.const import STATE_ON, STATE_OFF, DEVICE_DEFAULT_NAME
|
||||
def get_test_home_assistant():
|
||||
""" Returns a Home Assistant object pointing at test config dir. """
|
||||
hass = ha.HomeAssistant()
|
||||
hass.config_dir = os.path.join(os.path.dirname(__file__), "config")
|
||||
hass.config.config_dir = os.path.join(os.path.dirname(__file__), "config")
|
||||
|
||||
return hass
|
||||
|
||||
|
@ -32,7 +32,7 @@ class TestComponentsDeviceTracker(unittest.TestCase):
|
||||
self.hass = get_test_home_assistant()
|
||||
loader.prepare(self.hass)
|
||||
|
||||
self.known_dev_path = self.hass.get_config_path(
|
||||
self.known_dev_path = self.hass.config.path(
|
||||
device_tracker.KNOWN_DEVICES_FILE)
|
||||
|
||||
def tearDown(self): # pylint: disable=invalid-name
|
||||
|
@ -29,7 +29,7 @@ class TestLight(unittest.TestCase):
|
||||
""" Stop down stuff we started. """
|
||||
self.hass.stop()
|
||||
|
||||
user_light_file = self.hass.get_config_path(light.LIGHT_PROFILES_FILE)
|
||||
user_light_file = self.hass.config.path(light.LIGHT_PROFILES_FILE)
|
||||
|
||||
if os.path.isfile(user_light_file):
|
||||
os.remove(user_light_file)
|
||||
@ -218,7 +218,7 @@ class TestLight(unittest.TestCase):
|
||||
platform = loader.get_component('light.test')
|
||||
platform.init()
|
||||
|
||||
user_light_file = self.hass.get_config_path(light.LIGHT_PROFILES_FILE)
|
||||
user_light_file = self.hass.config.path(light.LIGHT_PROFILES_FILE)
|
||||
|
||||
# Setup a wrong light file
|
||||
with open(user_light_file, 'w') as user_file:
|
||||
@ -234,7 +234,7 @@ class TestLight(unittest.TestCase):
|
||||
platform = loader.get_component('light.test')
|
||||
platform.init()
|
||||
|
||||
user_light_file = self.hass.get_config_path(light.LIGHT_PROFILES_FILE)
|
||||
user_light_file = self.hass.config.path(light.LIGHT_PROFILES_FILE)
|
||||
|
||||
with open(user_light_file, 'w') as user_file:
|
||||
user_file.write('id,x,y,brightness\n')
|
||||
|
@ -11,7 +11,6 @@ import datetime as dt
|
||||
import ephem
|
||||
|
||||
import homeassistant as ha
|
||||
from homeassistant.const import CONF_LATITUDE, CONF_LONGITUDE
|
||||
import homeassistant.components.sun as sun
|
||||
|
||||
|
||||
@ -35,12 +34,9 @@ class TestSun(unittest.TestCase):
|
||||
def test_setting_rising(self):
|
||||
""" Test retrieving sun setting and rising. """
|
||||
# Compare it with the real data
|
||||
self.assertTrue(sun.setup(
|
||||
self.hass,
|
||||
{ha.DOMAIN: {
|
||||
CONF_LATITUDE: '32.87336',
|
||||
CONF_LONGITUDE: '117.22743'
|
||||
}}))
|
||||
self.hass.config.latitude = '32.87336'
|
||||
self.hass.config.longitude = '117.22743'
|
||||
sun.setup(self.hass, None)
|
||||
|
||||
observer = ephem.Observer()
|
||||
observer.lat = '32.87336' # pylint: disable=assigning-non-slot
|
||||
@ -74,12 +70,9 @@ class TestSun(unittest.TestCase):
|
||||
|
||||
def test_state_change(self):
|
||||
""" Test if the state changes at next setting/rising. """
|
||||
self.assertTrue(sun.setup(
|
||||
self.hass,
|
||||
{ha.DOMAIN: {
|
||||
CONF_LATITUDE: '32.87336',
|
||||
CONF_LONGITUDE: '117.22743'
|
||||
}}))
|
||||
self.hass.config.latitude = '32.87336'
|
||||
self.hass.config.longitude = '117.22743'
|
||||
sun.setup(self.hass, None)
|
||||
|
||||
if sun.is_on(self.hass):
|
||||
test_state = sun.STATE_BELOW_HORIZON
|
||||
@ -96,30 +89,3 @@ class TestSun(unittest.TestCase):
|
||||
self.hass.pool.block_till_done()
|
||||
|
||||
self.assertEqual(test_state, self.hass.states.get(sun.ENTITY_ID).state)
|
||||
|
||||
def test_setup(self):
|
||||
""" Test Sun setup with empty and wrong configs. """
|
||||
self.assertFalse(sun.setup(self.hass, {}))
|
||||
self.assertFalse(sun.setup(self.hass, {sun.DOMAIN: {}}))
|
||||
self.assertFalse(sun.setup(
|
||||
self.hass, {ha.DOMAIN: {CONF_LATITUDE: '32.87336'}}))
|
||||
self.assertFalse(sun.setup(
|
||||
self.hass, {ha.DOMAIN: {CONF_LONGITUDE: '117.22743'}}))
|
||||
self.assertFalse(sun.setup(
|
||||
self.hass, {ha.DOMAIN: {CONF_LATITUDE: 'hello'}}))
|
||||
self.assertFalse(sun.setup(
|
||||
self.hass, {ha.DOMAIN: {CONF_LONGITUDE: 'how are you'}}))
|
||||
self.assertFalse(sun.setup(
|
||||
self.hass, {ha.DOMAIN: {
|
||||
CONF_LATITUDE: 'wrong', CONF_LONGITUDE: '117.22743'
|
||||
}}))
|
||||
self.assertFalse(sun.setup(
|
||||
self.hass, {ha.DOMAIN: {
|
||||
CONF_LATITUDE: '32.87336', CONF_LONGITUDE: 'wrong'
|
||||
}}))
|
||||
|
||||
# Test with correct config
|
||||
self.assertTrue(sun.setup(
|
||||
self.hass, {ha.DOMAIN: {
|
||||
CONF_LATITUDE: '32.87336', CONF_LONGITUDE: '117.22743'
|
||||
}}))
|
||||
|
@ -35,10 +35,10 @@ class TestHomeAssistant(unittest.TestCase):
|
||||
def test_get_config_path(self):
|
||||
""" Test get_config_path method. """
|
||||
self.assertEqual(os.path.join(os.getcwd(), "config"),
|
||||
self.hass.config_dir)
|
||||
self.hass.config.config_dir)
|
||||
|
||||
self.assertEqual(os.path.join(os.getcwd(), "config", "test.conf"),
|
||||
self.hass.get_config_path("test.conf"))
|
||||
self.hass.config.path("test.conf"))
|
||||
|
||||
def test_block_till_stoped(self):
|
||||
""" Test if we can block till stop service is called. """
|
||||
|
Loading…
x
Reference in New Issue
Block a user