mirror of
https://github.com/home-assistant/core.git
synced 2025-07-27 23:27:37 +00:00
Merge branch 'dev' of https://github.com/balloob/home-assistant into automation_confg_list
This commit is contained in:
commit
e1a7b8f988
@ -3,11 +3,6 @@ language: python
|
|||||||
python:
|
python:
|
||||||
- "3.4"
|
- "3.4"
|
||||||
install:
|
install:
|
||||||
- pip install -r requirements_all.txt
|
- script/bootstrap_server
|
||||||
- pip install flake8 pylint coveralls
|
|
||||||
script:
|
script:
|
||||||
- flake8 homeassistant
|
- script/cibuild
|
||||||
- pylint homeassistant
|
|
||||||
- coverage run -m unittest discover tests
|
|
||||||
after_success:
|
|
||||||
- coveralls
|
|
||||||
|
@ -103,6 +103,10 @@ def get_arguments():
|
|||||||
'--uninstall-osx',
|
'--uninstall-osx',
|
||||||
action='store_true',
|
action='store_true',
|
||||||
help='Uninstalls from OS X.')
|
help='Uninstalls from OS X.')
|
||||||
|
parser.add_argument(
|
||||||
|
'--restart-osx',
|
||||||
|
action='store_true',
|
||||||
|
help='Restarts on OS X.')
|
||||||
if os.name != "nt":
|
if os.name != "nt":
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
'--daemon',
|
'--daemon',
|
||||||
@ -216,6 +220,10 @@ def main():
|
|||||||
if args.uninstall_osx:
|
if args.uninstall_osx:
|
||||||
uninstall_osx()
|
uninstall_osx()
|
||||||
return
|
return
|
||||||
|
if args.restart_osx:
|
||||||
|
uninstall_osx()
|
||||||
|
install_osx()
|
||||||
|
return
|
||||||
|
|
||||||
# daemon functions
|
# daemon functions
|
||||||
if args.pid_file:
|
if args.pid_file:
|
||||||
|
@ -27,8 +27,7 @@ def trigger(hass, config, action):
|
|||||||
if CONF_AFTER in config:
|
if CONF_AFTER in config:
|
||||||
after = dt_util.parse_time_str(config[CONF_AFTER])
|
after = dt_util.parse_time_str(config[CONF_AFTER])
|
||||||
if after is None:
|
if after is None:
|
||||||
_LOGGER.error(
|
_error_time(config[CONF_AFTER], CONF_AFTER)
|
||||||
'Received invalid after value: %s', config[CONF_AFTER])
|
|
||||||
return False
|
return False
|
||||||
hours, minutes, seconds = after.hour, after.minute, after.second
|
hours, minutes, seconds = after.hour, after.minute, after.second
|
||||||
elif (CONF_HOURS in config or CONF_MINUTES in config
|
elif (CONF_HOURS in config or CONF_MINUTES in config
|
||||||
@ -63,27 +62,27 @@ def if_action(hass, config):
|
|||||||
CONF_BEFORE, CONF_AFTER, CONF_WEEKDAY)
|
CONF_BEFORE, CONF_AFTER, CONF_WEEKDAY)
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
if before is not None:
|
||||||
|
before = dt_util.parse_time_str(before)
|
||||||
|
if before is None:
|
||||||
|
_error_time(before, CONF_BEFORE)
|
||||||
|
return None
|
||||||
|
|
||||||
|
if after is not None:
|
||||||
|
after = dt_util.parse_time_str(after)
|
||||||
|
if after is None:
|
||||||
|
_error_time(after, CONF_AFTER)
|
||||||
|
return None
|
||||||
|
|
||||||
def time_if():
|
def time_if():
|
||||||
""" Validate time based if-condition """
|
""" Validate time based if-condition """
|
||||||
now = dt_util.now()
|
now = dt_util.now()
|
||||||
if before is not None:
|
if before is not None and now > now.replace(hour=before.hour,
|
||||||
time = dt_util.parse_time_str(before)
|
minute=before.minute):
|
||||||
if time is None:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
before_point = now.replace(hour=time.hour, minute=time.minute)
|
if after is not None and now < now.replace(hour=after.hour,
|
||||||
|
minute=after.minute):
|
||||||
if now > before_point:
|
|
||||||
return False
|
|
||||||
|
|
||||||
if after is not None:
|
|
||||||
time = dt_util.parse_time_str(after)
|
|
||||||
if time is None:
|
|
||||||
return False
|
|
||||||
|
|
||||||
after_point = now.replace(hour=time.hour, minute=time.minute)
|
|
||||||
|
|
||||||
if now < after_point:
|
|
||||||
return False
|
return False
|
||||||
|
|
||||||
if weekday is not None:
|
if weekday is not None:
|
||||||
@ -96,3 +95,11 @@ def if_action(hass, config):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
return time_if
|
return time_if
|
||||||
|
|
||||||
|
|
||||||
|
def _error_time(value, key):
|
||||||
|
""" Helper method to print error. """
|
||||||
|
_LOGGER.error(
|
||||||
|
"Received invalid value for '%s': %s", key, value)
|
||||||
|
if isinstance(value, int):
|
||||||
|
_LOGGER.error('Make sure you wrap time values in quotes')
|
||||||
|
@ -1,41 +1,31 @@
|
|||||||
"""
|
"""
|
||||||
Support for Foscam IP Cameras.
|
homeassistant.components.camera.foscam
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
This component provides basic support for Foscam IP cameras.
|
This component provides basic support for Foscam IP cameras.
|
||||||
|
|
||||||
As part of the basic support the following features will be provided:
|
As part of the basic support the following features will be provided:
|
||||||
-MJPEG video streaming
|
-MJPEG video streaming
|
||||||
|
|
||||||
To use this component, add the following to your config/configuration.yaml:
|
To use this component, add the following to your configuration.yaml file.
|
||||||
|
|
||||||
camera:
|
camera:
|
||||||
platform: foscam
|
platform: foscam
|
||||||
name: Door Camera
|
name: Door Camera
|
||||||
ip: 192.168.0.123
|
ip: 192.168.0.123
|
||||||
port: 88
|
port: 88
|
||||||
username: visitor
|
username: YOUR_USERNAME
|
||||||
password: password
|
password: YOUR_PASSWORD
|
||||||
|
|
||||||
camera 2:
|
Variables:
|
||||||
name: 'Second Camera'
|
|
||||||
...
|
|
||||||
camera 3:
|
|
||||||
name: 'Camera Three'
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
VARIABLES:
|
|
||||||
|
|
||||||
These are the variables for the device_data array:
|
|
||||||
|
|
||||||
ip
|
ip
|
||||||
*Required
|
*Required
|
||||||
The IP address of your foscam device
|
The IP address of your Foscam device.
|
||||||
|
|
||||||
username
|
username
|
||||||
*Required
|
*Required
|
||||||
The username of a visitor or operator of your camera.
|
The username of a visitor or operator of your camera. Oddly admin accounts
|
||||||
Oddly admin accounts don't seem to have access to take snapshots.
|
don't seem to have access to take snapshots.
|
||||||
|
|
||||||
password
|
password
|
||||||
*Required
|
*Required
|
||||||
@ -49,6 +39,8 @@ port
|
|||||||
*Optional
|
*Optional
|
||||||
The port that the camera is running on. The default is 88.
|
The port that the camera is running on. The default is 88.
|
||||||
|
|
||||||
|
For more details about this platform, please refer to the documentation at
|
||||||
|
https://home-assistant.io/components/camera.foscam.html
|
||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from homeassistant.helpers import validate_config
|
from homeassistant.helpers import validate_config
|
||||||
@ -72,9 +64,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
|||||||
|
|
||||||
# pylint: disable=too-many-instance-attributes
|
# pylint: disable=too-many-instance-attributes
|
||||||
class FoscamCamera(Camera):
|
class FoscamCamera(Camera):
|
||||||
"""
|
""" An implementation of a Foscam IP camera. """
|
||||||
An implementation of a Foscam IP camera.
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(self, device_info):
|
def __init__(self, device_info):
|
||||||
super(FoscamCamera, self).__init__()
|
super(FoscamCamera, self).__init__()
|
||||||
@ -94,7 +84,7 @@ class FoscamCamera(Camera):
|
|||||||
self._name, self._snap_picture_url)
|
self._name, self._snap_picture_url)
|
||||||
|
|
||||||
def camera_image(self):
|
def camera_image(self):
|
||||||
""" Return a still image reponse from the camera """
|
""" Return a still image reponse from the camera. """
|
||||||
|
|
||||||
# send the request to snap a picture
|
# send the request to snap a picture
|
||||||
response = requests.get(self._snap_picture_url)
|
response = requests.get(self._snap_picture_url)
|
||||||
@ -111,5 +101,5 @@ class FoscamCamera(Camera):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def name(self):
|
def name(self):
|
||||||
""" Return the name of this device """
|
""" Return the name of this device. """
|
||||||
return self._name
|
return self._name
|
||||||
|
@ -28,6 +28,14 @@ REQUIREMENTS = ['SoCo==0.11.1']
|
|||||||
|
|
||||||
_LOGGER = logging.getLogger(__name__)
|
_LOGGER = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# The soco library is excessively chatty when it comes to logging and
|
||||||
|
# causes a LOT of spam in the logs due to making a http connection to each
|
||||||
|
# speaker every 10 seconds. Quiet it down a bit to just actual problems.
|
||||||
|
_SOCO_LOGGER = logging.getLogger('soco')
|
||||||
|
_SOCO_LOGGER.setLevel(logging.ERROR)
|
||||||
|
_REQUESTS_LOGGER = logging.getLogger('requests')
|
||||||
|
_REQUESTS_LOGGER.setLevel(logging.ERROR)
|
||||||
|
|
||||||
SUPPORT_SONOS = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE |\
|
SUPPORT_SONOS = SUPPORT_PAUSE | SUPPORT_VOLUME_SET | SUPPORT_VOLUME_MUTE |\
|
||||||
SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | SUPPORT_SEEK
|
SUPPORT_PREVIOUS_TRACK | SUPPORT_NEXT_TRACK | SUPPORT_SEEK
|
||||||
|
|
||||||
|
@ -256,7 +256,7 @@ class Recorder(threading.Thread):
|
|||||||
""" Query the database. """
|
""" Query the database. """
|
||||||
try:
|
try:
|
||||||
with self.conn, self.lock:
|
with self.conn, self.lock:
|
||||||
_LOGGER.info("Running query %s", sql_query)
|
_LOGGER.debug("Running query %s", sql_query)
|
||||||
|
|
||||||
cur = self.conn.cursor()
|
cur = self.conn.cursor()
|
||||||
|
|
||||||
|
@ -70,7 +70,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
|
|||||||
data,
|
data,
|
||||||
config.get('name', DEFAULT_NAME),
|
config.get('name', DEFAULT_NAME),
|
||||||
config.get('unit_of_measurement'),
|
config.get('unit_of_measurement'),
|
||||||
config.get('correction_factor', None),
|
config.get('correction_factor', 1.0),
|
||||||
config.get('decimal_places', 0)
|
config.get('decimal_places', 0)
|
||||||
)])
|
)])
|
||||||
|
|
||||||
@ -108,12 +108,15 @@ class CommandSensor(Entity):
|
|||||||
self.data.update()
|
self.data.update()
|
||||||
value = self.data.value
|
value = self.data.value
|
||||||
|
|
||||||
if value is not None:
|
try:
|
||||||
if self._corr_factor is not None:
|
if value is not None:
|
||||||
self._state = round((int(value) * self._corr_factor),
|
if self._corr_factor is not None:
|
||||||
self._decimal_places)
|
self._state = round((float(value) * self._corr_factor),
|
||||||
else:
|
self._decimal_places)
|
||||||
self._state = value
|
else:
|
||||||
|
self._state = value
|
||||||
|
except ValueError:
|
||||||
|
self._state = value
|
||||||
|
|
||||||
|
|
||||||
# pylint: disable=too-few-public-methods
|
# pylint: disable=too-few-public-methods
|
||||||
|
@ -3,7 +3,6 @@ homeassistant.components.sensor.glances
|
|||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
Gathers system information of hosts which running glances.
|
Gathers system information of hosts which running glances.
|
||||||
|
|
||||||
|
|
||||||
Configuration:
|
Configuration:
|
||||||
|
|
||||||
To use the glances sensor you will need to add something like the following
|
To use the glances sensor you will need to add something like the following
|
||||||
|
@ -91,7 +91,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
_LOGGER.error(
|
_LOGGER.error(
|
||||||
"Connection error "
|
"Connection error "
|
||||||
"Please check your settings for OpenWeatherMap.")
|
"Please check your settings for OpenWeatherMap.")
|
||||||
return None
|
return False
|
||||||
|
|
||||||
data = WeatherData(owm, forecast, hass.config.latitude,
|
data = WeatherData(owm, forecast, hass.config.latitude,
|
||||||
hass.config.longitude)
|
hass.config.longitude)
|
||||||
|
@ -31,7 +31,7 @@ Details for the API : http://transport.opendata.ch
|
|||||||
"""
|
"""
|
||||||
import logging
|
import logging
|
||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
from requests import get
|
import requests
|
||||||
|
|
||||||
from homeassistant.util import Throttle
|
from homeassistant.util import Throttle
|
||||||
import homeassistant.util.dt as dt_util
|
import homeassistant.util.dt as dt_util
|
||||||
@ -53,8 +53,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
|
|||||||
try:
|
try:
|
||||||
for location in [config.get('from', None), config.get('to', None)]:
|
for location in [config.get('from', None), config.get('to', None)]:
|
||||||
# transport.opendata.ch doesn't play nice with requests.Session
|
# transport.opendata.ch doesn't play nice with requests.Session
|
||||||
result = get(_RESOURCE + 'locations?query=%s' % location,
|
result = requests.get(_RESOURCE + 'locations?query=%s' % location,
|
||||||
timeout=10)
|
timeout=10)
|
||||||
journey.append(result.json()['stations'][0]['name'])
|
journey.append(result.json()['stations'][0]['name'])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
_LOGGER.exception(
|
_LOGGER.exception(
|
||||||
@ -110,7 +110,7 @@ class PublicTransportData(object):
|
|||||||
def update(self):
|
def update(self):
|
||||||
""" Gets the latest data from opendata.ch. """
|
""" Gets the latest data from opendata.ch. """
|
||||||
|
|
||||||
response = get(
|
response = requests.get(
|
||||||
_RESOURCE +
|
_RESOURCE +
|
||||||
'connections?' +
|
'connections?' +
|
||||||
'from=' + self.start + '&' +
|
'from=' + self.start + '&' +
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
"""Helpers to install PyPi packages."""
|
"""Helpers to install PyPi packages."""
|
||||||
import os
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
import pkg_resources
|
import pkg_resources
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
@ -15,25 +15,24 @@ def install_package(package, upgrade=True, target=None):
|
|||||||
"""Install a package on PyPi. Accepts pip compatible package strings.
|
"""Install a package on PyPi. Accepts pip compatible package strings.
|
||||||
Return boolean if install successfull."""
|
Return boolean if install successfull."""
|
||||||
# Not using 'import pip; pip.main([])' because it breaks the logger
|
# Not using 'import pip; pip.main([])' because it breaks the logger
|
||||||
args = [sys.executable, '-m', 'pip', 'install', '--quiet', package]
|
|
||||||
|
|
||||||
if upgrade:
|
|
||||||
args.append('--upgrade')
|
|
||||||
if target:
|
|
||||||
args += ['--target', os.path.abspath(target)]
|
|
||||||
|
|
||||||
with INSTALL_LOCK:
|
with INSTALL_LOCK:
|
||||||
if check_package_exists(package, target):
|
if check_package_exists(package, target):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
_LOGGER.info('Attempting install of %s', package)
|
_LOGGER.info('Attempting install of %s', package)
|
||||||
|
args = [sys.executable, '-m', 'pip', 'install', '--quiet', package]
|
||||||
|
if upgrade:
|
||||||
|
args.append('--upgrade')
|
||||||
|
if target:
|
||||||
|
args += ['--target', os.path.abspath(target)]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
return 0 == subprocess.call(args)
|
return 0 == subprocess.call(args)
|
||||||
except subprocess.SubprocessError:
|
except subprocess.SubprocessError:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def check_package_exists(package, target=None):
|
def check_package_exists(package, target):
|
||||||
"""Check if a package exists.
|
"""Check if a package exists.
|
||||||
Returns True when the requirement is met.
|
Returns True when the requirement is met.
|
||||||
Returns False when the package is not installed or doesn't meet req."""
|
Returns False when the package is not installed or doesn't meet req."""
|
||||||
@ -43,16 +42,5 @@ def check_package_exists(package, target=None):
|
|||||||
# This is a zip file
|
# This is a zip file
|
||||||
req = pkg_resources.Requirement.parse(urlparse(package).fragment)
|
req = pkg_resources.Requirement.parse(urlparse(package).fragment)
|
||||||
|
|
||||||
if target:
|
return any(dist in req for dist in
|
||||||
work_set = pkg_resources.WorkingSet([target])
|
pkg_resources.find_distributions(target))
|
||||||
search_fun = work_set.find
|
|
||||||
|
|
||||||
else:
|
|
||||||
search_fun = pkg_resources.get_distribution
|
|
||||||
|
|
||||||
try:
|
|
||||||
result = search_fun(req)
|
|
||||||
except (pkg_resources.DistributionNotFound, pkg_resources.VersionConflict):
|
|
||||||
return False
|
|
||||||
|
|
||||||
return bool(result)
|
|
||||||
|
9
script/bootstrap
Executable file
9
script/bootstrap
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# script/bootstrap: Resolve all dependencies that the application requires to
|
||||||
|
# run.
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
script/bootstrap_server
|
||||||
|
script/bootstrap_frontend
|
5
script/bootstrap_frontend
Executable file
5
script/bootstrap_frontend
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
echo "Bootstrapping frontend..."
|
||||||
|
cd homeassistant/components/frontend/www_static/home-assistant-polymer
|
||||||
|
npm install
|
||||||
|
npm run setup_js_dev
|
||||||
|
cd ../../../../..
|
10
script/bootstrap_server
Executable file
10
script/bootstrap_server
Executable file
@ -0,0 +1,10 @@
|
|||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
echo "Update the submodule to latest version..."
|
||||||
|
git submodule update
|
||||||
|
|
||||||
|
echo "Installing dependencies..."
|
||||||
|
python3 -m pip install --upgrade -r requirements_all.txt
|
||||||
|
|
||||||
|
echo "Installing development dependencies.."
|
||||||
|
python3 -m pip install --upgrade flake8 pylint coveralls pytest pytest-cov
|
@ -1,12 +1,8 @@
|
|||||||
# Builds the frontend for production
|
# Builds the frontend for production
|
||||||
|
|
||||||
# If current pwd is scripts, go 1 up.
|
cd "$(dirname "$0")/.."
|
||||||
if [ ${PWD##*/} == "scripts" ]; then
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
cd homeassistant/components/frontend/www_static/home-assistant-polymer
|
cd homeassistant/components/frontend/www_static/home-assistant-polymer
|
||||||
npm install
|
|
||||||
npm run frontend_prod
|
npm run frontend_prod
|
||||||
|
|
||||||
cp bower_components/webcomponentsjs/webcomponents-lite.min.js ..
|
cp bower_components/webcomponentsjs/webcomponents-lite.min.js ..
|
@ -3,10 +3,7 @@
|
|||||||
# apt-get install cython3 libudev-dev python-sphinx python3-setuptools
|
# apt-get install cython3 libudev-dev python-sphinx python3-setuptools
|
||||||
# pip3 install cython
|
# pip3 install cython
|
||||||
|
|
||||||
# If current pwd is scripts, go 1 up.
|
cd "$(dirname "$0")/.."
|
||||||
if [ ${PWD##*/} == "scripts" ]; then
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ ! -d build ]; then
|
if [ ! -d build ]; then
|
||||||
mkdir build
|
mkdir build
|
7
script/cibuild
Executable file
7
script/cibuild
Executable file
@ -0,0 +1,7 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# script/cibuild: Setup environment for CI to run tests. This is primarily
|
||||||
|
# designed to run on the continuous integration server.
|
||||||
|
|
||||||
|
script/test coverage
|
||||||
|
coveralls
|
@ -3,10 +3,7 @@
|
|||||||
# Optional: pass in a timezone as first argument
|
# Optional: pass in a timezone as first argument
|
||||||
# If not given will attempt to mount /etc/localtime
|
# If not given will attempt to mount /etc/localtime
|
||||||
|
|
||||||
# If current pwd is scripts, go 1 up.
|
cd "$(dirname "$0")/.."
|
||||||
if [ ${PWD##*/} == "scripts" ]; then
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
docker build -t home-assistant-dev .
|
docker build -t home-assistant-dev .
|
||||||
|
|
@ -1,10 +1,7 @@
|
|||||||
# Open a docker that can be used to debug/dev python-openzwave
|
# Open a docker that can be used to debug/dev python-openzwave
|
||||||
# Pass in a command line argument to build
|
# Pass in a command line argument to build
|
||||||
|
|
||||||
# If current pwd is scripts, go 1 up.
|
cd "$(dirname "$0")/.."
|
||||||
if [ ${PWD##*/} == "scripts" ]; then
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ $# -gt 0 ]
|
if [ $# -gt 0 ]
|
||||||
then
|
then
|
3
scripts/hass-daemon → script/hass-daemon
Normal file → Executable file
3
scripts/hass-daemon → script/hass-daemon
Normal file → Executable file
@ -34,6 +34,7 @@ RUN_AS="USER"
|
|||||||
PID_FILE="/var/run/hass.pid"
|
PID_FILE="/var/run/hass.pid"
|
||||||
CONFIG_DIR="/var/opt/homeassistant"
|
CONFIG_DIR="/var/opt/homeassistant"
|
||||||
FLAGS="-v --config $CONFIG_DIR --pid-file $PID_FILE --daemon"
|
FLAGS="-v --config $CONFIG_DIR --pid-file $PID_FILE --daemon"
|
||||||
|
REDIRECT="> $CONFIG_DIR/home-assistant.log 2>&1"
|
||||||
|
|
||||||
start() {
|
start() {
|
||||||
if [ -f $PID_FILE ] && kill -0 $(cat $PID_FILE); then
|
if [ -f $PID_FILE ] && kill -0 $(cat $PID_FILE); then
|
||||||
@ -41,7 +42,7 @@ start() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
echo 'Starting service…' >&2
|
echo 'Starting service…' >&2
|
||||||
local CMD="$PRE_EXEC hass $FLAGS;"
|
local CMD="$PRE_EXEC hass $FLAGS $REDIRECT;"
|
||||||
su -c "$CMD" $RUN_AS
|
su -c "$CMD" $RUN_AS
|
||||||
echo 'Service started' >&2
|
echo 'Service started' >&2
|
||||||
}
|
}
|
9
script/lint
Executable file
9
script/lint
Executable file
@ -0,0 +1,9 @@
|
|||||||
|
# Run style checks
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
echo "Checking style with flake8..."
|
||||||
|
flake8 homeassistant
|
||||||
|
|
||||||
|
echo "Checking style with pylint..."
|
||||||
|
pylint homeassistant
|
8
script/server
Executable file
8
script/server
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# script/server: Launch the application and any extra required processes
|
||||||
|
# locally.
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
python3 -m homeassistant -c config
|
5
script/setup
Executable file
5
script/setup
Executable file
@ -0,0 +1,5 @@
|
|||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
git submodule init
|
||||||
|
script/bootstrap
|
||||||
|
python3 setup.py develop
|
16
script/test
Executable file
16
script/test
Executable file
@ -0,0 +1,16 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# script/test: Run test suite for application. Optionallly pass in a path to an
|
||||||
|
# individual test file to run a single test.
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
script/lint
|
||||||
|
|
||||||
|
echo "Running tests..."
|
||||||
|
|
||||||
|
if [ "$1" = "coverage" ]; then
|
||||||
|
py.test --cov homeassistant tests
|
||||||
|
else
|
||||||
|
py.test tests
|
||||||
|
fi
|
8
script/update
Executable file
8
script/update
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
# script/update: Update application to run for its current checkout.
|
||||||
|
|
||||||
|
cd "$(dirname "$0")/.."
|
||||||
|
|
||||||
|
git pull
|
||||||
|
git submodule update
|
@ -1,9 +0,0 @@
|
|||||||
# Run style checks
|
|
||||||
|
|
||||||
# If current pwd is scripts, go 1 up.
|
|
||||||
if [ ${PWD##*/} == "scripts" ]; then
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
flake8 homeassistant
|
|
||||||
pylint homeassistant
|
|
@ -1,10 +0,0 @@
|
|||||||
# If current pwd is scripts, go 1 up.
|
|
||||||
if [ ${PWD##*/} == "scripts" ]; then
|
|
||||||
cd ..
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$1" = "coverage" ]; then
|
|
||||||
coverage run -m unittest discover tests
|
|
||||||
else
|
|
||||||
python3 -m unittest discover tests
|
|
||||||
fi
|
|
@ -1,6 +0,0 @@
|
|||||||
echo "The update script has been deprecated since Home Assistant v0.7"
|
|
||||||
echo
|
|
||||||
echo "Home Assistant is now distributed via PyPi and can be installed and"
|
|
||||||
echo "upgraded by running: pip3 install --upgrade homeassistant"
|
|
||||||
echo
|
|
||||||
echo "If you are developing a new feature for Home Assistant, run: git pull"
|
|
@ -285,9 +285,9 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
'trigger': {
|
'trigger': {
|
||||||
'platform': 'time',
|
'platform': 'time',
|
||||||
'hours': 0,
|
'hours': 1,
|
||||||
'minutes': 0,
|
'minutes': 2,
|
||||||
'seconds': 0,
|
'seconds': 3,
|
||||||
},
|
},
|
||||||
'action': {
|
'action': {
|
||||||
'execute_service': 'test.automation'
|
'execute_service': 'test.automation'
|
||||||
@ -296,7 +296,7 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
}))
|
}))
|
||||||
|
|
||||||
fire_time_changed(self.hass, dt_util.utcnow().replace(
|
fire_time_changed(self.hass, dt_util.utcnow().replace(
|
||||||
hour=0, minute=0, second=0))
|
hour=1, minute=2, second=3))
|
||||||
|
|
||||||
self.hass.pool.block_till_done()
|
self.hass.pool.block_till_done()
|
||||||
self.assertEqual(1, len(self.calls))
|
self.assertEqual(1, len(self.calls))
|
||||||
@ -320,6 +320,30 @@ class TestAutomationTime(unittest.TestCase):
|
|||||||
self.hass.pool.block_till_done()
|
self.hass.pool.block_till_done()
|
||||||
self.assertEqual(1, len(self.calls))
|
self.assertEqual(1, len(self.calls))
|
||||||
|
|
||||||
|
@patch('homeassistant.components.automation.time._LOGGER.error')
|
||||||
|
def test_if_not_fires_using_wrong_after(self, mock_error):
|
||||||
|
""" YAML translates time values to total seconds. This should break the
|
||||||
|
before rule. """
|
||||||
|
self.assertTrue(automation.setup(self.hass, {
|
||||||
|
automation.DOMAIN: {
|
||||||
|
'trigger': {
|
||||||
|
'platform': 'time',
|
||||||
|
'after': 3605,
|
||||||
|
# Total seconds. Hour = 3600 second
|
||||||
|
},
|
||||||
|
'action': {
|
||||||
|
'execute_service': 'test.automation'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
|
||||||
|
fire_time_changed(self.hass, dt_util.utcnow().replace(
|
||||||
|
hour=1, minute=0, second=5))
|
||||||
|
|
||||||
|
self.hass.pool.block_till_done()
|
||||||
|
self.assertEqual(0, len(self.calls))
|
||||||
|
self.assertEqual(2, mock_error.call_count)
|
||||||
|
|
||||||
def test_if_action_before(self):
|
def test_if_action_before(self):
|
||||||
automation.setup(self.hass, {
|
automation.setup(self.hass, {
|
||||||
automation.DOMAIN: {
|
automation.DOMAIN: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user