From 22a2b65e3fb8a4340f45cdff26cd4eff2e418f42 Mon Sep 17 00:00:00 2001 From: andythigpen Date: Sat, 21 Feb 2015 16:03:02 -0600 Subject: [PATCH 1/7] Add configurable intervals to device tracker. Allows the user to configure a longer interval for when the device tracker should scan for devices. --- .../components/device_tracker/__init__.py | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/homeassistant/components/device_tracker/__init__.py b/homeassistant/components/device_tracker/__init__.py index 97b9f457703..3899f42a621 100644 --- a/homeassistant/components/device_tracker/__init__.py +++ b/homeassistant/components/device_tracker/__init__.py @@ -36,6 +36,9 @@ TIME_DEVICE_NOT_FOUND = timedelta(minutes=3) # Filename to save known devices to KNOWN_DEVICES_FILE = "known_devices.csv" +CONF_SECONDS = "interval_seconds" + +DEFAULT_CONF_SECONDS = 12 _LOGGER = logging.getLogger(__name__) @@ -81,7 +84,10 @@ def setup(hass, config): return False - tracker = DeviceTracker(hass, device_scanner) + seconds = util.convert(config[DOMAIN].get(CONF_SECONDS), int, + DEFAULT_CONF_SECONDS) + + tracker = DeviceTracker(hass, device_scanner, seconds) # We only succeeded if we got to parse the known devices file return not tracker.invalid_known_devices_file @@ -90,7 +96,7 @@ def setup(hass, config): class DeviceTracker(object): """ Class that tracks which devices are home and which are not. """ - def __init__(self, hass, device_scanner): + def __init__(self, hass, device_scanner, seconds): self.hass = hass self.device_scanner = device_scanner @@ -126,8 +132,10 @@ class DeviceTracker(object): if self.invalid_known_devices_file: return - hass.track_time_change( - update_device_state, second=range(0, 60, 12)) + seconds = range(0, 60, seconds) + + _LOGGER.info("Device tracker interval second=%s", seconds) + hass.track_time_change(update_device_state, second=seconds) hass.services.register(DOMAIN, SERVICE_DEVICE_TRACKER_RELOAD, From 356732189c375ddeca086b31b2156ee4919812ce Mon Sep 17 00:00:00 2001 From: theolind Date: Sat, 28 Feb 2015 16:56:58 +0100 Subject: [PATCH 2/7] Added support for YAML configuration files --- homeassistant/bootstrap.py | 21 ++++++++++++--------- requirements.txt | 3 +++ 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 99278a6a426..c246b822dc3 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -110,17 +110,20 @@ def from_config_file(config_path, hass=None): # Set config dir to directory holding config file hass.config_dir = os.path.abspath(os.path.dirname(config_path)) - # Read config - config = configparser.ConfigParser() - config.read(config_path) + # check config file type + if(os.path.splitext(config_path)[1] == '.yaml'): + # Read yaml + config_dict = yaml.load(io.open(config_path, 'r')) + else: + # Read config + config = configparser.ConfigParser() + config.read(config_path) - config_dict = {} + for section in config.sections(): + config_dict[section] = {} - for section in config.sections(): - config_dict[section] = {} - - for key, val in config.items(section): - config_dict[section][key] = val + for key, val in config.items(section): + config_dict[section][key] = val return from_config_dict(config_dict, hass) diff --git a/requirements.txt b/requirements.txt index 4bf9fc83d6a..f4cd404beaf 100644 --- a/requirements.txt +++ b/requirements.txt @@ -29,3 +29,6 @@ pushbullet.py>=0.7.1 # thermostat.nest python-nest>=2.1 + +# pyyaml +pyyaml From 223d2c2c3ff7a784c95d74adaea7bec6b1a71123 Mon Sep 17 00:00:00 2001 From: theolind Date: Sat, 28 Feb 2015 17:05:38 +0100 Subject: [PATCH 3/7] Added support for YAML files, now with included python modules --- homeassistant/bootstrap.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index c246b822dc3..3c1d722768b 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -11,6 +11,8 @@ start by calling homeassistant.start_home_assistant(bus) import os import configparser +import yaml +import io import logging from collections import defaultdict From f2b602c7ec651274c7d6bfd79d97b8a9fbeb2113 Mon Sep 17 00:00:00 2001 From: theolind Date: Sat, 28 Feb 2015 17:42:23 +0100 Subject: [PATCH 4/7] Added logic to main that prefers .yaml-config over .conf --- homeassistant/__main__.py | 12 ++++++++---- homeassistant/bootstrap.py | 1 + 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/homeassistant/__main__.py b/homeassistant/__main__.py index 05de14dbefc..13703dee416 100644 --- a/homeassistant/__main__.py +++ b/homeassistant/__main__.py @@ -72,15 +72,19 @@ def ensure_config_path(config_dir): 'directory {} ').format(config_dir)) sys.exit() - config_path = os.path.join(config_dir, 'home-assistant.conf') + # Try to use yaml configuration first + config_path = os.path.join(config_dir, 'configuration.yaml') + if not os.path.isfile(config_path): + config_path = os.path.join(config_dir, 'home-assistant.conf') # Ensure a config file exists to make first time usage easier if not os.path.isfile(config_path): + config_path = os.path.join(config_dir, 'configuration.yaml') try: with open(config_path, 'w') as conf: - conf.write("[frontend]\n\n") - conf.write("[discovery]\n\n") - conf.write("[history]\n\n") + conf.write("frontend:\n\n") + conf.write("discovery:\n\n") + conf.write("history:\n\n") except IOError: print(('Fatal Error: No configuration file found and unable ' 'to write a default one to {}').format(config_path)) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index 3c1d722768b..b7de8a6cd33 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -112,6 +112,7 @@ def from_config_file(config_path, hass=None): # Set config dir to directory holding config file hass.config_dir = os.path.abspath(os.path.dirname(config_path)) + config_dict = {} # check config file type if(os.path.splitext(config_path)[1] == '.yaml'): # Read yaml From 8da1fb1d74f98d42fccf7e0ba89be46f0dc87122 Mon Sep 17 00:00:00 2001 From: theolind Date: Sat, 28 Feb 2015 18:59:45 +0100 Subject: [PATCH 5/7] Added example yaml config file, removed old example config, fixed style violation in bootstrap.py --- config/configuration.yaml.example | 98 +++++++++++++++++++++++++++++ config/home-assistant.conf.example | 99 ------------------------------ homeassistant/bootstrap.py | 2 +- 3 files changed, 99 insertions(+), 100 deletions(-) create mode 100644 config/configuration.yaml.example delete mode 100644 config/home-assistant.conf.example diff --git a/config/configuration.yaml.example b/config/configuration.yaml.example new file mode 100644 index 00000000000..b6a1c04bcbb --- /dev/null +++ b/config/configuration.yaml.example @@ -0,0 +1,98 @@ +homeassistant: +# Location required to calculate the time the sun rises and sets + latitude: '32.87336' + longitude: '-117.22743' + +http: + api_password: mypass + # Set to 1 to load each Polymer component separately + # development: 1 + +#light: +# platform: hue + +#wink: + # Get your token at https://winkbearertoken.appspot.com +# access_token: 'YOUR_TOKEN' + +#device_tracker: + # The following types are available: netgear, tomato, luci, nmap_tracker + platform: netgear + host: 192.168.1.1 + username: admin + password: PASSWORD + # http_id is needed for Tomato routers only + # http_id: ABCDEFGHH + # For nmap_tracker, only the IP addresses to scan are needed: + # hosts: 192.168.1.1/24 # netmask prefix notation or + # hosts: 192.168.1.1-255 # address range + +#chromecast: +switch: + platform: wemo + +#thermostat: + platform: nest + # Required: username and password that are used to login to the Nest thermostat. + username: myemail@mydomain.com + password: mypassword + +downloader: + download_dir: downloads + +notify: + platform: pushbullet + api_key: ABCDEFGHJKLMNOPQRSTUVXYZ + +device_sun_light_trigger: + # Optional: specify a specific light/group of lights that has to be turned on + light_group: group.living_room + # Optional: specify which light profile to use when turning lights on + light_profile: relax + # Optional: disable lights being turned off when everybody leaves the house + # disable_turn_off: 1 + +# A comma seperated list of states that have to be tracked as a single group +# Grouped states should share the same type of states (ON/OFF or HOME/NOT_HOME) +group: + living_room: light.Bowl,light.Ceiling,light.TV_back_light + children: device_tracker.child_1,device_tracker.child_2 + +process: + # items are which processes to look for: : + xbmc: XBMC.App + +example: + +simple_alarm: + # Which light/light group has to flash when a known device comes home + known_light: light.Bowl + # Which light/light group has to flash red when light turns on while no one home + unknown_light: group.living_room + +browser: + +keyboard: + +automation: + platform: state + alias: Sun starts shining + + state_entity_id: sun.sun + # Next two are optional, omit to match all + state_from: below_horizon + state_to: above_horizon + + execute_service: light.turn_off + service_entity_id: group.living_room + +automation 2: + platform: time + alias: Beer o Clock + + time_hours: 16 + time_minutes: 0 + time_seconds: 0 + + execute_service: notify.notify + service_data: {"message":"It's 4, time for beer!"} diff --git a/config/home-assistant.conf.example b/config/home-assistant.conf.example deleted file mode 100644 index d71c3c0cc14..00000000000 --- a/config/home-assistant.conf.example +++ /dev/null @@ -1,99 +0,0 @@ -[homeassistant] -# Location required to calculate the time the sun rises and sets -latitude=32.87336 -longitude=-117.22743 - -[http] -api_password=mypass -# Set to 1 to load each Polymer component separately -# development=1 - -[light] -platform=hue - -[wink] -# Get your token at https://winkbearertoken.appspot.com -access_token=YOUR_TOKEN - -[device_tracker] -# The following types are available: netgear, tomato, luci, nmap_tracker -platform=netgear -host=192.168.1.1 -username=admin -password=PASSWORD -# http_id is needed for Tomato routers only -# http_id=ABCDEFGHH -# For nmap_tracker, only the IP addresses to scan are needed: -# hosts=192.168.1.1/24 # netmask prefix notation or -# hosts=192.168.1.1-255 # address range - -[chromecast] - -[switch] -platform=wemo - -[thermostat] -platform=nest -# Required: username and password that are used to login to the Nest thermostat. -username=myemail@mydomain.com -password=mypassword - -[downloader] -download_dir=downloads - -[notify] -platform=pushbullet -api_key=ABCDEFGHJKLMNOPQRSTUVXYZ - -[device_sun_light_trigger] -# Optional: specify a specific light/group of lights that has to be turned on -light_group=group.living_room -# Optional: specify which light profile to use when turning lights on -light_profile=relax -# Optional: disable lights being turned off when everybody leaves the house -# disable_turn_off=1 - -# A comma seperated list of states that have to be tracked as a single group -# Grouped states should share the same type of states (ON/OFF or HOME/NOT_HOME) -[group] -living_room=light.Bowl,light.Ceiling,light.TV_back_light -children=device_tracker.child_1,device_tracker.child_2 - -[process] -# items are which processes to look for: = -xbmc=XBMC.App - -[example] - -[simple_alarm] -# Which light/light group has to flash when a known device comes home -known_light=light.Bowl -# Which light/light group has to flash red when light turns on while no one home -unknown_light=group.living_room - -[browser] - -[keyboard] - -[automation] -platform=state -alias=Sun starts shining - -state_entity_id=sun.sun -# Next two are optional, omit to match all -state_from=below_horizon -state_to=above_horizon - -execute_service=light.turn_off -service_entity_id=group.living_room - -[automation 2] -platform=time -alias=Beer o Clock - -time_hours=16 -time_minutes=0 -time_seconds=0 - -execute_service=notify.notify -service_data={"message":"It's 4, time for beer!"} diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index b7de8a6cd33..ee127976fae 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -114,7 +114,7 @@ def from_config_file(config_path, hass=None): config_dict = {} # check config file type - if(os.path.splitext(config_path)[1] == '.yaml'): + if os.path.splitext(config_path)[1] == '.yaml': # Read yaml config_dict = yaml.load(io.open(config_path, 'r')) else: From 461e0d03146f87254706996ca5ed5847a3375945 Mon Sep 17 00:00:00 2001 From: theolind Date: Sat, 28 Feb 2015 20:17:50 +0100 Subject: [PATCH 6/7] Now converting config values to dictionaries if they are None --- homeassistant/bootstrap.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index ee127976fae..dacb4a3bcf7 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -79,7 +79,8 @@ def from_config_dict(config, hass=None): # Make a copy because we are mutating it. # Convert it to defaultdict so components can always have config dict - config = defaultdict(dict, config) + # Convert values to dictionaries if they are None + config = defaultdict(dict, {key: value or {} for key, value in config.items()}) # Filter out the repeating and common config section [homeassistant] components = (key for key in config.keys() From 1206c2113cccb93870de728028252e364c6a62e3 Mon Sep 17 00:00:00 2001 From: theolind Date: Sat, 28 Feb 2015 20:31:26 +0100 Subject: [PATCH 7/7] Fixed style error, a line was too long --- homeassistant/bootstrap.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/homeassistant/bootstrap.py b/homeassistant/bootstrap.py index dacb4a3bcf7..56d77fdcb26 100644 --- a/homeassistant/bootstrap.py +++ b/homeassistant/bootstrap.py @@ -80,7 +80,8 @@ def from_config_dict(config, hass=None): # Make a copy because we are mutating it. # Convert it to defaultdict so components can always have config dict # Convert values to dictionaries if they are None - config = defaultdict(dict, {key: value or {} for key, value in config.items()}) + config = defaultdict( + dict, {key: value or {} for key, value in config.items()}) # Filter out the repeating and common config section [homeassistant] components = (key for key in config.keys()