Compare commits

..

15 Commits

Author SHA1 Message Date
Paulus Schoutsen db3bfad0b5 Merge pull request #3359 from home-assistant/hotfix-0-28-2
0.28.2
2016-09-12 21:28:57 -07:00
Teagan Glenn 2b1416c514 Automatic polling (#3360)
* Test updating automatic

* Scan interval

* Schedule scan every time delta

* Pass around has

* Recursive issue

* Method invocation

* Oops

* Set up poll

* Default argument value

* Unused import

* Semicolon

* Fix tests

* Linting

* Unneeded throttle as it's handled by time event

* Use track time change event listener

* Disable lint rule

* Attribute removed - removing test

* Debug instead of info

* Unused import
2016-09-12 19:59:53 -07:00
Paulus Schoutsen b9154158e8 Version bump to 0.28.2 2016-09-12 18:33:36 -07:00
Nick Vella b43bf62347 Add open/closed state for open_cover and close_cover in SERVICE_TO_STATE (#3180)
* Add open/closed state mapping for open_cover and close_cover

* Add 'open', 'closed' for open/close_cover_tilt

* Revert "Add 'open', 'closed' for open/close_cover_tilt"

This reverts commit e45582d439.
2016-09-12 18:33:11 -07:00
John Arild Berentsen c6b6ab1b79 Bugfix ecobee: inverted high and low temps and enforce int to temps (#3325)
* inverted high and low temps

* Looks like somethings are mixed up

* Added debugentires

* Added debugentires 2

* Enforce int on temperatures
2016-09-12 18:33:11 -07:00
John Arild Berentsen 07148fc580 Missing garage door detection (#3349) 2016-09-12 18:33:11 -07:00
Pascal Vizeli bc600b8f32 Bugfix voluptuous on recorder (#3350) 2016-09-12 18:33:11 -07:00
David-Leon Pohl dd4611064f Bugfix pilight component (#3355)
* BUG Message data cannot be changed thus use voluptuous to ensure format

* Pilight daemon expects JSON serializable data

Thus dict is needed and not a mapping proxy.

* Add explanation why dict as message data is needed

* Use more obvious voluptuous validation scheme

* Pylint:  Trailing whitespace
2016-09-12 18:33:11 -07:00
Paulus Schoutsen 71aa1a2f3c Merge pull request #3332 from home-assistant/hotfix-0-28-1
Hotfix 0 28 1
2016-09-11 22:42:16 -07:00
Paulus Schoutsen 0cfa5e5f67 Version bump to 0.28.1 2016-09-11 22:28:53 -07:00
Paulus Schoutsen f0ec51711c Bugfix group order (#3323)
* Add ordered dict config validator

* Have group component use ordered dict config validator

* Improve config_validation testing

* update doc string config_validation.ordered_dict

* validate full dict entries

* Further simplify ordered_dict validator.

* Lint fix
2016-09-11 22:27:47 -07:00
Teagan Glenn d6ca930427 Automatic Device Tracker Bug Fix (#3330)
* Iterate over items

* Pass display name as host name
2016-09-11 22:27:47 -07:00
John Arild Berentsen 7bce8bc33f Revert only add 1 device (#3324) 2016-09-11 22:27:47 -07:00
Marcelo Moreira de Mello 36785296ce Fixed voluptuous to accept string instead positive_int for CODE on Simplisafe (#3310) 2016-09-11 22:27:47 -07:00
Fabian Affolter 1b46ed5045 0.28 (#3288)
* Backend support for importing waypoints from owntracks as HA zones

* Added test for Owntracks waypoints import

* Backend support for importing waypoints from owntracks as HA zones

* Added test for Owntracks waypoints import

* Removed redundant assignment to CONF_WAYPOINT_IMPORT_USER

* Fixed zone test break and code style issues

* Fixed style issues

* Fixed variable scope issues for entities

* Fixed E302

* Do not install pip packages in tests

* EventBus: return function to unlisten

* Convert automation to entities with services

* Refactored zone creation based on code review feedback, enhanced configuration

* Added unit test to enhance waypoint_whitelist coverage

* Fix JSON encoder issue in recorder

* Fix tests docstring

* * Improved zone naming in waypoint import
* Added more test coverage for owntracks and zone

* Back to 0.28.0.dev0

* Code review feedback from @pavoni

* Added bitfield of features for flux_led since we are supporting effects

* Host should be optional for apcupsd component (#3072)

* Use voluptuous for file (#3049)

* Zwave climate Bugfix: if some setpoints have different units, we should fetch the o… (#3078)

* Bugfix: if some setpoints have different units, we should fetch the one that are active.

* Move order of population for first time detection

* Default to config if None unit_of_measurement

* unit fix (#3083)

* humidity slider (#3088)

* If device was off target temp was null. Default to Heating setpoint (#3091)

* Fix linting

* Upgrade pyuserinput to 0.1.11 (#3068)

* Upgrade pyowm to 2.4.0 (#3067)

* improve isfile validation check (#3101)

* Refactor notification titles to allow for them to be None, this also includes a change in Telegram to only include the title if it's present, and to use a Markdown parse mode for messages (#3100)

* Fix broken test

* rfxtrx sensor clean up

* Bitcoin sensor use warning instead of error (#3103)

* Use voluptuous for HDMI CEC & CONF_DEVICES constants (#3107)

* Update voluptuous for nest (#3109)

* Update configuration check
* Extend platform

* Fix for BLE device tracker (#3019)

* Bug fix tracked devices
* Added scan_duration configuration parameter

* fix homematic climate implementation (#3114)

* Allow 'None' MAC to be loaded from known_devices (#3102)

* Use voluptuous for xmpp (#3127)

* Use voluptuous for twitter (#3126)

* Use voluptuous for Fritzbox and DDWRT (#3122)

* Use Voluptuous for BT Home Hub (#3121)

* Use voluptuous for syslog (#3120)

* Use voluptuous for Aruba (#3119)

* Use constants, update configuration check, and ordering (Pilight) (#3118)

* Use contants, update configuration check, and ordering

* Fix pylint issue

* Migrate to voluptuous (#3113)

* Fix typo (#3108)

* Migrate to voluptuous (#3106)

* Update voluptuous (#3104)

* Climate and cover bugfix (#3097)

* Avoid None comparison for zwave cover.

* Just rely on unit from config for unit_of_measurement

* Explicit return None

* Mqtt (#11)

* Explicit return None

* Missing service and wrong service name defined

* Mqtt state was inverted, and never triggering

* Migrate to voluptuous (#3096)

* Migrate to voluptuous (#3084)

* Fixed Homematic cover (#3116)

* Migrate to voluptuous (#3069)

🐬

* Migrate to voluptuous (#3066)

🐬

* snapcast update (#3012)

* snapcast update

* snapcast update

* validate config

* use conf constants

* orvibo updates (#3006)

🐬

* Update frontend

* move units to temperature for climate zwave. wrong state was sent to mqtt cove

* Use voluptuous for instapush (#3132)

* Use voluptuous for Octoprint (#3111)

* Migrate to voluptuous

* Fix pylint issues

* Add missing docstrings (fix PEP257 issues) (#3098)

* Add missing docstrings (fix PEP257 issues)

* Finish sentence

* Updated braviatv's braviarc version to 0.3.4 (#2997)

* Updated braviarc version to 0.3.4

* Updated braviarc version to requirements_all.txt

* Use voluptuous for Acer projector switch (#3077)

🐬

* Use voluptuous for twilio (#3134)

* Use voluptuous for webostv (#3135)

* Use voluptuous for Command line platforms (#2968)

* Migrate to voluptuous

* Fix pylint issues

* Remove FIXME

* Split setup test

* Test with bootstrap

* Remove lon and lat

* Fix pylint issues

* Add coinmarketcap sensor (#3064)

* Migrate to voluptuous (#3142)

🐬

* Back out insteon hub and fan changes (#3062)

* Move details to docs (#3146)

* Update frontend

* Use constants (#3148)

* Update ordering (#3149)

* Migrate to voluptuous (#3092)

* Display the error instead of the traceback (notify.slack) (#3079)

* Display the error instead of the traceback

* Remove name for check

* Automatic ODB device tracker & device tracker attributes (#3035)

* Migrate to voluptuous (#3173)

* Add voluptuous for tomato and SNMP (#3172)

* Improve voluptuous and login errors for Asus device tracker (#3170)

* Add exclude option to nmap device tracker (#2983)

* Add exclude option to nmap device tracker

Adds an optional exclude paramater to nmap device tracker.
Devices specified in the exclude list will never be scanned
by nmap. This can help to reduce log spam.

ex:
```
device_tracker:
  - platform: nmap_tracker
    hosts: 10.0.0.1/24
    home_interval: 1
    interval_seconds: 12
    consider_home: 120
    track_new_devices: yes
    exclude:
      - 10.0.0.2
      - 10.0.0.1
```

* Handle optional exclude

* Style fixed

* Added Xbox Live component (#3013)

* Added Xbox Live component

* Added Xbox Live sensor to coveralls

* Added init success checks

* Added entity id

* Adding link_names to post.message call (#3167)

If you do not turn link_names on, Slack will not highlight @channel and @username messages.

* Allow https (fixes #3150) (#3155)

* Use constants (#3156)

* Bugfix: ctach Runtime errors (#3153)

"RuntimeError: Disable scan failed" has been seen in a live installation

* Migrate to voluptuous (#3166)

🐬

* Migrate to voluptuous (#3164)

🐬

* Migrate to voluptuous (#3163)

🐬

* Migrate to voluptuous (#3162)

🐬 and 🍪 for fixing quotes!

* Exclude www_static from pydocstyle linting (#3175)

🐬

* Migrate to voluptuous (#3174)

* Migrate to voluptuous (#3171)

* Use voluptuous for mFi switch (#3168)

* Migrate to voluptuous

* Take change configuration into account

* Migrate to voluptuous (#3144)

🐬

* Add the occupancy sensor_class (#3176)

Such a complicated PR

* Update frontend

* Use voluptuous for Unifi, Ubus (#3125)

* Using alert with Hue maintains prior state (#3147)

* When using flash with hue, dont change the on/off state of the light so that it will naturally return to its previous state once flash is complete

* ATTR_FLASH not ATTR_EFFECT

* MQTT fan platform (#3095)

* Add fan.mqtt, allow brightness to be passed and mapped to a fan speed for compatibility with emulated_hue

* Pylint/Flake8 fixes

* Remove brightness

* Add more features, like custom oscillation/speed payloads and setting the speed list

* Flake8 fixes

* flake8/pylint fixes

* Use constants

* block fan.mqtt from coverage

* Fix oscillating comment

* Add Sphinx API doc generation (#3029)

* add's sphinx project to docs/ dir
* include core/helpers autodocs for API reference

* Allow reloading automation without restarting HA (#3002)

* Migrate to voluptuous (#3182)

🐬

* Migrate to voluptuous (#3179)

🐬

* Added scale and offset to the Temper component (#2853)

🐬

* Use voluptuous for BT and Owntracks device trackers (#3187)

🐬

* Correct binary_sensor.ecobee docs URL

* Use voluptuous for Hikvisioncam switch (#3184)

* Migrate to voluptuous

* Use vol.Optional

* Use voluptuous for Edimax (#3178)

🐬

* Use voluptuous for Bravia TV (#3165)

🐬

* Added support to 'effect: random' to Osram Lightify lights (#3192)

* Added support to 'effect: random' to Osram Lightify lights

* removed extra line not required

* Use voluptuous for message_bird, sendgrid (#3136)

* Try out the RTD theme

* Doc updates

* Update voluptuous for existing notify platforms (#3133)

* Update voluptuous for exists notify platforms

* fix constants

* Simple trend sensor. (#3073)

* First cut of trend sensor.

* Tidy.

* Migrate to voluptuous (#3193)

* Migrate to voluptuous (#3194)

🐬

* Migrate to voluptuous (#3197)

* Migrate to voluptuous (#3198)

🐬

* Use extend of PLATFORM_SCHEMA (#3199)

* Migrate to voluptuous (#3202)

🐬

* Updated to use the occupancy sensor_class (#3204)

🐬

* Migrate to voluptuous (#3206)

* Migrate to voluptuous (#3207)

* Migrate to voluptuous (#3208)

🐬

* Migrate to voluptuous (#3209)

🐬

* Migrate to voluptuous (#3214)

* Use voluptuous for SqueezeBox (#3212)

* Migrate to voluptuous

* Remove name

* Migrate to voluptuous and upgrade uber_rides to 0.2.5 (#3181)

* Migrate to voluptuous (#3200)

🐬

* Use Voluptuous for Luci and Netgear device trackers (#3123)

* Use Voluptuous for Luci and NEtgear device trackers

* str_schema shortcut

* Undo str_schema

* change update handling with variable for breack CCU2 (#3215)

* Update ordering (#3216)

* Docs update

* Flake8/pylint

* Add new docs requirements

* Update email validation (#3228)

🐬

* Fix email validation (fixes #3138) (#3227)

* Upgrade slacker to 0.9.25 (#3224)

* Upgrade psutil to 4.3.1 (#3223)

* Upgrade gps3 to 0.33.3 (#3222)

* Upgrade Werkzeug to 0.11.11 (#3220)

* Upgrade sendgrid to 3.4.0 (#3226)

* Bluetooth: keep looking for new devices (#3201)

* keep looking for new devices

* Update bluetooth_tracker.py

* change default value for tracking new devices

* remove commented code

* dlink switch added device state attributes and support for legacy firmware (#3211)

* Use voluptuous for free mobile (#3236)

* Use voluptuous for nma (#3241)

* Improve 1-Wire device family detection and error checking. Use volupt… (#3233)

* Improve 1-Wire device family detection and error checking. Use voluptuous

* Fix detection of gpio connected devices

* Replace rollershutter and garage door with cover, add fan (#3242)

* Use voluptuous for Alarm.com (#3229)

* Use voluptuous for gntp (#3237)

* Use voluptuous for pushbullet, pushetta and pushover (#3240)

* Migrate to voluptuous (#3230)

🐬

* Fix mFi sensors in uninitialized state (#3246)

If mFi sensors are identified but not fully assigned they can
have no tag value, and mficlient throws a ValueError to signal this.
This patch handles that case by considering such devices to always
be STATE_OFF.

* Use voluptuous for PulseAudio Loopback (#3160)

* Migrate to voluptuous

* Fix conf var

* Use voluptuous for Verisure (#3169)

* Migrate to voluptuous

* Update type and add missing config variable

* thread safe modbus (#3188)

*  Upgraded fitbit to version 0.2.3 which fixed oauthlib.oauth2.rfc6749.errors.TokenExpiredError: (token_expired) (#3244)

* update ffmpeg version to 0.10 add get image to camera (#3235)

* Migrate to voluptuous (#3234)

* fix bugfix with unique_id (#3217)

* Zwave climate fix and wink cover. (#3205)

* Fixes setpoint get was done outside loop

* zxt_120

* Wink not migrated to cover

* Clarifying debug

* too long line

* Only add 1 device entity

* Owntracks voluptuous fix (#3191)

* Zwave set temperature fix (#3221)

* If device was off set target temp would not work.

* Changed to use a workaround just for Horstmann HRT4-ZW Zwave Thermostat

* Wrong Horseman id

* style changes

* Change PR to suggestion on gitter (#3243)

* Reload groups (#3203)

* Allow reloading groups without restart

* Test to make sure automation listeners are removed.

* Remove unused imports for group tests

* Simplify group config validation

* Add prepare_reload function to entity component

* Migrate group to use entity_component.prepare_reload

* Migrate automation to use entity_component.prepare_reload

* Clean up group.get_entity_ids

* Use cv.boolean for group config validation

* fix remove listener (#3196)

* Add linux battery sensor (#3238)

* protect service data for changes in calls (#3249)

* protect service data for changes in calls

* change handling

* move MappingProxyType to service call

* Fix issue #3250 (#3253)

* Minor Ecobee changes (#3131)

* Update configuration check, ordering, and constants

* Make API key optional

* issue #3250

* Add voluptuous to ecobee (#3257)

* Use constants and update ordering (#3261)

* Add support for complex template structures to data_template (#3255)

* Improve yaml fault tolerance and handle check_config border cases (#3159)

* Use voluptuous for nx584 alarm (#3231)

* Migrate to voluptuous

* Fix pylint issue

* fastdotcom from pypi (#3269)

* Use constants and update ordering (#3268)

🐬

* Use constants and update ordering (#3267)

🐬

* Add additional template for custom date formats (#3262)

I can live with a few visual line breaks 🐬

* Use constants and update ordering (#3266)

* Updated  braviatv's braviarc version to 0.3.5 (#3271)

* Use voluptuous for Device Sun Light Trigger (#3105)

* Migrate to voluptuous

* Use default

* Point to master till archive is back (#3285)

* Pi-Hole statistics sensor (#3158)

* Add Pi-Hole sensor

* Update docstrings and remove print()

* Use None for payload

* Added stuff for support range setting (#3189)

* cleanup Homematic code (#3291)

* cleanup old code

* cleanup round 2

* remove unwanted platforms

* Update frontend

* Hotfix for #3100 (#3302)

* Fix TP-Link Archer C7 long passwords (#3225)

* Fix tplink C7 long passwords

Fixes an issue where passwords longer than 15 chars could not log in to Archer C7 routers.

* Truncate in correct place

* Add comment about TP-Link C7 pass truncation

* Fix lint error

* Truncate comment at 79 chars not 80

* modbus write registers service (#3252)

* Fix bloomsky platform discovery (#3303)

* Remove dev tag
2016-09-10 18:22:58 -07:00
15 changed files with 139 additions and 79 deletions
@@ -26,7 +26,7 @@ DEFAULT_NAME = 'SimpliSafe'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_PASSWORD): cv.string,
vol.Required(CONF_USERNAME): cv.string,
vol.Optional(CONF_CODE): cv.positive_int,
vol.Optional(CONF_CODE): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
})
+12 -7
View File
@@ -116,9 +116,6 @@ class Thermostat(ClimateDevice):
return self.target_temperature_low
elif self.operation_mode == 'cool':
return self.target_temperature_high
else:
return (self.target_temperature_low +
self.target_temperature_high) / 2
@property
def target_temperature_low(self):
@@ -223,19 +220,27 @@ class Thermostat(ClimateDevice):
"""Set new target temperature."""
if kwargs.get(ATTR_TEMPERATURE) is not None:
temperature = kwargs.get(ATTR_TEMPERATURE)
low_temp = temperature - 1
high_temp = temperature + 1
low_temp = int(temperature)
high_temp = int(temperature)
if kwargs.get(ATTR_TARGET_TEMP_LOW) is not None and \
kwargs.get(ATTR_TARGET_TEMP_HIGH) is not None:
low_temp = kwargs.get(ATTR_TARGET_TEMP_LOW)
high_temp = kwargs.get(ATTR_TARGET_TEMP_HIGH)
high_temp = int(kwargs.get(ATTR_TARGET_TEMP_LOW))
low_temp = int(kwargs.get(ATTR_TARGET_TEMP_HIGH))
if self.hold_temp:
self.data.ecobee.set_hold_temp(self.thermostat_index, low_temp,
high_temp, "indefinite")
_LOGGER.debug("Setting ecobee hold_temp to: low=%s, is=%s, "
"high=%s, is=%s", low_temp, isinstance(
low_temp, (int, float)), high_temp,
isinstance(high_temp, (int, float)))
else:
self.data.ecobee.set_hold_temp(self.thermostat_index, low_temp,
high_temp)
_LOGGER.debug("Setting ecobee temp to: low=%s, is=%s, "
"high=%s, is=%s", low_temp, isinstance(
low_temp, (int, float)), high_temp,
isinstance(high_temp, (int, float)))
def set_operation_mode(self, operation_mode):
"""Set HVAC mode (auto, auxHeatOnly, cool, heat, off)."""
@@ -70,8 +70,6 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
node = zwave.NETWORK.nodes[discovery_info[ATTR_NODE_ID]]
value = node.values[discovery_info[ATTR_VALUE_ID]]
value.set_change_verified(False)
if value.index != 1: # Only add 1 device
return
add_devices([ZWaveClimate(value, temp_unit)])
_LOGGER.debug("discovery_info=%s and zwave.NETWORK=%s",
discovery_info, zwave.NETWORK)
+3 -1
View File
@@ -28,8 +28,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
pywink.set_bearer_token(token)
add_devices(WinkCoverDevice(shade) for shade, door in
add_devices(WinkCoverDevice(shade) for shade in
pywink.get_shades())
add_devices(WinkCoverDevice(door) for door in
pywink.get_garage_doors())
class WinkCoverDevice(WinkDevice, CoverDevice):
@@ -338,7 +338,7 @@ class Device(Entity):
attr[ATTR_BATTERY] = self.battery
if self.attributes:
for key, value in self.attributes:
for key, value in self.attributes.items():
attr[key] = value
return attr
@@ -15,12 +15,11 @@ from homeassistant.components.device_tracker import (PLATFORM_SCHEMA,
ATTR_ATTRIBUTES)
from homeassistant.const import CONF_USERNAME, CONF_PASSWORD
import homeassistant.helpers.config_validation as cv
from homeassistant.util import Throttle, datetime as dt_util
from homeassistant.helpers.event import track_utc_time_change
from homeassistant.util import datetime as dt_util
_LOGGER = logging.getLogger(__name__)
MIN_TIME_BETWEEN_SCANS = timedelta(seconds=30)
CONF_CLIENT_ID = 'client_id'
CONF_SECRET = 'secret'
CONF_DEVICES = 'devices'
@@ -53,7 +52,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_scanner(hass, config: dict, see):
"""Validate the configuration and return an Automatic scanner."""
try:
AutomaticDeviceScanner(config, see)
AutomaticDeviceScanner(hass, config, see)
except requests.HTTPError as err:
_LOGGER.error(str(err))
return False
@@ -61,11 +60,14 @@ def setup_scanner(hass, config: dict, see):
return True
# pylint: disable=too-many-instance-attributes
# pylint: disable=too-few-public-methods
class AutomaticDeviceScanner(object):
"""A class representing an Automatic device."""
def __init__(self, config: dict, see) -> None:
def __init__(self, hass, config: dict, see) -> None:
"""Initialize the automatic device scanner."""
self.hass = hass
self._devices = config.get(CONF_DEVICES, None)
self._access_token_payload = {
'username': config.get(CONF_USERNAME),
@@ -81,20 +83,10 @@ class AutomaticDeviceScanner(object):
self.last_trips = {}
self.see = see
self.scan_devices()
def scan_devices(self):
"""Scan for new devices and return a list with found device IDs."""
self._update_info()
return [item['id'] for item in self.last_results]
def get_device_name(self, device):
"""Get the device name from id."""
vehicle = [item['display_name'] for item in self.last_results
if item['id'] == device]
return vehicle[0]
track_utc_time_change(self.hass, self._update_info,
second=range(0, 60, 30))
def _update_headers(self):
"""Get the access token from automatic."""
@@ -114,10 +106,9 @@ class AutomaticDeviceScanner(object):
'Authorization': 'Bearer {}'.format(access_token)
}
@Throttle(MIN_TIME_BETWEEN_SCANS)
def _update_info(self) -> None:
def _update_info(self, now=None) -> None:
"""Update the device info."""
_LOGGER.info('Updating devices')
_LOGGER.debug('Updating devices %s', now)
self._update_headers()
response = requests.get(URL_VEHICLES, headers=self._headers)
@@ -142,6 +133,7 @@ class AutomaticDeviceScanner(object):
for vehicle in self.last_results:
dev_id = vehicle.get('id')
host_name = vehicle.get('display_name')
attrs = {
'fuel_level': vehicle.get('fuel_level_percent')
@@ -149,6 +141,7 @@ class AutomaticDeviceScanner(object):
kwargs = {
'dev_id': dev_id,
'host_name': host_name,
'mac': dev_id,
ATTR_ATTRIBUTES: attrs
}
+2 -2
View File
@@ -46,12 +46,12 @@ def _conf_preprocess(value):
CONFIG_SCHEMA = vol.Schema({
DOMAIN: {cv.match_all: vol.Schema(vol.All(_conf_preprocess, {
DOMAIN: cv.ordered_dict(vol.All(_conf_preprocess, {
vol.Optional(CONF_ENTITIES): vol.Any(cv.entity_ids, None),
CONF_VIEW: cv.boolean,
CONF_NAME: cv.string,
CONF_ICON: cv.icon,
}))}
}, cv.match_all))
}, extra=vol.ALLOW_EXTRA)
# List of ON/OFF state tuples for groupable states
+7 -8
View File
@@ -10,7 +10,6 @@ import socket
import voluptuous as vol
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.config_validation import ensure_list
from homeassistant.const import (
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP, CONF_HOST, CONF_PORT,
CONF_WHITELIST)
@@ -29,7 +28,10 @@ EVENT = 'pilight_received'
# The pilight code schema depends on the protocol
# Thus only require to have the protocol information
RF_CODE_SCHEMA = vol.Schema({vol.Required(ATTR_PROTOCOL): cv.string},
# Ensure that protocol is in a list otherwise segfault in pilight-daemon
# https://github.com/pilight/pilight/issues/296
RF_CODE_SCHEMA = vol.Schema({vol.Required(ATTR_PROTOCOL):
vol.All(cv.ensure_list, [cv.string])},
extra=vol.ALLOW_EXTRA)
SERVICE_NAME = 'send'
@@ -71,12 +73,9 @@ def setup(hass, config):
def send_code(call):
"""Send RF code to the pilight-daemon."""
message_data = call.data
# Patch data because of bug:
# https://github.com/pilight/pilight/issues/296
# Protocol has to be in a list otherwise segfault in pilight-daemon
message_data['protocol'] = ensure_list(message_data['protocol'])
# Change type to dict from mappingproxy
# since data has to be JSON serializable
message_data = dict(call.data)
try:
pilight_client.send_code(message_data)
@@ -20,6 +20,7 @@ from homeassistant.core import HomeAssistant
from homeassistant.const import (EVENT_HOMEASSISTANT_START,
EVENT_HOMEASSISTANT_STOP, EVENT_STATE_CHANGED,
EVENT_TIME_CHANGED, MATCH_ALL)
import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.event import track_point_in_utc_time
from homeassistant.helpers.typing import ConfigType, QueryType
import homeassistant.util.dt as dt_util
@@ -40,10 +41,9 @@ QUERY_RETRY_WAIT = 0.1
CONFIG_SCHEMA = vol.Schema({
DOMAIN: vol.Schema({
vol.Optional(CONF_PURGE_DAYS): vol.All(vol.Coerce(int),
vol.Range(min=1)),
# pylint: disable=no-value-for-parameter
vol.Optional(CONF_DB_URL): vol.Url(),
vol.Optional(CONF_PURGE_DAYS):
vol.All(vol.Coerce(int), vol.Range(min=1)),
vol.Optional(CONF_DB_URL): cv.string,
})
}, extra=vol.ALLOW_EXTRA)
+2 -2
View File
@@ -1,8 +1,8 @@
# coding: utf-8
"""Constants used by Home Assistant components."""
MAJOR_VERSION = 0
MINOR_VERSION = 29
PATCH_VERSION = '0.dev0'
MINOR_VERSION = 28
PATCH_VERSION = '2'
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
REQUIRED_PYTHON_VER = (3, 4)
@@ -1,4 +1,5 @@
"""Helpers for config validation using voluptuous."""
from collections import OrderedDict
from datetime import timedelta
import os
from urllib.parse import urlparse
@@ -290,6 +291,27 @@ def url(value: Any) -> str:
raise vol.Invalid('invalid url')
def ordered_dict(value_validator, key_validator=match_all):
"""Validate an ordered dict validator that maintains ordering.
value_validator will be applied to each value of the dictionary.
key_validator (optional) will be applied to each key of the dictionary.
"""
item_validator = vol.Schema({key_validator: value_validator})
def validator(value):
"""Validate ordered dict."""
config = OrderedDict()
for key, val in value.items():
v_res = item_validator({key: val})
config.update(v_res)
return config
return validator
# Validator helpers
def key_dependency(key, dependency):
+6 -4
View File
@@ -29,10 +29,10 @@ from homeassistant.const import (
SERVICE_CLOSE, SERVICE_LOCK, SERVICE_MEDIA_PAUSE, SERVICE_MEDIA_PLAY,
SERVICE_MEDIA_SEEK, SERVICE_MOVE_DOWN, SERVICE_MOVE_UP, SERVICE_OPEN,
SERVICE_TURN_OFF, SERVICE_TURN_ON, SERVICE_UNLOCK, SERVICE_VOLUME_MUTE,
SERVICE_VOLUME_SET, STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME,
STATE_ALARM_DISARMED, STATE_ALARM_TRIGGERED, STATE_CLOSED, STATE_LOCKED,
STATE_OFF, STATE_ON, STATE_OPEN, STATE_PAUSED, STATE_PLAYING,
STATE_UNKNOWN, STATE_UNLOCKED)
SERVICE_VOLUME_SET, SERVICE_OPEN_COVER, SERVICE_CLOSE_COVER,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED,
STATE_ALARM_TRIGGERED, STATE_CLOSED, STATE_LOCKED, STATE_OFF, STATE_ON,
STATE_OPEN, STATE_PAUSED, STATE_PLAYING, STATE_UNKNOWN, STATE_UNLOCKED)
from homeassistant.core import State
_LOGGER = logging.getLogger(__name__)
@@ -77,6 +77,8 @@ SERVICE_TO_STATE = {
SERVICE_OPEN: STATE_OPEN,
SERVICE_MOVE_UP: STATE_OPEN,
SERVICE_MOVE_DOWN: STATE_CLOSED,
SERVICE_OPEN_COVER: STATE_OPEN,
SERVICE_CLOSE_COVER: STATE_CLOSED
}
@@ -6,8 +6,9 @@ import unittest
from unittest.mock import patch
from homeassistant.components.device_tracker.automatic import (
URL_AUTHORIZE, URL_VEHICLES, URL_TRIPS, setup_scanner,
AutomaticDeviceScanner)
URL_AUTHORIZE, URL_VEHICLES, URL_TRIPS, setup_scanner)
from tests.common import get_test_home_assistant
_LOGGER = logging.getLogger(__name__)
@@ -205,6 +206,7 @@ class TestAutomatic(unittest.TestCase):
def setUp(self):
"""Set up test data."""
self.hass = get_test_home_assistant()
def tearDown(self):
"""Tear down test data."""
@@ -221,7 +223,7 @@ class TestAutomatic(unittest.TestCase):
'secret': CLIENT_SECRET
}
self.assertFalse(setup_scanner(None, config, self.see_mock))
self.assertFalse(setup_scanner(self.hass, config, self.see_mock))
@patch('requests.get', side_effect=mocked_requests)
@patch('requests.post', side_effect=mocked_requests)
@@ -235,20 +237,4 @@ class TestAutomatic(unittest.TestCase):
'secret': CLIENT_SECRET
}
self.assertTrue(setup_scanner(None, config, self.see_mock))
@patch('requests.get', side_effect=mocked_requests)
@patch('requests.post', side_effect=mocked_requests)
def test_device_attributes(self, mock_get, mock_post):
"""Test device attributes are set on load."""
config = {
'platform': 'automatic',
'username': VALID_USERNAME,
'password': PASSWORD,
'client_id': CLIENT_ID,
'secret': CLIENT_SECRET
}
scanner = AutomaticDeviceScanner(config, self.see_mock)
self.assertEqual(DISPLAY_NAME, scanner.get_device_name('vid'))
self.assertTrue(setup_scanner(self.hass, config, self.see_mock))
+10 -7
View File
@@ -1,5 +1,6 @@
"""The tests for the Group components."""
# pylint: disable=protected-access,too-many-public-methods
from collections import OrderedDict
import unittest
from unittest.mock import patch
@@ -220,16 +221,16 @@ class TestComponentsGroup(unittest.TestCase):
test_group = group.Group(
self.hass, 'init_group', ['light.Bowl', 'light.Ceiling'], False)
_setup_component(self.hass, 'group', {'group': {
'second_group': {
group_conf = OrderedDict()
group_conf['second_group'] = {
'entities': 'light.Bowl, ' + test_group.entity_id,
'icon': 'mdi:work',
'view': True,
},
'test_group': 'hello.world,sensor.happy',
'empty_group': {'name': 'Empty Group', 'entities': None},
}
})
}
group_conf['test_group'] = 'hello.world,sensor.happy'
group_conf['empty_group'] = {'name': 'Empty Group', 'entities': None}
_setup_component(self.hass, 'group', {'group': group_conf})
group_state = self.hass.states.get(
group.ENTITY_ID_FORMAT.format('second_group'))
@@ -241,6 +242,7 @@ class TestComponentsGroup(unittest.TestCase):
group_state.attributes.get(ATTR_ICON))
self.assertTrue(group_state.attributes.get(group.ATTR_VIEW))
self.assertTrue(group_state.attributes.get(ATTR_HIDDEN))
self.assertEqual(1, group_state.attributes.get(group.ATTR_ORDER))
group_state = self.hass.states.get(
group.ENTITY_ID_FORMAT.format('test_group'))
@@ -251,6 +253,7 @@ class TestComponentsGroup(unittest.TestCase):
self.assertIsNone(group_state.attributes.get(ATTR_ICON))
self.assertIsNone(group_state.attributes.get(group.ATTR_VIEW))
self.assertIsNone(group_state.attributes.get(ATTR_HIDDEN))
self.assertEqual(2, group_state.attributes.get(group.ATTR_ORDER))
def test_groups_get_unique_names(self):
"""Two groups with same name should both have a unique entity id."""
+50
View File
@@ -1,3 +1,5 @@
"""Test config validators."""
from collections import OrderedDict
from datetime import timedelta
import os
import tempfile
@@ -367,3 +369,51 @@ def test_has_at_least_one_key():
for value in ({'beer': None}, {'soda': None}):
schema(value)
def test_ordered_dict_order():
"""Test ordered_dict validator."""
schema = vol.Schema(cv.ordered_dict(int, cv.string))
val = OrderedDict()
val['first'] = 1
val['second'] = 2
validated = schema(val)
assert isinstance(validated, OrderedDict)
assert ['first', 'second'] == list(validated.keys())
def test_ordered_dict_key_validator():
"""Test ordered_dict key validator."""
schema = vol.Schema(cv.ordered_dict(cv.match_all, cv.string))
with pytest.raises(vol.Invalid):
schema({None: 1})
schema({'hello': 'world'})
schema = vol.Schema(cv.ordered_dict(cv.match_all, int))
with pytest.raises(vol.Invalid):
schema({'hello': 1})
schema({1: 'works'})
def test_ordered_dict_value_validator():
"""Test ordered_dict validator."""
schema = vol.Schema(cv.ordered_dict(cv.string))
with pytest.raises(vol.Invalid):
schema({'hello': None})
schema({'hello': 'world'})
schema = vol.Schema(cv.ordered_dict(int))
with pytest.raises(vol.Invalid):
schema({'hello': 'world'})
schema({'hello': 5})