Merge pull request from home-assistant/release-0-44

0.44
This commit is contained in:
Paulus Schoutsen 2017-05-06 10:38:45 -07:00 committed by GitHub
commit 43ff95ad3b
709 changed files with 10140 additions and 5554 deletions

View file

@ -77,6 +77,9 @@ omit =
homeassistant/components/octoprint.py homeassistant/components/octoprint.py
homeassistant/components/*/octoprint.py homeassistant/components/*/octoprint.py
homeassistant/components/opencv.py
homeassistant/components/*/opencv.py
homeassistant/components/qwikswitch.py homeassistant/components/qwikswitch.py
homeassistant/components/*/qwikswitch.py homeassistant/components/*/qwikswitch.py
@ -154,6 +157,13 @@ omit =
homeassistant/components/tado.py homeassistant/components/tado.py
homeassistant/components/*/tado.py homeassistant/components/*/tado.py
homeassistant/components/zha/__init__.py
homeassistant/components/zha/const.py
homeassistant/components/*/zha.py
homeassistant/components/eight_sleep.py
homeassistant/components/*/eight_sleep.py
homeassistant/components/alarm_control_panel/alarmdotcom.py homeassistant/components/alarm_control_panel/alarmdotcom.py
homeassistant/components/alarm_control_panel/concord232.py homeassistant/components/alarm_control_panel/concord232.py
homeassistant/components/alarm_control_panel/nx584.py homeassistant/components/alarm_control_panel/nx584.py
@ -165,6 +175,7 @@ omit =
homeassistant/components/binary_sensor/flic.py homeassistant/components/binary_sensor/flic.py
homeassistant/components/binary_sensor/hikvision.py homeassistant/components/binary_sensor/hikvision.py
homeassistant/components/binary_sensor/iss.py homeassistant/components/binary_sensor/iss.py
homeassistant/components/binary_sensor/pilight.py
homeassistant/components/binary_sensor/ping.py homeassistant/components/binary_sensor/ping.py
homeassistant/components/binary_sensor/rest.py homeassistant/components/binary_sensor/rest.py
homeassistant/components/browser.py homeassistant/components/browser.py
@ -182,15 +193,18 @@ omit =
homeassistant/components/climate/oem.py homeassistant/components/climate/oem.py
homeassistant/components/climate/proliphix.py homeassistant/components/climate/proliphix.py
homeassistant/components/climate/radiotherm.py homeassistant/components/climate/radiotherm.py
homeassistant/components/climate/sensibo.py
homeassistant/components/cover/garadget.py homeassistant/components/cover/garadget.py
homeassistant/components/cover/homematic.py homeassistant/components/cover/homematic.py
homeassistant/components/cover/myq.py homeassistant/components/cover/myq.py
homeassistant/components/cover/opengarage.py
homeassistant/components/cover/rpi_gpio.py homeassistant/components/cover/rpi_gpio.py
homeassistant/components/cover/scsgate.py homeassistant/components/cover/scsgate.py
homeassistant/components/cover/wink.py homeassistant/components/cover/wink.py
homeassistant/components/device_tracker/actiontec.py homeassistant/components/device_tracker/actiontec.py
homeassistant/components/device_tracker/aruba.py homeassistant/components/device_tracker/aruba.py
homeassistant/components/device_tracker/asuswrt.py homeassistant/components/device_tracker/asuswrt.py
homeassistant/components/device_tracker/automatic.py
homeassistant/components/device_tracker/bbox.py homeassistant/components/device_tracker/bbox.py
homeassistant/components/device_tracker/bluetooth_le_tracker.py homeassistant/components/device_tracker/bluetooth_le_tracker.py
homeassistant/components/device_tracker/bluetooth_tracker.py homeassistant/components/device_tracker/bluetooth_tracker.py
@ -201,6 +215,7 @@ omit =
homeassistant/components/device_tracker/icloud.py homeassistant/components/device_tracker/icloud.py
homeassistant/components/device_tracker/linksys_ap.py homeassistant/components/device_tracker/linksys_ap.py
homeassistant/components/device_tracker/luci.py homeassistant/components/device_tracker/luci.py
homeassistant/components/device_tracker/mikrotik.py
homeassistant/components/device_tracker/netgear.py homeassistant/components/device_tracker/netgear.py
homeassistant/components/device_tracker/nmap_tracker.py homeassistant/components/device_tracker/nmap_tracker.py
homeassistant/components/device_tracker/ping.py homeassistant/components/device_tracker/ping.py
@ -222,10 +237,13 @@ omit =
homeassistant/components/foursquare.py homeassistant/components/foursquare.py
homeassistant/components/hdmi_cec.py homeassistant/components/hdmi_cec.py
homeassistant/components/ifttt.py homeassistant/components/ifttt.py
homeassistant/components/image_processing/dlib_face_detect.py
homeassistant/components/image_processing/dlib_face_identify.py
homeassistant/components/joaoapps_join.py homeassistant/components/joaoapps_join.py
homeassistant/components/keyboard.py homeassistant/components/keyboard.py
homeassistant/components/keyboard_remote.py homeassistant/components/keyboard_remote.py
homeassistant/components/light/avion.py homeassistant/components/light/avion.py
homeassistant/components/light/blinkt.py
homeassistant/components/light/blinksticklight.py homeassistant/components/light/blinksticklight.py
homeassistant/components/light/decora.py homeassistant/components/light/decora.py
homeassistant/components/light/flux_led.py homeassistant/components/light/flux_led.py
@ -238,6 +256,7 @@ omit =
homeassistant/components/light/osramlightify.py homeassistant/components/light/osramlightify.py
homeassistant/components/light/rpi_gpio_pwm.py homeassistant/components/light/rpi_gpio_pwm.py
homeassistant/components/light/piglow.py homeassistant/components/light/piglow.py
homeassistant/components/light/sensehat.py
homeassistant/components/light/tikteck.py homeassistant/components/light/tikteck.py
homeassistant/components/light/tradfri.py homeassistant/components/light/tradfri.py
homeassistant/components/light/x10.py homeassistant/components/light/x10.py
@ -335,6 +354,7 @@ omit =
homeassistant/components/sensor/broadlink.py homeassistant/components/sensor/broadlink.py
homeassistant/components/sensor/dublin_bus_transport.py homeassistant/components/sensor/dublin_bus_transport.py
homeassistant/components/sensor/coinmarketcap.py homeassistant/components/sensor/coinmarketcap.py
homeassistant/components/sensor/cert_expiry.py
homeassistant/components/sensor/comed_hourly_pricing.py homeassistant/components/sensor/comed_hourly_pricing.py
homeassistant/components/sensor/cpuspeed.py homeassistant/components/sensor/cpuspeed.py
homeassistant/components/sensor/crimereports.py homeassistant/components/sensor/crimereports.py
@ -350,6 +370,7 @@ omit =
homeassistant/components/sensor/eddystone_temperature.py homeassistant/components/sensor/eddystone_temperature.py
homeassistant/components/sensor/eliqonline.py homeassistant/components/sensor/eliqonline.py
homeassistant/components/sensor/emoncms.py homeassistant/components/sensor/emoncms.py
homeassistant/components/sensor/envirophat.py
homeassistant/components/sensor/fastdotcom.py homeassistant/components/sensor/fastdotcom.py
homeassistant/components/sensor/fedex.py homeassistant/components/sensor/fedex.py
homeassistant/components/sensor/fido.py homeassistant/components/sensor/fido.py
@ -391,6 +412,7 @@ omit =
homeassistant/components/sensor/pi_hole.py homeassistant/components/sensor/pi_hole.py
homeassistant/components/sensor/plex.py homeassistant/components/sensor/plex.py
homeassistant/components/sensor/pocketcasts.py homeassistant/components/sensor/pocketcasts.py
homeassistant/components/sensor/pushbullet.py
homeassistant/components/sensor/pvoutput.py homeassistant/components/sensor/pvoutput.py
homeassistant/components/sensor/qnap.py homeassistant/components/sensor/qnap.py
homeassistant/components/sensor/sabnzbd.py homeassistant/components/sensor/sabnzbd.py

View file

@ -1,4 +1,4 @@
"""Starts home assistant.""" """Start Home Assistant."""
from __future__ import print_function from __future__ import print_function
import argparse import argparse
@ -277,7 +277,7 @@ def cmdline() -> List[str]:
def setup_and_run_hass(config_dir: str, def setup_and_run_hass(config_dir: str,
args: argparse.Namespace) -> Optional[int]: args: argparse.Namespace) -> Optional[int]:
"""Setup HASS and run.""" """Set up HASS and run."""
from homeassistant import bootstrap from homeassistant import bootstrap
# Run a simple daemon runner process on Windows to handle restarts # Run a simple daemon runner process on Windows to handle restarts

View file

@ -1,4 +1,4 @@
"""Provides methods to bootstrap a home assistant instance.""" """Provide methods to bootstrap a Home Assistant instance."""
import asyncio import asyncio
import logging import logging
import logging.handlers import logging.handlers
@ -206,7 +206,7 @@ def async_from_config_file(config_path: str,
@core.callback @core.callback
def async_enable_logging(hass: core.HomeAssistant, verbose: bool=False, def async_enable_logging(hass: core.HomeAssistant, verbose: bool=False,
log_rotate_days=None) -> None: log_rotate_days=None) -> None:
"""Setup the logging. """Set up the logging.
This method must be run in the event loop. This method must be run in the event loop.
""" """
@ -214,12 +214,12 @@ def async_enable_logging(hass: core.HomeAssistant, verbose: bool=False,
fmt = ("%(asctime)s %(levelname)s (%(threadName)s) " fmt = ("%(asctime)s %(levelname)s (%(threadName)s) "
"[%(name)s] %(message)s") "[%(name)s] %(message)s")
colorfmt = "%(log_color)s{}%(reset)s".format(fmt) colorfmt = "%(log_color)s{}%(reset)s".format(fmt)
datefmt = '%y-%m-%d %H:%M:%S' datefmt = '%Y-%m-%d %H:%M:%S'
# suppress overly verbose logs from libraries that aren't helpful # Suppress overly verbose logs from libraries that aren't helpful
logging.getLogger("requests").setLevel(logging.WARNING) logging.getLogger('requests').setLevel(logging.WARNING)
logging.getLogger("urllib3").setLevel(logging.WARNING) logging.getLogger('urllib3').setLevel(logging.WARNING)
logging.getLogger("aiohttp.access").setLevel(logging.WARNING) logging.getLogger('aiohttp.access').setLevel(logging.WARNING)
try: try:
from colorlog import ColoredFormatter from colorlog import ColoredFormatter
@ -274,7 +274,7 @@ def async_enable_logging(hass: core.HomeAssistant, verbose: bool=False,
else: else:
_LOGGER.error( _LOGGER.error(
'Unable to setup error log %s (access denied)', err_log_path) "Unable to setup error log %s (access denied)", err_log_path)
def mount_local_lib_path(config_dir: str) -> str: def mount_local_lib_path(config_dir: str) -> str:

View file

@ -102,10 +102,10 @@ def reload_core_config(hass):
@asyncio.coroutine @asyncio.coroutine
def async_setup(hass, config): def async_setup(hass, config):
"""Setup general services related to Home Assistant.""" """Set up general services related to Home Assistant."""
@asyncio.coroutine @asyncio.coroutine
def async_handle_turn_service(service): def async_handle_turn_service(service):
"""Method to handle calls to homeassistant.turn_on/off.""" """Handle calls to homeassistant.turn_on/off."""
entity_ids = extract_entity_ids(hass, service) entity_ids = extract_entity_ids(hass, service)
# Generic turn on/off method requires entity id # Generic turn on/off method requires entity id

View file

@ -25,7 +25,7 @@ DEPENDENCIES = ['alarmdecoder']
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Perform the setup for AlarmDecoder alarm panels.""" """Set up for AlarmDecoder alarm panels."""
_LOGGER.debug("AlarmDecoderAlarmPanel: setup") _LOGGER.debug("AlarmDecoderAlarmPanel: setup")
device = AlarmDecoderAlarmPanel("Alarm Panel", hass) device = AlarmDecoderAlarmPanel("Alarm Panel", hass)
@ -44,7 +44,7 @@ class AlarmDecoderAlarmPanel(alarm.AlarmControlPanel):
self._name = name self._name = name
self._state = STATE_UNKNOWN self._state = STATE_UNKNOWN
_LOGGER.debug("AlarmDecoderAlarm: Setting up panel") _LOGGER.debug("Setting up panel")
@asyncio.coroutine @asyncio.coroutine
def async_added_to_hass(self): def async_added_to_hass(self):
@ -78,12 +78,12 @@ class AlarmDecoderAlarmPanel(alarm.AlarmControlPanel):
@property @property
def should_poll(self): def should_poll(self):
"""No polling needed.""" """Return the polling state."""
return False return False
@property @property
def code_format(self): def code_format(self):
"""Regex for code format or None if no code is required.""" """Return the regex for code format or None if no code is required."""
return '^\\d{4,6}$' return '^\\d{4,6}$'
@property @property
@ -94,26 +94,23 @@ class AlarmDecoderAlarmPanel(alarm.AlarmControlPanel):
@asyncio.coroutine @asyncio.coroutine
def async_alarm_disarm(self, code=None): def async_alarm_disarm(self, code=None):
"""Send disarm command.""" """Send disarm command."""
_LOGGER.debug("AlarmDecoderAlarm::alarm_disarm: %s", code) _LOGGER.debug("alarm_disarm: %s", code)
if code: if code:
_LOGGER.debug("AlarmDecoderAlarm::alarm_disarm: sending %s1", _LOGGER.debug("alarm_disarm: sending %s1", str(code))
str(code))
self.hass.data[DATA_AD].send("{!s}1".format(code)) self.hass.data[DATA_AD].send("{!s}1".format(code))
@asyncio.coroutine @asyncio.coroutine
def async_alarm_arm_away(self, code=None): def async_alarm_arm_away(self, code=None):
"""Send arm away command.""" """Send arm away command."""
_LOGGER.debug("AlarmDecoderAlarm::alarm_arm_away: %s", code) _LOGGER.debug("alarm_arm_away: %s", code)
if code: if code:
_LOGGER.debug("AlarmDecoderAlarm::alarm_arm_away: sending %s2", _LOGGER.debug("alarm_arm_away: sending %s2", str(code))
str(code))
self.hass.data[DATA_AD].send("{!s}2".format(code)) self.hass.data[DATA_AD].send("{!s}2".format(code))
@asyncio.coroutine @asyncio.coroutine
def async_alarm_arm_home(self, code=None): def async_alarm_arm_home(self, code=None):
"""Send arm home command.""" """Send arm home command."""
_LOGGER.debug("AlarmDecoderAlarm::alarm_arm_home: %s", code) _LOGGER.debug("alarm_arm_home: %s", code)
if code: if code:
_LOGGER.debug("AlarmDecoderAlarm::alarm_arm_home: sending %s3", _LOGGER.debug("alarm_arm_home: sending %s3", str(code))
str(code))
self.hass.data[DATA_AD].send("{!s}3".format(code)) self.hass.data[DATA_AD].send("{!s}3".format(code))

View file

@ -1,5 +1,4 @@
""" """
Interfaces with Alarm.com alarm control panels. Interfaces with Alarm.com alarm control panels.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
@ -33,7 +32,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a Alarm.com control panel.""" """Set up a Alarm.com control panel."""
name = config.get(CONF_NAME) name = config.get(CONF_NAME)
code = config.get(CONF_CODE) code = config.get(CONF_CODE)
username = config.get(CONF_USERNAME) username = config.get(CONF_USERNAME)

View file

@ -51,7 +51,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class Concord232Alarm(alarm.AlarmControlPanel): class Concord232Alarm(alarm.AlarmControlPanel):
"""Represents the Concord232-based alarm panel.""" """Representation of the Concord232-based alarm panel."""
def __init__(self, hass, url, name): def __init__(self, hass, url, name):
"""Initialize the Concord232 alarm panel.""" """Initialize the Concord232 alarm panel."""
@ -79,7 +79,7 @@ class Concord232Alarm(alarm.AlarmControlPanel):
@property @property
def code_format(self): def code_format(self):
"""The characters if code is defined.""" """Return the characters if code is defined."""
return '[0-9]{4}([0-9]{2})?' return '[0-9]{4}([0-9]{2})?'
@property @property

View file

@ -8,7 +8,7 @@ import homeassistant.components.alarm_control_panel.manual as manual
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo alarm control panel platform.""" """Set up the Demo alarm control panel platform."""
add_devices([ add_devices([
manual.ManualAlarm(hass, 'Alarm', '1234', 5, 10, False), manual.ManualAlarm(hass, 'Alarm', '1234', 5, 10, False),
]) ])

View file

@ -104,7 +104,7 @@ class EnvisalinkAlarm(EnvisalinkDevice, alarm.AlarmControlPanel):
@callback @callback
def _update_callback(self, partition): def _update_callback(self, partition):
"""Update HA state, if needed.""" """Update Home Assistant state, if needed."""
if partition is None or int(partition) == self._partition_number: if partition is None or int(partition) == self._partition_number:
self.hass.async_add_job(self.async_update_ha_state()) self.hass.async_add_job(self.async_update_ha_state())

View file

@ -39,7 +39,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the manual alarm platform.""" """Set up the manual alarm platform."""
add_devices([ManualAlarm( add_devices([ManualAlarm(
hass, hass,
config[CONF_NAME], config[CONF_NAME],
@ -52,7 +52,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class ManualAlarm(alarm.AlarmControlPanel): class ManualAlarm(alarm.AlarmControlPanel):
""" """
Represents an alarm status. Representation of an alarm status.
When armed, will be pending for 'pending_time', after that armed. When armed, will be pending for 'pending_time', after that armed.
When triggered, will be pending for 'trigger_time'. After that will be When triggered, will be pending for 'trigger_time'. After that will be
@ -62,7 +62,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
def __init__(self, hass, name, code, pending_time, def __init__(self, hass, name, code, pending_time,
trigger_time, disarm_after_trigger): trigger_time, disarm_after_trigger):
"""Initalize the manual alarm panel.""" """Init the manual alarm panel."""
self._state = STATE_ALARM_DISARMED self._state = STATE_ALARM_DISARMED
self._hass = hass self._hass = hass
self._name = name self._name = name
@ -75,7 +75,7 @@ class ManualAlarm(alarm.AlarmControlPanel):
@property @property
def should_poll(self): def should_poll(self):
"""No polling needed.""" """Return the plling state."""
return False return False
@property @property
@ -166,5 +166,5 @@ class ManualAlarm(alarm.AlarmControlPanel):
"""Validate given code.""" """Validate given code."""
check = self._code is None or code == self._code check = self._code is None or code == self._code
if not check: if not check:
_LOGGER.warning('Invalid code given for %s', state) _LOGGER.warning("Invalid code given for %s", state)
return check return check

View file

@ -45,7 +45,7 @@ PLATFORM_SCHEMA = mqtt.MQTT_BASE_PLATFORM_SCHEMA.extend({
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup the MQTT platform.""" """Set up the MQTT Alarm Control Panel platform."""
async_add_devices([MqttAlarm( async_add_devices([MqttAlarm(
config.get(CONF_NAME), config.get(CONF_NAME),
config.get(CONF_STATE_TOPIC), config.get(CONF_STATE_TOPIC),
@ -62,7 +62,7 @@ class MqttAlarm(alarm.AlarmControlPanel):
def __init__(self, name, state_topic, command_topic, qos, payload_disarm, def __init__(self, name, state_topic, command_topic, qos, payload_disarm,
payload_arm_home, payload_arm_away, code): payload_arm_home, payload_arm_away, code):
"""Initalize the MQTT alarm panel.""" """Init the MQTT Alarm Control Panel."""
self._state = STATE_UNKNOWN self._state = STATE_UNKNOWN
self._name = name self._name = name
self._state_topic = state_topic self._state_topic = state_topic
@ -80,11 +80,11 @@ class MqttAlarm(alarm.AlarmControlPanel):
""" """
@callback @callback
def message_received(topic, payload, qos): def message_received(topic, payload, qos):
"""A new MQTT message has been received.""" """Run when new MQTT message has been received."""
if payload not in (STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME, if payload not in (STATE_ALARM_DISARMED, STATE_ALARM_ARMED_HOME,
STATE_ALARM_ARMED_AWAY, STATE_ALARM_PENDING, STATE_ALARM_ARMED_AWAY, STATE_ALARM_PENDING,
STATE_ALARM_TRIGGERED): STATE_ALARM_TRIGGERED):
_LOGGER.warning('Received unexpected payload: %s', payload) _LOGGER.warning("Received unexpected payload: %s", payload)
return return
self._state = payload self._state = payload
self.hass.async_add_job(self.async_update_ha_state()) self.hass.async_add_job(self.async_update_ha_state())

View file

@ -32,7 +32,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup nx584 platform.""" """Set up the nx584 platform."""
name = config.get(CONF_NAME) name = config.get(CONF_NAME)
host = config.get(CONF_HOST) host = config.get(CONF_HOST)
port = config.get(CONF_PORT) port = config.get(CONF_PORT)
@ -42,15 +42,15 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
try: try:
add_devices([NX584Alarm(hass, url, name)]) add_devices([NX584Alarm(hass, url, name)])
except requests.exceptions.ConnectionError as ex: except requests.exceptions.ConnectionError as ex:
_LOGGER.error('Unable to connect to NX584: %s', str(ex)) _LOGGER.error("Unable to connect to NX584: %s", str(ex))
return False return False
class NX584Alarm(alarm.AlarmControlPanel): class NX584Alarm(alarm.AlarmControlPanel):
"""Represents the NX584-based alarm panel.""" """Representation of a NX584-based alarm panel."""
def __init__(self, hass, url, name): def __init__(self, hass, url, name):
"""Initalize the nx584 alarm panel.""" """Init the nx584 alarm panel."""
from nx584 import client from nx584 import client
self._hass = hass self._hass = hass
self._name = name self._name = name
@ -69,7 +69,7 @@ class NX584Alarm(alarm.AlarmControlPanel):
@property @property
def code_format(self): def code_format(self):
"""The characters if code is defined.""" """Return che characters if code is defined."""
return '[0-9]{4}([0-9]{2})?' return '[0-9]{4}([0-9]{2})?'
@property @property
@ -83,20 +83,19 @@ class NX584Alarm(alarm.AlarmControlPanel):
part = self._alarm.list_partitions()[0] part = self._alarm.list_partitions()[0]
zones = self._alarm.list_zones() zones = self._alarm.list_zones()
except requests.exceptions.ConnectionError as ex: except requests.exceptions.ConnectionError as ex:
_LOGGER.error('Unable to connect to %(host)s: %(reason)s', _LOGGER.error("Unable to connect to %(host)s: %(reason)s",
dict(host=self._url, reason=ex)) dict(host=self._url, reason=ex))
self._state = STATE_UNKNOWN self._state = STATE_UNKNOWN
zones = [] zones = []
except IndexError: except IndexError:
_LOGGER.error('nx584 reports no partitions') _LOGGER.error("nx584 reports no partitions")
self._state = STATE_UNKNOWN self._state = STATE_UNKNOWN
zones = [] zones = []
bypassed = False bypassed = False
for zone in zones: for zone in zones:
if zone['bypassed']: if zone['bypassed']:
_LOGGER.debug('Zone %(zone)s is bypassed, ' _LOGGER.debug("Zone %(zone)s is bypassed, assuming HOME",
'assuming HOME',
dict(zone=zone['number'])) dict(zone=zone['number']))
bypassed = True bypassed = True
break break

View file

@ -123,25 +123,25 @@ class SimpliSafeAlarm(alarm.AlarmControlPanel):
if not self._validate_code(code, 'disarming'): if not self._validate_code(code, 'disarming'):
return return
self.simplisafe.set_state('off') self.simplisafe.set_state('off')
_LOGGER.info('SimpliSafe alarm disarming') _LOGGER.info("SimpliSafe alarm disarming")
def alarm_arm_home(self, code=None): def alarm_arm_home(self, code=None):
"""Send arm home command.""" """Send arm home command."""
if not self._validate_code(code, 'arming home'): if not self._validate_code(code, 'arming home'):
return return
self.simplisafe.set_state('home') self.simplisafe.set_state('home')
_LOGGER.info('SimpliSafe alarm arming home') _LOGGER.info("SimpliSafe alarm arming home")
def alarm_arm_away(self, code=None): def alarm_arm_away(self, code=None):
"""Send arm away command.""" """Send arm away command."""
if not self._validate_code(code, 'arming away'): if not self._validate_code(code, 'arming away'):
return return
self.simplisafe.set_state('away') self.simplisafe.set_state('away')
_LOGGER.info('SimpliSafe alarm arming away') _LOGGER.info("SimpliSafe alarm arming away")
def _validate_code(self, code, state): def _validate_code(self, code, state):
"""Validate given code.""" """Validate given code."""
check = self._code is None or code == self._code check = self._code is None or code == self._code
if not check: if not check:
_LOGGER.warning('Wrong code entered for %s', state) _LOGGER.warning("Wrong code entered for %s", state)
return check return check

View file

@ -1,15 +1,20 @@
"""Interfaces with TotalConnect alarm control panels.""" """
Interfaces with TotalConnect alarm control panels.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/alarm_control_panel.totalconnect/
"""
import logging import logging
import voluptuous as vol import voluptuous as vol
import homeassistant.helpers.config_validation as cv
import homeassistant.components.alarm_control_panel as alarm import homeassistant.components.alarm_control_panel as alarm
from homeassistant.components.alarm_control_panel import PLATFORM_SCHEMA from homeassistant.components.alarm_control_panel import PLATFORM_SCHEMA
from homeassistant.const import ( from homeassistant.const import (
CONF_PASSWORD, CONF_USERNAME, STATE_ALARM_ARMED_AWAY, CONF_PASSWORD, CONF_USERNAME, STATE_ALARM_ARMED_AWAY,
STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_UNKNOWN, STATE_ALARM_ARMED_HOME, STATE_ALARM_DISARMED, STATE_UNKNOWN,
CONF_NAME) CONF_NAME)
import homeassistant.helpers.config_validation as cv
REQUIREMENTS = ['total_connect_client==0.7'] REQUIREMENTS = ['total_connect_client==0.7']
@ -25,7 +30,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup a TotalConnect control panel.""" """Set up a TotalConnect control panel."""
name = config.get(CONF_NAME) name = config.get(CONF_NAME)
username = config.get(CONF_USERNAME) username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD) password = config.get(CONF_PASSWORD)
@ -41,13 +46,13 @@ class TotalConnect(alarm.AlarmControlPanel):
"""Initialize the TotalConnect status.""" """Initialize the TotalConnect status."""
from total_connect_client import TotalConnectClient from total_connect_client import TotalConnectClient
_LOGGER.debug('Setting up TotalConnect...') _LOGGER.debug("Setting up TotalConnect...")
self._name = name self._name = name
self._username = username self._username = username
self._password = password self._password = password
self._state = STATE_UNKNOWN self._state = STATE_UNKNOWN
self._client = TotalConnectClient.TotalConnectClient(username, self._client = TotalConnectClient.TotalConnectClient(
password) username, password)
@property @property
def name(self): def name(self):

View file

@ -17,7 +17,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Verisure platform.""" """Set up the Verisure platform."""
alarms = [] alarms = []
if int(hub.config.get(CONF_ALARM, 1)): if int(hub.config.get(CONF_ALARM, 1)):
hub.update_alarms() hub.update_alarms()
@ -29,10 +29,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class VerisureAlarm(alarm.AlarmControlPanel): class VerisureAlarm(alarm.AlarmControlPanel):
"""Represent a Verisure alarm status.""" """Representation of a Verisure alarm status."""
def __init__(self, device_id): def __init__(self, device_id):
"""Initalize the Verisure alarm panel.""" """Initialize the Verisure alarm panel."""
self._id = device_id self._id = device_id
self._state = STATE_UNKNOWN self._state = STATE_UNKNOWN
self._digits = hub.config.get(CONF_CODE_DIGITS) self._digits = hub.config.get(CONF_CODE_DIGITS)
@ -55,12 +55,12 @@ class VerisureAlarm(alarm.AlarmControlPanel):
@property @property
def code_format(self): def code_format(self):
"""The code format as regex.""" """Return the code format as regex."""
return '^\\d{%s}$' % self._digits return '^\\d{%s}$' % self._digits
@property @property
def changed_by(self): def changed_by(self):
"""Last change triggered by.""" """Return the last change triggered by."""
return self._changed_by return self._changed_by
def update(self): def update(self):
@ -75,24 +75,23 @@ class VerisureAlarm(alarm.AlarmControlPanel):
self._state = STATE_ALARM_ARMED_AWAY self._state = STATE_ALARM_ARMED_AWAY
elif hub.alarm_status[self._id].status != 'pending': elif hub.alarm_status[self._id].status != 'pending':
_LOGGER.error( _LOGGER.error(
'Unknown alarm state %s', "Unknown alarm state %s", hub.alarm_status[self._id].status)
hub.alarm_status[self._id].status)
self._changed_by = hub.alarm_status[self._id].name self._changed_by = hub.alarm_status[self._id].name
def alarm_disarm(self, code=None): def alarm_disarm(self, code=None):
"""Send disarm command.""" """Send disarm command."""
hub.my_pages.alarm.set(code, 'DISARMED') hub.my_pages.alarm.set(code, 'DISARMED')
_LOGGER.info('verisure alarm disarming') _LOGGER.info("Verisure alarm disarming")
hub.my_pages.alarm.wait_while_pending() hub.my_pages.alarm.wait_while_pending()
def alarm_arm_home(self, code=None): def alarm_arm_home(self, code=None):
"""Send arm home command.""" """Send arm home command."""
hub.my_pages.alarm.set(code, 'ARMED_HOME') hub.my_pages.alarm.set(code, 'ARMED_HOME')
_LOGGER.info('verisure alarm arming home') _LOGGER.info("Verisure alarm arming home")
hub.my_pages.alarm.wait_while_pending() hub.my_pages.alarm.wait_while_pending()
def alarm_arm_away(self, code=None): def alarm_arm_away(self, code=None):
"""Send arm away command.""" """Send arm away command."""
hub.my_pages.alarm.set(code, 'ARMED_AWAY') hub.my_pages.alarm.set(code, 'ARMED_AWAY')
_LOGGER.info('verisure alarm arming away') _LOGGER.info("Verisure alarm arming away")
hub.my_pages.alarm.wait_while_pending() hub.my_pages.alarm.wait_while_pending()

View file

@ -16,11 +16,12 @@ from homeassistant.components.wink import WinkDevice, DOMAIN
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['wink'] DEPENDENCIES = ['wink']
STATE_ALARM_PRIVACY = 'Private' STATE_ALARM_PRIVACY = 'Private'
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink platform.""" """Set up the Wink platform."""
import pywink import pywink
for camera in pywink.get_cameras(): for camera in pywink.get_cameras():

View file

@ -8,11 +8,10 @@ import asyncio
import logging import logging
import voluptuous as vol import voluptuous as vol
import homeassistant.helpers.config_validation as cv
import homeassistant.helpers.config_validation as cv
from homeassistant.core import callback from homeassistant.core import callback
from homeassistant.const import EVENT_HOMEASSISTANT_STOP from homeassistant.const import EVENT_HOMEASSISTANT_STOP
from homeassistant.helpers.discovery import async_load_platform from homeassistant.helpers.discovery import async_load_platform
from homeassistant.helpers.dispatcher import async_dispatcher_send from homeassistant.helpers.dispatcher import async_dispatcher_send
@ -24,19 +23,16 @@ DOMAIN = 'alarmdecoder'
DATA_AD = 'alarmdecoder' DATA_AD = 'alarmdecoder'
CONF_DEVICE = 'device' CONF_DEVICE = 'device'
CONF_DEVICE_TYPE = 'type'
CONF_DEVICE_HOST = 'host'
CONF_DEVICE_PORT = 'port'
CONF_DEVICE_PATH = 'path'
CONF_DEVICE_BAUD = 'baudrate' CONF_DEVICE_BAUD = 'baudrate'
CONF_DEVICE_HOST = 'host'
CONF_ZONES = 'zones' CONF_DEVICE_PATH = 'path'
CONF_DEVICE_PORT = 'port'
CONF_DEVICE_TYPE = 'type'
CONF_PANEL_DISPLAY = 'panel_display'
CONF_ZONE_NAME = 'name' CONF_ZONE_NAME = 'name'
CONF_ZONE_TYPE = 'type' CONF_ZONE_TYPE = 'type'
CONF_ZONES = 'zones'
CONF_PANEL_DISPLAY = 'panel_display'
DEFAULT_DEVICE_TYPE = 'socket' DEFAULT_DEVICE_TYPE = 'socket'
DEFAULT_DEVICE_HOST = 'localhost' DEFAULT_DEVICE_HOST = 'localhost'
@ -87,7 +83,7 @@ CONFIG_SCHEMA = vol.Schema({
@asyncio.coroutine @asyncio.coroutine
def async_setup(hass, config): def async_setup(hass, config):
"""Common setup for AlarmDecoder devices.""" """Set up for the AlarmDecoder devices."""
from alarmdecoder import AlarmDecoder from alarmdecoder import AlarmDecoder
from alarmdecoder.devices import (SocketDevice, SerialDevice, USBDevice) from alarmdecoder.devices import (SocketDevice, SerialDevice, USBDevice)
@ -106,28 +102,28 @@ def async_setup(hass, config):
sync_connect = asyncio.Future(loop=hass.loop) sync_connect = asyncio.Future(loop=hass.loop)
def handle_open(device): def handle_open(device):
"""Callback for a successful connection.""" """Handle the successful connection."""
_LOGGER.info("Established a connection with the alarmdecoder.") _LOGGER.info("Established a connection with the alarmdecoder")
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_alarmdecoder) hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, stop_alarmdecoder)
sync_connect.set_result(True) sync_connect.set_result(True)
@callback @callback
def stop_alarmdecoder(event): def stop_alarmdecoder(event):
"""Callback to handle shutdown alarmdecoder.""" """Handle the shutdown of AlarmDecoder."""
_LOGGER.debug("Shutting down alarmdecoder.") _LOGGER.debug("Shutting down alarmdecoder")
controller.close() controller.close()
@callback @callback
def handle_message(sender, message): def handle_message(sender, message):
"""Callback to handle message from alarmdecoder.""" """Handle message from AlarmDecoder."""
async_dispatcher_send(hass, SIGNAL_PANEL_MESSAGE, message) async_dispatcher_send(hass, SIGNAL_PANEL_MESSAGE, message)
def zone_fault_callback(sender, zone): def zone_fault_callback(sender, zone):
"""Callback to handle zone fault from alarmdecoder.""" """Handle zone fault from AlarmDecoder."""
async_dispatcher_send(hass, SIGNAL_ZONE_FAULT, zone) async_dispatcher_send(hass, SIGNAL_ZONE_FAULT, zone)
def zone_restore_callback(sender, zone): def zone_restore_callback(sender, zone):
"""Callback to handle zone restore from alarmdecoder.""" """Handle zone restore from AlarmDecoder."""
async_dispatcher_send(hass, SIGNAL_ZONE_RESTORE, zone) async_dispatcher_send(hass, SIGNAL_ZONE_RESTORE, zone)
controller = False controller = False
@ -157,15 +153,16 @@ def async_setup(hass, config):
if not result: if not result:
return False return False
hass.async_add_job(async_load_platform(hass, 'alarm_control_panel', DOMAIN, hass.async_add_job(
conf, config)) async_load_platform(hass, 'alarm_control_panel', DOMAIN, conf,
config))
if zones: if zones:
hass.async_add_job(async_load_platform( hass.async_add_job(async_load_platform(
hass, 'binary_sensor', DOMAIN, {CONF_ZONES: zones}, config)) hass, 'binary_sensor', DOMAIN, {CONF_ZONES: zones}, config))
if display: if display:
hass.async_add_job(async_load_platform(hass, 'sensor', DOMAIN, hass.async_add_job(async_load_platform(
conf, config)) hass, 'sensor', DOMAIN, conf, config))
return True return True

View file

@ -141,7 +141,7 @@ def reload(hass):
@asyncio.coroutine @asyncio.coroutine
def async_setup(hass, config): def async_setup(hass, config):
"""Setup the automation.""" """Set up the automation."""
component = EntityComponent(_LOGGER, DOMAIN, hass, component = EntityComponent(_LOGGER, DOMAIN, hass,
group_name=GROUP_NAME_ALL_AUTOMATIONS) group_name=GROUP_NAME_ALL_AUTOMATIONS)
@ -400,7 +400,7 @@ def _async_get_action(hass, config, name):
@asyncio.coroutine @asyncio.coroutine
def action(entity_id, variables): def action(entity_id, variables):
"""Action to be executed.""" """Execute an action."""
_LOGGER.info('Executing %s', name) _LOGGER.info('Executing %s', name)
logbook.async_log_entry( logbook.async_log_entry(
hass, name, 'has been triggered', DOMAIN, entity_id) hass, name, 'has been triggered', DOMAIN, entity_id)
@ -430,7 +430,7 @@ def _async_process_if(hass, config, p_config):
@asyncio.coroutine @asyncio.coroutine
def _async_process_trigger(hass, config, trigger_configs, name, action): def _async_process_trigger(hass, config, trigger_configs, name, action):
"""Setup the triggers. """Set up the triggers.
This method is a coroutine. This method is a coroutine.
""" """

View file

@ -13,8 +13,8 @@ from homeassistant.core import callback, CoreState
from homeassistant.const import CONF_PLATFORM, EVENT_HOMEASSISTANT_START from homeassistant.const import CONF_PLATFORM, EVENT_HOMEASSISTANT_START
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
CONF_EVENT_TYPE = "event_type" CONF_EVENT_TYPE = 'event_type'
CONF_EVENT_DATA = "event_data" CONF_EVENT_DATA = 'event_data'
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)

View file

@ -31,7 +31,7 @@ def async_trigger(hass, config, action):
if event == EVENT_SHUTDOWN: if event == EVENT_SHUTDOWN:
@callback @callback
def hass_shutdown(event): def hass_shutdown(event):
"""Called when Home Assistant is shutting down.""" """Execute when Home Assistant is shutting down."""
hass.async_run_job(action, { hass.async_run_job(action, {
'trigger': { 'trigger': {
'platform': 'homeassistant', 'platform': 'homeassistant',

View file

@ -14,11 +14,11 @@ from homeassistant.helpers.event import (
async_track_state_change, async_track_point_in_utc_time) async_track_state_change, async_track_point_in_utc_time)
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
CONF_ENTITY_ID = "entity_id" CONF_ENTITY_ID = 'entity_id'
CONF_FROM = "from" CONF_FROM = 'from'
CONF_TO = "to" CONF_TO = 'to'
CONF_STATE = "state" CONF_STATE = 'state'
CONF_FOR = "for" CONF_FOR = 'for'
TRIGGER_SCHEMA = vol.All( TRIGGER_SCHEMA = vol.All(
vol.Schema({ vol.Schema({

View file

@ -14,9 +14,9 @@ from homeassistant.const import CONF_AFTER, CONF_PLATFORM
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.event import async_track_time_change from homeassistant.helpers.event import async_track_time_change
CONF_HOURS = "hours" CONF_HOURS = 'hours'
CONF_MINUTES = "minutes" CONF_MINUTES = 'minutes'
CONF_SECONDS = "seconds" CONF_SECONDS = 'seconds'
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)

View file

@ -14,8 +14,8 @@ from homeassistant.helpers.event import async_track_state_change
from homeassistant.helpers import ( from homeassistant.helpers import (
condition, config_validation as cv, location) condition, config_validation as cv, location)
EVENT_ENTER = "enter" EVENT_ENTER = 'enter'
EVENT_LEAVE = "leave" EVENT_LEAVE = 'leave'
DEFAULT_EVENT = EVENT_ENTER DEFAULT_EVENT = EVENT_ENTER
TRIGGER_SCHEMA = vol.Schema({ TRIGGER_SCHEMA = vol.Schema({

View file

@ -37,14 +37,14 @@ def setup(hass, config):
# noqa: F821 # noqa: F821
def setup_output(pin): def setup_output(pin):
"""Setup a GPIO as output.""" """Set up a GPIO as output."""
# pylint: disable=import-error,undefined-variable # pylint: disable=import-error,undefined-variable
import Adafruit_BBIO.GPIO as GPIO import Adafruit_BBIO.GPIO as GPIO
GPIO.setup(pin, GPIO.OUT) GPIO.setup(pin, GPIO.OUT)
def setup_input(pin, pull_mode): def setup_input(pin, pull_mode):
"""Setup a GPIO as input.""" """Set up a GPIO as input."""
# pylint: disable=import-error,undefined-variable # pylint: disable=import-error,undefined-variable
import Adafruit_BBIO.GPIO as GPIO import Adafruit_BBIO.GPIO as GPIO
GPIO.setup(pin, GPIO.IN, # noqa: F821 GPIO.setup(pin, GPIO.IN, # noqa: F821

View file

@ -57,7 +57,7 @@ class BinarySensorDevice(Entity):
@property @property
def is_on(self): def is_on(self):
"""Return True if the binary sensor is on.""" """Return true if the binary sensor is on."""
return None return None
@property @property

View file

@ -11,7 +11,6 @@ from homeassistant.core import callback
from homeassistant.helpers.dispatcher import async_dispatcher_connect from homeassistant.helpers.dispatcher import async_dispatcher_connect
from homeassistant.components.binary_sensor import BinarySensorDevice from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.const import (STATE_ON, STATE_OFF, STATE_OPEN, STATE_CLOSED)
from homeassistant.components.alarmdecoder import (ZONE_SCHEMA, from homeassistant.components.alarmdecoder import (ZONE_SCHEMA,
CONF_ZONES, CONF_ZONES,
CONF_ZONE_NAME, CONF_ZONE_NAME,
@ -27,7 +26,7 @@ _LOGGER = logging.getLogger(__name__)
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup AlarmDecoder binary sensor devices.""" """Set up the AlarmDecoder binary sensor devices."""
configured_zones = discovery_info[CONF_ZONES] configured_zones = discovery_info[CONF_ZONES]
devices = [] devices = []
@ -36,10 +35,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
device_config_data = ZONE_SCHEMA(configured_zones[zone_num]) device_config_data = ZONE_SCHEMA(configured_zones[zone_num])
zone_type = device_config_data[CONF_ZONE_TYPE] zone_type = device_config_data[CONF_ZONE_TYPE]
zone_name = device_config_data[CONF_ZONE_NAME] zone_name = device_config_data[CONF_ZONE_NAME]
device = AlarmDecoderBinarySensor(hass, device = AlarmDecoderBinarySensor(
zone_num, hass, zone_num, zone_name, zone_type)
zone_name,
zone_type)
devices.append(device) devices.append(device)
async_add_devices(devices) async_add_devices(devices)
@ -58,7 +55,7 @@ class AlarmDecoderBinarySensor(BinarySensorDevice):
self._name = zone_name self._name = zone_name
self._type = zone_type self._type = zone_type
_LOGGER.debug('AlarmDecoderBinarySensor: Setup up zone: ' + zone_name) _LOGGER.debug("Setup up zone: %s", self._name)
@asyncio.coroutine @asyncio.coroutine
def async_added_to_hass(self): def async_added_to_hass(self):
@ -69,14 +66,6 @@ class AlarmDecoderBinarySensor(BinarySensorDevice):
async_dispatcher_connect( async_dispatcher_connect(
self.hass, SIGNAL_ZONE_RESTORE, self._restore_callback) self.hass, SIGNAL_ZONE_RESTORE, self._restore_callback)
@property
def state(self):
"""Return the state of the binary sensor."""
if self._type == 'opening':
return STATE_OPEN if self.is_on else STATE_CLOSED
return STATE_ON if self.is_on else STATE_OFF
@property @property
def name(self): def name(self):
"""Return the name of the entity.""" """Return the name of the entity."""

View file

@ -15,7 +15,7 @@ DEPENDENCIES = ['android_ip_webcam']
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup IP Webcam binary sensors.""" """Set up the IP Webcam binary sensors."""
if discovery_info is None: if discovery_info is None:
return return
@ -28,7 +28,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
class IPWebcamBinarySensor(AndroidIPCamEntity, BinarySensorDevice): class IPWebcamBinarySensor(AndroidIPCamEntity, BinarySensorDevice):
"""Represents an IP Webcam binary sensor.""" """Representation of an IP Webcam binary sensor."""
def __init__(self, name, host, ipcam, sensor): def __init__(self, name, host, ipcam, sensor):
"""Initialize the binary sensor.""" """Initialize the binary sensor."""
@ -47,7 +47,7 @@ class IPWebcamBinarySensor(AndroidIPCamEntity, BinarySensorDevice):
@property @property
def is_on(self): def is_on(self):
"""True if the binary sensor is on.""" """Return true if the binary sensor is on."""
return self._state return self._state
@asyncio.coroutine @asyncio.coroutine

View file

@ -21,7 +21,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_entities, discovery_info=None): def setup_platform(hass, config, add_entities, discovery_info=None):
"""Setup an Online Status binary sensor.""" """Set up an Online Status binary sensor."""
add_entities((OnlineStatus(config, apcupsd.DATA),)) add_entities((OnlineStatus(config, apcupsd.DATA),))

View file

@ -42,7 +42,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Beaglebone Black GPIO devices.""" """Set up the Beaglebone Black GPIO devices."""
pins = config.get(CONF_PINS) pins = config.get(CONF_PINS)
binary_sensors = [] binary_sensors = []
@ -53,7 +53,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class BBBGPIOBinarySensor(BinarySensorDevice): class BBBGPIOBinarySensor(BinarySensorDevice):
"""Represent a binary sensor that uses Beaglebone Black GPIO.""" """Representation of a binary sensor that uses Beaglebone Black GPIO."""
def __init__(self, pin, params): def __init__(self, pin, params):
"""Initialize the Beaglebone Black binary sensor.""" """Initialize the Beaglebone Black binary sensor."""

View file

@ -24,7 +24,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class BlinkCameraMotionSensor(BinarySensorDevice): class BlinkCameraMotionSensor(BinarySensorDevice):
"""A representation of a Blink binary sensor.""" """Representation of a Blink binary sensor."""
def __init__(self, name, data): def __init__(self, name, data):
"""Initialize the sensor.""" """Initialize the sensor."""

View file

@ -18,7 +18,6 @@ _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['bloomsky'] DEPENDENCIES = ['bloomsky']
# These are the available sensors mapped to binary_sensor class
SENSOR_TYPES = { SENSOR_TYPES = {
'Rain': 'moisture', 'Rain': 'moisture',
'Night': None, 'Night': None,
@ -31,7 +30,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the available BloomSky weather binary sensors.""" """Set up the available BloomSky weather binary sensors."""
bloomsky = get_component('bloomsky') bloomsky = get_component('bloomsky')
# Default needed in case of discovery # Default needed in case of discovery
sensors = config.get(CONF_MONITORED_CONDITIONS, SENSOR_TYPES) sensors = config.get(CONF_MONITORED_CONDITIONS, SENSOR_TYPES)
@ -42,7 +41,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class BloomSkySensor(BinarySensorDevice): class BloomSkySensor(BinarySensorDevice):
"""Represent a single binary sensor in a BloomSky device.""" """Representation of a single binary sensor in a BloomSky device."""
def __init__(self, bs, device, sensor_name): def __init__(self, bs, device, sensor_name):
"""Initialize a BloomSky binary sensor.""" """Initialize a BloomSky binary sensor."""
@ -55,7 +54,7 @@ class BloomSkySensor(BinarySensorDevice):
@property @property
def name(self): def name(self):
"""The name of the BloomSky device and this sensor.""" """Return the name of the BloomSky device and this sensor."""
return self._name return self._name
@property @property

View file

@ -39,7 +39,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Command line Binary Sensor.""" """Set up the Command line Binary Sensor."""
name = config.get(CONF_NAME) name = config.get(CONF_NAME)
command = config.get(CONF_COMMAND) command = config.get(CONF_COMMAND)
payload_off = config.get(CONF_PAYLOAD_OFF) payload_off = config.get(CONF_PAYLOAD_OFF)
@ -56,7 +56,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class CommandBinarySensor(BinarySensorDevice): class CommandBinarySensor(BinarySensorDevice):
"""Represent a command line binary sensor.""" """Representation of a command line binary sensor."""
def __init__(self, hass, data, name, device_class, payload_on, def __init__(self, hass, data, name, device_class, payload_on,
payload_off, value_template): payload_off, value_template):

View file

@ -67,8 +67,9 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
if zone['number'] not in exclude: if zone['number'] not in exclude:
sensors.append( sensors.append(
Concord232ZoneSensor( Concord232ZoneSensor(
hass, client, zone, zone_types.get(zone['number'], hass, client, zone, zone_types.get(
get_opening_type(zone))) zone['number'], get_opening_type(zone))
)
) )
add_devices(sensors) add_devices(sensors)
@ -77,7 +78,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
def get_opening_type(zone): def get_opening_type(zone):
"""Helper function to try to guess sensor type from name.""" """Return the result of the type guessing from name."""
if 'MOTION' in zone['name']: if 'MOTION' in zone['name']:
return 'motion' return 'motion'
if 'KEY' in zone['name']: if 'KEY' in zone['name']:
@ -123,7 +124,7 @@ class Concord232ZoneSensor(BinarySensorDevice):
return bool(self._zone['state'] == 'Normal') return bool(self._zone['state'] == 'Normal')
def update(self): def update(self):
""""Get updated stats from API.""" """Get updated stats from API."""
last_update = datetime.datetime.now() - self._client.last_zone_update last_update = datetime.datetime.now() - self._client.last_zone_update
_LOGGER.debug("Zone: %s ", self._zone) _LOGGER.debug("Zone: %s ", self._zone)
if last_update > datetime.timedelta(seconds=1): if last_update > datetime.timedelta(seconds=1):

View file

@ -8,7 +8,7 @@ from homeassistant.components.binary_sensor import BinarySensorDevice
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo binary sensor platform.""" """Set up the Demo binary sensor platform."""
add_devices([ add_devices([
DemoBinarySensor('Basement Floor Wet', False, 'moisture'), DemoBinarySensor('Basement Floor Wet', False, 'moisture'),
DemoBinarySensor('Movement Backyard', True, 'motion'), DemoBinarySensor('Movement Backyard', True, 'motion'),
@ -16,7 +16,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class DemoBinarySensor(BinarySensorDevice): class DemoBinarySensor(BinarySensorDevice):
"""A Demo binary sensor.""" """representation of a Demo binary sensor."""
def __init__(self, name, state, device_class): def __init__(self, name, state, device_class):
"""Initialize the demo sensor.""" """Initialize the demo sensor."""

View file

@ -13,7 +13,7 @@ ECOBEE_CONFIG_FILE = 'ecobee.conf'
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Ecobee sensors.""" """Set up the Ecobee sensors."""
if discovery_info is None: if discovery_info is None:
return return
data = ecobee.NETWORK data = ecobee.NETWORK

View file

@ -0,0 +1,69 @@
"""
Support for Eight Sleep binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.eight_sleep/
"""
import logging
import asyncio
from homeassistant.components.binary_sensor import BinarySensorDevice
from homeassistant.components.eight_sleep import (
DATA_EIGHT, EightSleepHeatEntity, CONF_BINARY_SENSORS, NAME_MAP)
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['eight_sleep']
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the eight sleep binary sensor."""
if discovery_info is None:
return
name = 'Eight'
sensors = discovery_info[CONF_BINARY_SENSORS]
eight = hass.data[DATA_EIGHT]
all_sensors = []
for sensor in sensors:
all_sensors.append(EightHeatSensor(name, eight, sensor))
async_add_devices(all_sensors, True)
class EightHeatSensor(EightSleepHeatEntity, BinarySensorDevice):
"""Representation of a Eight Sleep heat-based sensor."""
def __init__(self, name, eight, sensor):
"""Initialize the sensor."""
super().__init__(eight)
self._sensor = sensor
self._mapped_name = NAME_MAP.get(self._sensor, self._sensor)
self._name = '{} {}'.format(name, self._mapped_name)
self._state = None
self._side = self._sensor.split('_')[0]
self._userid = self._eight.fetch_userid(self._side)
self._usrobj = self._eight.users[self._userid]
_LOGGER.debug("Presence Sensor: %s, Side: %s, User: %s",
self._sensor, self._side, self._userid)
@property
def name(self):
"""Return the name of the sensor, if any."""
return self._name
@property
def is_on(self):
"""Return true if the binary sensor is on."""
return self._state
@asyncio.coroutine
def async_update(self):
"""Retrieve latest state."""
self._state = self._usrobj.bed_presence

View file

@ -30,7 +30,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Binary Sensor platform fo EnOcean.""" """Set up the Binary Sensor platform for EnOcean."""
dev_id = config.get(CONF_ID) dev_id = config.get(CONF_ID)
devname = config.get(CONF_NAME) devname = config.get(CONF_NAME)
device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS) device_class = get_deprecated(config, CONF_DEVICE_CLASS, CONF_SENSOR_CLASS)
@ -44,7 +44,7 @@ class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice):
def __init__(self, dev_id, devname, device_class): def __init__(self, dev_id, devname, device_class):
"""Initialize the EnOcean binary sensor.""" """Initialize the EnOcean binary sensor."""
enocean.EnOceanDevice.__init__(self) enocean.EnOceanDevice.__init__(self)
self.stype = "listener" self.stype = 'listener'
self.dev_id = dev_id self.dev_id = dev_id
self.which = -1 self.which = -1
self.onoff = -1 self.onoff = -1
@ -53,7 +53,7 @@ class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice):
@property @property
def name(self): def name(self):
"""The default name for the binary sensor.""" """Return the default name for the binary sensor."""
return self.devname return self.devname
@property @property
@ -80,7 +80,7 @@ class EnOceanBinarySensor(enocean.EnOceanDevice, BinarySensorDevice):
elif value2 == 0x10: elif value2 == 0x10:
self.which = 1 self.which = 1
self.onoff = 1 self.onoff = 1
self.hass.bus.fire('button_pressed', {"id": self.dev_id, self.hass.bus.fire('button_pressed', {'id': self.dev_id,
'pushed': value, 'pushed': value,
'which': self.which, 'which': self.which,
'onoff': self.onoff}) 'onoff': self.onoff})

View file

@ -15,13 +15,14 @@ from homeassistant.components.envisalink import (
SIGNAL_ZONE_UPDATE) SIGNAL_ZONE_UPDATE)
from homeassistant.const import ATTR_LAST_TRIP_TIME from homeassistant.const import ATTR_LAST_TRIP_TIME
DEPENDENCIES = ['envisalink']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['envisalink']
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup Envisalink binary sensor devices.""" """Set up the Envisalink binary sensor devices."""
configured_zones = discovery_info['zones'] configured_zones = discovery_info['zones']
devices = [] devices = []

View file

@ -48,23 +48,21 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Create the binary sensor.""" """Set up the FFmpeg binary moition sensor."""
manager = hass.data[DATA_FFMPEG] manager = hass.data[DATA_FFMPEG]
# check source
if not manager.async_run_test(config.get(CONF_INPUT)): if not manager.async_run_test(config.get(CONF_INPUT)):
return return
# generate sensor object
entity = FFmpegMotion(hass, manager, config) entity = FFmpegMotion(hass, manager, config)
async_add_devices([entity]) async_add_devices([entity])
class FFmpegBinarySensor(FFmpegBase, BinarySensorDevice): class FFmpegBinarySensor(FFmpegBase, BinarySensorDevice):
"""A binary sensor which use ffmpeg for noise detection.""" """A binary sensor which use FFmpeg for noise detection."""
def __init__(self, config): def __init__(self, config):
"""Constructor for binary sensor noise detection.""" """Init for the binary sensor noise detection."""
super().__init__(config.get(CONF_INITIAL_STATE)) super().__init__(config.get(CONF_INITIAL_STATE))
self._state = False self._state = False
@ -79,7 +77,7 @@ class FFmpegBinarySensor(FFmpegBase, BinarySensorDevice):
@property @property
def is_on(self): def is_on(self):
"""True if the binary sensor is on.""" """Return true if the binary sensor is on."""
return self._state return self._state
@property @property
@ -89,10 +87,10 @@ class FFmpegBinarySensor(FFmpegBase, BinarySensorDevice):
class FFmpegMotion(FFmpegBinarySensor): class FFmpegMotion(FFmpegBinarySensor):
"""A binary sensor which use ffmpeg for noise detection.""" """A binary sensor which use FFmpeg for noise detection."""
def __init__(self, hass, manager, config): def __init__(self, hass, manager, config):
"""Initialize ffmpeg motion binary sensor.""" """Initialize FFmpeg motion binary sensor."""
from haffmpeg import SensorMotion from haffmpeg import SensorMotion
super().__init__(config) super().__init__(config)
@ -125,4 +123,4 @@ class FFmpegMotion(FFmpegBinarySensor):
@property @property
def device_class(self): def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES.""" """Return the class of this sensor, from DEVICE_CLASSES."""
return "motion" return 'motion'

View file

@ -45,23 +45,21 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Create the binary sensor.""" """Set up the FFmpeg noise binary sensor."""
manager = hass.data[DATA_FFMPEG] manager = hass.data[DATA_FFMPEG]
# check source
if not manager.async_run_test(config.get(CONF_INPUT)): if not manager.async_run_test(config.get(CONF_INPUT)):
return return
# generate sensor object
entity = FFmpegNoise(hass, manager, config) entity = FFmpegNoise(hass, manager, config)
async_add_devices([entity]) async_add_devices([entity])
class FFmpegNoise(FFmpegBinarySensor): class FFmpegNoise(FFmpegBinarySensor):
"""A binary sensor which use ffmpeg for noise detection.""" """A binary sensor which use FFmpeg for noise detection."""
def __init__(self, hass, manager, config): def __init__(self, hass, manager, config):
"""Initialize ffmpeg noise binary sensor.""" """Initialize FFmpeg noise binary sensor."""
from haffmpeg import SensorNoise from haffmpeg import SensorNoise
super().__init__(config) super().__init__(config)
@ -77,14 +75,12 @@ class FFmpegNoise(FFmpegBinarySensor):
if entity_ids is not None and self.entity_id not in entity_ids: if entity_ids is not None and self.entity_id not in entity_ids:
return return
# init config
self.ffmpeg.set_options( self.ffmpeg.set_options(
time_duration=self._config.get(CONF_DURATION), time_duration=self._config.get(CONF_DURATION),
time_reset=self._config.get(CONF_RESET), time_reset=self._config.get(CONF_RESET),
peak=self._config.get(CONF_PEAK), peak=self._config.get(CONF_PEAK),
) )
# run
yield from self.ffmpeg.open_sensor( yield from self.ffmpeg.open_sensor(
input_source=self._config.get(CONF_INPUT), input_source=self._config.get(CONF_INPUT),
output_dest=self._config.get(CONF_OUTPUT), output_dest=self._config.get(CONF_OUTPUT),
@ -94,4 +90,4 @@ class FFmpegNoise(FFmpegBinarySensor):
@property @property
def device_class(self): def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES.""" """Return the class of this sensor, from DEVICE_CLASSES."""
return "sound" return 'sound'

View file

@ -110,7 +110,7 @@ def start_scanning(config, add_entities, client):
def setup_button(hass, config, add_entities, client, address): def setup_button(hass, config, add_entities, client, address):
"""Setup single button device.""" """Set up a single button device."""
timeout = config.get(CONF_TIMEOUT) timeout = config.get(CONF_TIMEOUT)
ignored_click_types = config.get(CONF_IGNORED_CLICK_TYPES) ignored_click_types = config.get(CONF_IGNORED_CLICK_TYPES)
button = FlicButton(hass, client, address, timeout, ignored_click_types) button = FlicButton(hass, client, address, timeout, ignored_click_types)

View file

@ -67,7 +67,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_entities, discovery_info=None): def setup_platform(hass, config, add_entities, discovery_info=None):
"""Setup Hikvision binary sensor devices.""" """Set up the Hikvision binary sensor devices."""
name = config.get(CONF_NAME) name = config.get(CONF_NAME)
host = config.get(CONF_HOST) host = config.get(CONF_HOST)
port = config.get(CONF_PORT) port = config.get(CONF_PORT)
@ -77,16 +77,16 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
customize = config.get(CONF_CUSTOMIZE) customize = config.get(CONF_CUSTOMIZE)
if config.get(CONF_SSL): if config.get(CONF_SSL):
protocol = "https" protocol = 'https'
else: else:
protocol = "http" protocol = 'http'
url = '{}://{}'.format(protocol, host) url = '{}://{}'.format(protocol, host)
data = HikvisionData(hass, url, port, name, username, password) data = HikvisionData(hass, url, port, name, username, password)
if data.sensors is None: if data.sensors is None:
_LOGGER.error('Hikvision event stream has no data, unable to setup.') _LOGGER.error("Hikvision event stream has no data, unable to setup")
return False return False
entities = [] entities = []
@ -104,7 +104,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
ignore = custom.get(CONF_IGNORED) ignore = custom.get(CONF_IGNORED)
delay = custom.get(CONF_DELAY) delay = custom.get(CONF_DELAY)
_LOGGER.debug('Entity: %s - %s, Options - Ignore: %s, Delay: %s', _LOGGER.debug("Entity: %s - %s, Options - Ignore: %s, Delay: %s",
data.name, sensor_name, ignore, delay) data.name, sensor_name, ignore, delay)
if not ignore: if not ignore:
entities.append(HikvisionBinarySensor( entities.append(HikvisionBinarySensor(
@ -126,8 +126,8 @@ class HikvisionData(object):
self._password = password self._password = password
# Establish camera # Establish camera
self.camdata = HikCamera(self._url, self._port, self.camdata = HikCamera(
self._username, self._password) self._url, self._port, self._username, self._password)
if self._name is None: if self._name is None:
self._name = self.camdata.get_name self._name = self.camdata.get_name
@ -251,7 +251,7 @@ class HikvisionBinarySensor(BinarySensorDevice):
# Set timer to wait until updating the state # Set timer to wait until updating the state
def _delay_update(now): def _delay_update(now):
"""Timer callback for sensor update.""" """Timer callback for sensor update."""
_LOGGER.debug('%s Called delayed (%ssec) update.', _LOGGER.debug("%s Called delayed (%ssec) update",
self._name, self._delay) self._name, self._delay)
self.schedule_update_ha_state() self.schedule_update_ha_state()
self._timer = None self._timer = None

View file

@ -14,22 +14,22 @@ _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['homematic'] DEPENDENCIES = ['homematic']
SENSOR_TYPES_CLASS = { SENSOR_TYPES_CLASS = {
"Remote": None, 'Remote': None,
"ShutterContact": "opening", 'ShutterContact': 'opening',
"MaxShutterContact": "opening", 'MaxShutterContact': 'opening',
"IPShutterContact": "opening", 'IPShutterContact': 'opening',
"Smoke": "smoke", 'Smoke': 'smoke',
"SmokeV2": "smoke", 'SmokeV2': 'smoke',
"Motion": "motion", 'Motion': 'motion',
"MotionV2": "motion", 'MotionV2': 'motion',
"RemoteMotion": None, 'RemoteMotion': None,
"WeatherSensor": None, 'WeatherSensor': None,
"TiltSensor": None, 'TiltSensor': None,
} }
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Homematic binary sensor platform.""" """Set up the Homematic binary sensor platform."""
if discovery_info is None: if discovery_info is None:
return return
@ -56,8 +56,8 @@ class HMBinarySensor(HMDevice, BinarySensorDevice):
def device_class(self): def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES.""" """Return the class of this sensor, from DEVICE_CLASSES."""
# If state is MOTION (RemoteMotion works only) # If state is MOTION (RemoteMotion works only)
if self._state == "MOTION": if self._state == 'MOTION':
return "motion" return 'motion'
return SENSOR_TYPES_CLASS.get(self._hmdevice.__class__.__name__, None) return SENSOR_TYPES_CLASS.get(self._hmdevice.__class__.__name__, None)
def _init_data_struct(self): def _init_data_struct(self):

View file

@ -67,7 +67,7 @@ class InsteonPLMBinarySensorDevice(BinarySensorDevice):
def is_on(self): def is_on(self):
"""Return the boolean response if the node is on.""" """Return the boolean response if the node is on."""
sensorstate = self._plm.get_device_attr(self._address, 'sensorstate') sensorstate = self._plm.get_device_attr(self._address, 'sensorstate')
_LOGGER.info('sensor state for %s is %s', self._address, sensorstate) _LOGGER.info("Sensor state for %s is %s", self._address, sensorstate)
return bool(sensorstate) return bool(sensorstate)
@property @property
@ -83,5 +83,5 @@ class InsteonPLMBinarySensorDevice(BinarySensorDevice):
@callback @callback
def async_binarysensor_update(self, message): def async_binarysensor_update(self, message):
"""Receive notification from transport that new data exists.""" """Receive notification from transport that new data exists."""
_LOGGER.info('Received update calback from PLM for %s', self._address) _LOGGER.info("Received update calback from PLM for %s", self._address)
self._hass.async_add_job(self.async_update_ha_state()) self._hass.async_add_job(self.async_update_ha_state())

View file

@ -12,7 +12,6 @@ import homeassistant.components.isy994 as isy
from homeassistant.const import STATE_ON, STATE_OFF from homeassistant.const import STATE_ON, STATE_OFF
from homeassistant.helpers.typing import ConfigType from homeassistant.helpers.typing import ConfigType
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
VALUE_TO_STATE = { VALUE_TO_STATE = {
@ -27,9 +26,9 @@ STATES = [STATE_OFF, STATE_ON, 'true', 'false']
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup_platform(hass, config: ConfigType, def setup_platform(hass, config: ConfigType,
add_devices: Callable[[list], None], discovery_info=None): add_devices: Callable[[list], None], discovery_info=None):
"""Setup the ISY994 binary sensor platform.""" """Set up the ISY994 binary sensor platform."""
if isy.ISY is None or not isy.ISY.connected: if isy.ISY is None or not isy.ISY.connected:
_LOGGER.error('A connection has not been made to the ISY controller.') _LOGGER.error("A connection has not been made to the ISY controller")
return False return False
devices = [] devices = []

View file

@ -11,7 +11,7 @@ DEPENDENCIES = ['knx']
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the KNX binary sensor platform.""" """Set up the KNX binary sensor platform."""
add_devices([KNXSwitch(hass, KNXConfig(config))]) add_devices([KNXSwitch(hass, KNXConfig(config))])

View file

@ -4,7 +4,6 @@ Support for MAX! Window Shutter via MAX! Cube.
For more details about this platform, please refer to the documentation For more details about this platform, please refer to the documentation
https://home-assistant.io/components/maxcube/ https://home-assistant.io/components/maxcube/
""" """
import logging import logging
from homeassistant.components.binary_sensor import BinarySensorDevice from homeassistant.components.binary_sensor import BinarySensorDevice
@ -15,27 +14,24 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Iterate through all MAX! Devices and add window shutters to HASS.""" """Iterate through all MAX! Devices and add window shutters."""
cube = hass.data[MAXCUBE_HANDLE].cube cube = hass.data[MAXCUBE_HANDLE].cube
# List of devices
devices = [] devices = []
for device in cube.devices: for device in cube.devices:
# Create device name by concatenating room name + device name name = "{} {}".format(
name = "%s %s" % (cube.room_by_id(device.room_id).name, device.name) cube.room_by_id(device.room_id).name, device.name)
# Only add Window Shutters # Only add Window Shutters
if cube.is_windowshutter(device): if cube.is_windowshutter(device):
# add device to HASS
devices.append(MaxCubeShutter(hass, name, device.rf_address)) devices.append(MaxCubeShutter(hass, name, device.rf_address))
if len(devices) > 0: if devices:
add_devices(devices) add_devices(devices)
class MaxCubeShutter(BinarySensorDevice): class MaxCubeShutter(BinarySensorDevice):
"""MAX! Cube BinarySensor device.""" """Representation of a MAX! Cube Binary Sensor device."""
def __init__(self, hass, name, rf_address): def __init__(self, hass, name, rf_address):
"""Initialize MAX! Cube BinarySensorDevice.""" """Initialize MAX! Cube BinarySensorDevice."""
@ -47,7 +43,7 @@ class MaxCubeShutter(BinarySensorDevice):
@property @property
def should_poll(self): def should_poll(self):
"""Polling is required.""" """Return the polling state."""
return True return True
@property @property
@ -68,9 +64,5 @@ class MaxCubeShutter(BinarySensorDevice):
def update(self): def update(self):
"""Get latest data from MAX! Cube.""" """Get latest data from MAX! Cube."""
self._cubehandle.update() self._cubehandle.update()
# Get the device we want to update
device = self._cubehandle.cube.device_by_rf(self._rf_address) device = self._cubehandle.cube.device_by_rf(self._rf_address)
# Update our internal state
self._state = device.is_open self._state = device.is_open

View file

@ -16,9 +16,9 @@ from homeassistant.components.sensor import PLATFORM_SCHEMA
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['modbus'] DEPENDENCIES = ['modbus']
CONF_COIL = "coil" CONF_COIL = 'coil'
CONF_COILS = "coils" CONF_COILS = 'coils'
CONF_SLAVE = "slave" CONF_SLAVE = 'slave'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_COILS): [{ vol.Required(CONF_COILS): [{
@ -30,7 +30,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup Modbus binary sensors.""" """Set up the Modbus binary sensors."""
sensors = [] sensors = []
for coil in config.get(CONF_COILS): for coil in config.get(CONF_COILS):
sensors.append(ModbusCoilSensor( sensors.append(ModbusCoilSensor(

View file

@ -79,7 +79,7 @@ class MqttBinarySensor(BinarySensorDevice):
""" """
@callback @callback
def message_received(topic, payload, qos): def message_received(topic, payload, qos):
"""A new MQTT message has been received.""" """Handle a new received MQTT message."""
if self._template is not None: if self._template is not None:
payload = self._template.async_render_with_possible_json_value( payload = self._template.async_render_with_possible_json_value(
payload) payload)
@ -95,7 +95,7 @@ class MqttBinarySensor(BinarySensorDevice):
@property @property
def should_poll(self): def should_poll(self):
"""No polling needed.""" """Return the polling state."""
return False return False
@property @property

View file

@ -16,7 +16,7 @@ DEPENDENCIES = []
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the mysensors platform for sensors.""" """Set up the MySensors platform for sensors."""
# Only act if loaded via mysensors by discovery event. # Only act if loaded via mysensors by discovery event.
# Otherwise gateway is not setup. # Otherwise gateway is not setup.
if discovery_info is None: if discovery_info is None:

View file

@ -16,15 +16,18 @@ DEPENDENCIES = ['nest']
BINARY_TYPES = ['online'] BINARY_TYPES = ['online']
CLIMATE_BINARY_TYPES = ['fan', CLIMATE_BINARY_TYPES = [
'is_using_emergency_heat', 'fan',
'is_locked', 'is_using_emergency_heat',
'has_leaf'] 'is_locked',
'has_leaf',
]
CAMERA_BINARY_TYPES = [ CAMERA_BINARY_TYPES = [
'motion_detected', 'motion_detected',
'sound_detected', 'sound_detected',
'person_detected'] 'person_detected',
]
_BINARY_TYPES_DEPRECATED = [ _BINARY_TYPES_DEPRECATED = [
'hvac_ac_state', 'hvac_ac_state',
@ -34,7 +37,8 @@ _BINARY_TYPES_DEPRECATED = [
'hvac_heat_x3_state', 'hvac_heat_x3_state',
'hvac_alt_heat_state', 'hvac_alt_heat_state',
'hvac_alt_heat_x2_state', 'hvac_alt_heat_x2_state',
'hvac_emer_heat_state'] 'hvac_emer_heat_state',
]
_VALID_BINARY_SENSOR_TYPES = BINARY_TYPES + CLIMATE_BINARY_TYPES \ _VALID_BINARY_SENSOR_TYPES = BINARY_TYPES + CLIMATE_BINARY_TYPES \
+ CAMERA_BINARY_TYPES + CAMERA_BINARY_TYPES
@ -43,7 +47,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup Nest binary sensors.""" """Set up the Nest binary sensors."""
if discovery_info is None: if discovery_info is None:
return return
@ -93,7 +97,7 @@ class NestBinarySensor(NestSensor, BinarySensorDevice):
@property @property
def is_on(self): def is_on(self):
"""True if the binary sensor is on.""" """Return true if the binary sensor is on."""
return self._state return self._state
def update(self): def update(self):

View file

@ -7,6 +7,7 @@ For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.netatmo/. https://home-assistant.io/components/binary_sensor.netatmo/.
""" """
import logging import logging
import voluptuous as vol import voluptuous as vol
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
@ -16,10 +17,9 @@ from homeassistant.loader import get_component
from homeassistant.const import CONF_TIMEOUT, CONF_OFFSET from homeassistant.const import CONF_TIMEOUT, CONF_OFFSET
from homeassistant.helpers import config_validation as cv from homeassistant.helpers import config_validation as cv
DEPENDENCIES = ["netatmo"]
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['netatmo']
# These are the available sensors mapped to binary_sensor class # These are the available sensors mapped to binary_sensor class
WELCOME_SENSOR_TYPES = { WELCOME_SENSOR_TYPES = {
@ -34,8 +34,8 @@ PRESENCE_SENSOR_TYPES = {
"Outdoor vehicle": "motion" "Outdoor vehicle": "motion"
} }
TAG_SENSOR_TYPES = { TAG_SENSOR_TYPES = {
"Tag Vibration": 'vibration', "Tag Vibration": "vibration",
"Tag Open": 'opening' "Tag Open": "opening"
} }
CONF_HOME = 'home' CONF_HOME = 'home'
@ -61,7 +61,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup access to Netatmo binary sensor.""" """Set up the access to Netatmo binary sensor."""
netatmo = get_component('netatmo') netatmo = get_component('netatmo')
home = config.get(CONF_HOME, None) home = config.get(CONF_HOME, None)
timeout = config.get(CONF_TIMEOUT, 15) timeout = config.get(CONF_TIMEOUT, 15)
@ -85,35 +85,31 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
for camera_name in data.get_camera_names(): for camera_name in data.get_camera_names():
camera_type = data.get_camera_type(camera=camera_name, home=home) camera_type = data.get_camera_type(camera=camera_name, home=home)
if camera_type == "NACamera": if camera_type == 'NACamera':
if CONF_CAMERAS in config: if CONF_CAMERAS in config:
if config[CONF_CAMERAS] != [] and \ if config[CONF_CAMERAS] != [] and \
camera_name not in config[CONF_CAMERAS]: camera_name not in config[CONF_CAMERAS]:
continue continue
for variable in welcome_sensors: for variable in welcome_sensors:
add_devices([NetatmoBinarySensor(data, camera_name, add_devices([NetatmoBinarySensor(
module_name, home, timeout, data, camera_name, module_name, home, timeout,
offset, camera_type, offset, camera_type, variable)])
variable)]) if camera_type == 'NOC':
if camera_type == "NOC":
if CONF_CAMERAS in config: if CONF_CAMERAS in config:
if config[CONF_CAMERAS] != [] and \ if config[CONF_CAMERAS] != [] and \
camera_name not in config[CONF_CAMERAS]: camera_name not in config[CONF_CAMERAS]:
continue continue
for variable in presence_sensors: for variable in presence_sensors:
add_devices([NetatmoBinarySensor(data, camera_name, add_devices([NetatmoBinarySensor(
module_name, home, timeout, data, camera_name, module_name, home, timeout, offset,
offset, camera_type, camera_type, variable)])
variable)])
for module_name in data.get_module_names(camera_name): for module_name in data.get_module_names(camera_name):
for variable in tag_sensors: for variable in tag_sensors:
camera_type = None camera_type = None
add_devices([NetatmoBinarySensor(data, camera_name, add_devices([NetatmoBinarySensor(
module_name, home, data, camera_name, module_name, home, timeout, offset,
timeout, offset, camera_type, variable)])
camera_type,
variable)])
class NetatmoBinarySensor(BinarySensorDevice): class NetatmoBinarySensor(BinarySensorDevice):
@ -121,7 +117,7 @@ class NetatmoBinarySensor(BinarySensorDevice):
def __init__(self, data, camera_name, module_name, home, def __init__(self, data, camera_name, module_name, home,
timeout, offset, camera_type, sensor): timeout, offset, camera_type, sensor):
"""Setup for access to the Netatmo camera events.""" """Set up for access to the Netatmo camera events."""
self._data = data self._data = data
self._camera_name = camera_name self._camera_name = camera_name
self._module_name = module_name self._module_name = module_name
@ -129,23 +125,23 @@ class NetatmoBinarySensor(BinarySensorDevice):
self._timeout = timeout self._timeout = timeout
self._offset = offset self._offset = offset
if home: if home:
self._name = home + ' / ' + camera_name self._name = '{} / {}'.format(home, camera_name)
else: else:
self._name = camera_name self._name = camera_name
if module_name: if module_name:
self._name += ' / ' + module_name self._name += ' / ' + module_name
self._sensor_name = sensor self._sensor_name = sensor
self._name += ' ' + sensor self._name += ' ' + sensor
camera_id = data.camera_data.cameraByName(camera=camera_name, camera_id = data.camera_data.cameraByName(
home=home)['id'] camera=camera_name, home=home)['id']
self._unique_id = "Netatmo_binary_sensor {0} - {1}".format(self._name, self._unique_id = "Netatmo_binary_sensor {0} - {1}".format(
camera_id) self._name, camera_id)
self._cameratype = camera_type self._cameratype = camera_type
self.update() self.update()
@property @property
def name(self): def name(self):
"""The name of the Netatmo device and this sensor.""" """Return the name of the Netatmo device and this sensor."""
return self._name return self._name
@property @property
@ -156,9 +152,9 @@ class NetatmoBinarySensor(BinarySensorDevice):
@property @property
def device_class(self): def device_class(self):
"""Return the class of this sensor, from DEVICE_CLASSES.""" """Return the class of this sensor, from DEVICE_CLASSES."""
if self._cameratype == "NACamera": if self._cameratype == 'NACamera':
return WELCOME_SENSOR_TYPES.get(self._sensor_name) return WELCOME_SENSOR_TYPES.get(self._sensor_name)
elif self._cameratype == "NOC": elif self._cameratype == 'NOC':
return PRESENCE_SENSOR_TYPES.get(self._sensor_name) return PRESENCE_SENSOR_TYPES.get(self._sensor_name)
else: else:
return TAG_SENSOR_TYPES.get(self._sensor_name) return TAG_SENSOR_TYPES.get(self._sensor_name)
@ -173,51 +169,44 @@ class NetatmoBinarySensor(BinarySensorDevice):
self._data.update() self._data.update()
self._data.update_event() self._data.update_event()
if self._cameratype == "NACamera": if self._cameratype == 'NACamera':
if self._sensor_name == "Someone known": if self._sensor_name == "Someone known":
self._state =\ self._state =\
self._data.camera_data.someoneKnownSeen(self._home, self._data.camera_data.someoneKnownSeen(
self._camera_name, self._home, self._camera_name, self._timeout*60)
self._timeout*60)
elif self._sensor_name == "Someone unknown": elif self._sensor_name == "Someone unknown":
self._state =\ self._state =\
self._data.camera_data.someoneUnknownSeen( self._data.camera_data.someoneUnknownSeen(
self._home, self._camera_name, self._timeout*60) self._home, self._camera_name, self._timeout*60)
elif self._sensor_name == "Motion": elif self._sensor_name == "Motion":
self._state =\ self._state =\
self._data.camera_data.motionDetected(self._home, self._data.camera_data.motionDetected(
self._camera_name, self._home, self._camera_name, self._timeout*60)
self._timeout*60) elif self._cameratype == 'NOC':
elif self._cameratype == "NOC":
if self._sensor_name == "Outdoor motion": if self._sensor_name == "Outdoor motion":
self._state =\ self._state =\
self._data.camera_data.outdoormotionDetected( self._data.camera_data.outdoormotionDetected(
self._home, self._camera_name, self._offset) self._home, self._camera_name, self._offset)
elif self._sensor_name == "Outdoor human": elif self._sensor_name == "Outdoor human":
self._state =\ self._state =\
self._data.camera_data.humanDetected(self._home, self._data.camera_data.humanDetected(
self._camera_name, self._home, self._camera_name, self._offset)
self._offset)
elif self._sensor_name == "Outdoor animal": elif self._sensor_name == "Outdoor animal":
self._state =\ self._state =\
self._data.camera_data.animalDetected(self._home, self._data.camera_data.animalDetected(
self._camera_name, self._home, self._camera_name, self._offset)
self._offset)
elif self._sensor_name == "Outdoor vehicle": elif self._sensor_name == "Outdoor vehicle":
self._state =\ self._state =\
self._data.camera_data.carDetected(self._home, self._data.camera_data.carDetected(
self._camera_name, self._home, self._camera_name, self._offset)
self._offset)
if self._sensor_name == "Tag Vibration": if self._sensor_name == "Tag Vibration":
self._state =\ self._state =\
self._data.camera_data.moduleMotionDetected(self._home, self._data.camera_data.moduleMotionDetected(
self._module_name, self._home, self._module_name, self._camera_name,
self._camera_name, self._timeout*60)
self._timeout*60)
elif self._sensor_name == "Tag Open": elif self._sensor_name == "Tag Open":
self._state =\ self._state =\
self._data.camera_data.moduleOpened(self._home, self._data.camera_data.moduleOpened(
self._module_name, self._home, self._module_name, self._camera_name)
self._camera_name)
else: else:
return None return None

View file

@ -41,7 +41,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the NX584 binary sensor platform.""" """Set up the NX584 binary sensor platform."""
from nx584 import client as nx584_client from nx584 import client as nx584_client
host = config.get(CONF_HOST) host = config.get(CONF_HOST)
@ -53,7 +53,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
client = nx584_client.Client('http://{}:{}'.format(host, port)) client = nx584_client.Client('http://{}:{}'.format(host, port))
zones = client.list_zones() zones = client.list_zones()
except requests.exceptions.ConnectionError as ex: except requests.exceptions.ConnectionError as ex:
_LOGGER.error('Unable to connect to NX584: %s', str(ex)) _LOGGER.error("Unable to connect to NX584: %s", str(ex))
return False return False
version = [int(v) for v in client.get_version().split('.')] version = [int(v) for v in client.get_version().split('.')]

View file

@ -9,14 +9,12 @@ import logging
import requests import requests
import voluptuous as vol import voluptuous as vol
from homeassistant.const import ( from homeassistant.const import CONF_NAME, CONF_MONITORED_CONDITIONS
CONF_NAME, STATE_ON, STATE_OFF, CONF_MONITORED_CONDITIONS)
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
BinarySensorDevice, PLATFORM_SCHEMA) BinarySensorDevice, PLATFORM_SCHEMA)
from homeassistant.loader import get_component from homeassistant.loader import get_component
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['octoprint'] DEPENDENCIES = ['octoprint']
@ -38,22 +36,18 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the available OctoPrint binary sensors.""" """Set up the available OctoPrint binary sensors."""
octoprint = get_component('octoprint') octoprint = get_component('octoprint')
name = config.get(CONF_NAME) name = config.get(CONF_NAME)
monitored_conditions = config.get(CONF_MONITORED_CONDITIONS, monitored_conditions = config.get(
SENSOR_TYPES.keys()) CONF_MONITORED_CONDITIONS, SENSOR_TYPES.keys())
devices = [] devices = []
for octo_type in monitored_conditions: for octo_type in monitored_conditions:
new_sensor = OctoPrintBinarySensor(octoprint.OCTOPRINT, new_sensor = OctoPrintBinarySensor(
octo_type, octoprint.OCTOPRINT, octo_type, SENSOR_TYPES[octo_type][2],
SENSOR_TYPES[octo_type][2], name, SENSOR_TYPES[octo_type][3], SENSOR_TYPES[octo_type][0],
name, SENSOR_TYPES[octo_type][1], 'flags')
SENSOR_TYPES[octo_type][3],
SENSOR_TYPES[octo_type][0],
SENSOR_TYPES[octo_type][1],
'flags')
devices.append(new_sensor) devices.append(new_sensor)
add_devices(devices) add_devices(devices)
@ -85,18 +79,10 @@ class OctoPrintBinarySensor(BinarySensorDevice):
"""Return the name of the sensor.""" """Return the name of the sensor."""
return self._name return self._name
@property
def state(self):
"""Return the state of the sensor."""
return self.is_on
@property @property
def is_on(self): def is_on(self):
"""Return true if binary sensor is on.""" """Return true if binary sensor is on."""
if self._state: return bool(self._state)
return STATE_ON
else:
return STATE_OFF
@property @property
def device_class(self): def device_class(self):
@ -106,10 +92,9 @@ class OctoPrintBinarySensor(BinarySensorDevice):
def update(self): def update(self):
"""Update state of sensor.""" """Update state of sensor."""
try: try:
self._state = self.api.update(self.sensor_type, self._state = self.api.update(
self.api_endpoint, self.sensor_type, self.api_endpoint, self.api_group,
self.api_group, self.api_tool)
self.api_tool)
except requests.exceptions.ConnectionError: except requests.exceptions.ConnectionError:
# Error calling the api, already logged in api.update() # Error calling the api, already logged in api.update()
return return

View file

@ -0,0 +1,186 @@
"""
Support for Pilight binary sensors.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.pilight/
"""
import datetime
import logging
import voluptuous as vol
from homeassistant.components import pilight
from homeassistant.components.binary_sensor import (
PLATFORM_SCHEMA,
BinarySensorDevice,
)
from homeassistant.const import (
CONF_DISARM_AFTER_TRIGGER,
CONF_NAME,
CONF_PAYLOAD,
CONF_PAYLOAD_OFF,
CONF_PAYLOAD_ON
)
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.event import track_point_in_time
from homeassistant.util import dt as dt_util
_LOGGER = logging.getLogger(__name__)
CONF_VARIABLE = 'variable'
DEFAULT_NAME = 'Pilight Binary Sensor'
DEPENDENCIES = ['pilight']
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_VARIABLE): cv.string,
vol.Required(CONF_PAYLOAD): vol.Schema(dict),
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
vol.Optional(CONF_PAYLOAD_ON, default='on'): cv.string,
vol.Optional(CONF_PAYLOAD_OFF, default='off'): cv.string,
vol.Optional(CONF_DISARM_AFTER_TRIGGER, default=False): cv.boolean
})
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
"""Set up Pilight Binary Sensor."""
disarm = config.get(CONF_DISARM_AFTER_TRIGGER)
if disarm:
add_devices([PilightTriggerSensor(
hass=hass,
name=config.get(CONF_NAME),
variable=config.get(CONF_VARIABLE),
payload=config.get(CONF_PAYLOAD),
on_value=config.get(CONF_PAYLOAD_ON),
off_value=config.get(CONF_PAYLOAD_OFF),
)])
else:
add_devices([PilightBinarySensor(
hass=hass,
name=config.get(CONF_NAME),
variable=config.get(CONF_VARIABLE),
payload=config.get(CONF_PAYLOAD),
on_value=config.get(CONF_PAYLOAD_ON),
off_value=config.get(CONF_PAYLOAD_OFF),
)])
class PilightBinarySensor(BinarySensorDevice):
"""Representation of a binary sensor that can be updated using Pilight."""
def __init__(self, hass, name, variable, payload, on_value, off_value):
"""Initialize the sensor."""
self._state = False
self._hass = hass
self._name = name
self._variable = variable
self._payload = payload
self._on_value = on_value
self._off_value = off_value
hass.bus.listen(pilight.EVENT, self._handle_code)
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def is_on(self):
"""Return True if the binary sensor is on."""
return self._state
def _handle_code(self, call):
"""Handle received code by the pilight-daemon.
If the code matches the defined playload
of this sensor the sensor state is changed accordingly.
"""
# Check if received code matches defined playoad
# True if payload is contained in received code dict
payload_ok = True
for key in self._payload:
if key not in call.data:
payload_ok = False
continue
if self._payload[key] != call.data[key]:
payload_ok = False
# Read out variable if payload ok
if payload_ok:
if self._variable not in call.data:
return
value = call.data[self._variable]
self._state = (value == self._on_value)
self.schedule_update_ha_state()
class PilightTriggerSensor(BinarySensorDevice):
"""Representation of a binary sensor that can be updated using Pilight."""
def __init__(
self,
hass,
name,
variable,
payload,
on_value,
off_value,
rst_dly_sec=30):
"""Initialize the sensor."""
self._state = False
self._hass = hass
self._name = name
self._variable = variable
self._payload = payload
self._on_value = on_value
self._off_value = off_value
self._reset_delay_sec = rst_dly_sec
self._delay_after = None
self._hass = hass
hass.bus.listen(pilight.EVENT, self._handle_code)
@property
def name(self):
"""Return the name of the sensor."""
return self._name
@property
def is_on(self):
"""Return True if the binary sensor is on."""
return self._state
def _reset_state(self, call):
self._state = False
self._delay_after = None
self.schedule_update_ha_state()
def _handle_code(self, call):
"""Handle received code by the pilight-daemon.
If the code matches the defined playload
of this sensor the sensor state is changed accordingly.
"""
# Check if received code matches defined playoad
# True if payload is contained in received code dict
payload_ok = True
for key in self._payload:
if key not in call.data:
payload_ok = False
continue
if self._payload[key] != call.data[key]:
payload_ok = False
# Read out variable if payload ok
if payload_ok:
if self._variable not in call.data:
return
value = call.data[self._variable]
self._state = (value == self._on_value)
if self._delay_after is None:
self._delay_after = dt_util.utcnow() + datetime.timedelta(
seconds=self._reset_delay_sec)
track_point_in_time(
self._hass, self._reset_state,
self._delay_after)
self.schedule_update_ha_state()

View file

@ -35,6 +35,9 @@ SCAN_INTERVAL = timedelta(minutes=5)
PING_MATCHER = re.compile( PING_MATCHER = re.compile(
r'(?P<min>\d+.\d+)\/(?P<avg>\d+.\d+)\/(?P<max>\d+.\d+)\/(?P<mdev>\d+.\d+)') r'(?P<min>\d+.\d+)\/(?P<avg>\d+.\d+)\/(?P<max>\d+.\d+)\/(?P<mdev>\d+.\d+)')
WIN32_PING_MATCHER = re.compile(
r'(?P<min>\d+)ms.+(?P<max>\d+)ms.+(?P<avg>\d+)ms')
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
vol.Required(CONF_HOST): cv.string, vol.Required(CONF_HOST): cv.string,
vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string, vol.Optional(CONF_NAME, default=DEFAULT_NAME): cv.string,
@ -102,7 +105,7 @@ class PingData(object):
if sys.platform == 'win32': if sys.platform == 'win32':
self._ping_cmd = [ self._ping_cmd = [
'ping', '-n', str(self._count), '-w 1000', self._ip_address] 'ping', '-n', str(self._count), '-w', '1000', self._ip_address]
else: else:
self._ping_cmd = [ self._ping_cmd = [
'ping', '-n', '-q', '-c', str(self._count), '-W1', 'ping', '-n', '-q', '-c', str(self._count), '-W1',
@ -114,13 +117,23 @@ class PingData(object):
self._ping_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) self._ping_cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
try: try:
out = pinger.communicate() out = pinger.communicate()
match = PING_MATCHER.search(str(out).split('\n')[-1]) _LOGGER.debug("Output is %s", str(out))
rtt_min, rtt_avg, rtt_max, rtt_mdev = match.groups() if sys.platform == 'win32':
return { match = WIN32_PING_MATCHER.search(str(out).split('\n')[-1])
'min': rtt_min, rtt_min, rtt_avg, rtt_max = match.groups()
'avg': rtt_avg, return {
'max': rtt_max, 'min': rtt_min,
'mdev': rtt_mdev} 'avg': rtt_avg,
'max': rtt_max,
'mdev': ''}
else:
match = PING_MATCHER.search(str(out).split('\n')[-1])
rtt_min, rtt_avg, rtt_max, rtt_mdev = match.groups()
return {
'min': rtt_min,
'avg': rtt_avg,
'max': rtt_max,
'mdev': rtt_mdev}
except (subprocess.CalledProcessError, AttributeError): except (subprocess.CalledProcessError, AttributeError):
return False return False

View file

@ -44,7 +44,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the REST binary sensor.""" """Set up the REST binary sensor."""
name = config.get(CONF_NAME) name = config.get(CONF_NAME)
resource = config.get(CONF_RESOURCE) resource = config.get(CONF_RESOURCE)
method = config.get(CONF_METHOD) method = config.get(CONF_METHOD)
@ -114,8 +114,8 @@ class RestBinarySensor(BinarySensorDevice):
try: try:
return bool(int(response)) return bool(int(response))
except ValueError: except ValueError:
return {"true": True, "on": True, "open": True, return {'true': True, 'on': True, 'open': True,
"yes": True}.get(response.lower(), False) 'yes': True}.get(response.lower(), False)
def update(self): def update(self):
"""Get the latest data from REST API and updates the state.""" """Get the latest data from REST API and updates the state."""

View file

@ -41,10 +41,10 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Raspberry PI GPIO devices.""" """Set up the Raspberry PI GPIO devices."""
pull_mode = config.get('pull_mode', DEFAULT_PULL_MODE) pull_mode = config.get(CONF_PULL_MODE)
bouncetime = config.get('bouncetime', DEFAULT_BOUNCETIME) bouncetime = config.get(CONF_BOUNCETIME)
invert_logic = config.get('invert_logic', DEFAULT_INVERT_LOGIC) invert_logic = config.get(CONF_INVERT_LOGIC)
binary_sensors = [] binary_sensors = []
ports = config.get('ports') ports = config.get('ports')

View file

@ -11,7 +11,7 @@ DEPENDENCIES = ['sleepiq']
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the SleepIQ sensors.""" """Set up the SleepIQ sensors."""
if discovery_info is None: if discovery_info is None:
return return

View file

@ -27,5 +27,5 @@ class TcpBinarySensor(BinarySensorDevice, TcpSensor):
@property @property
def is_on(self): def is_on(self):
"""True if the binary sensor is on.""" """Return true if the binary sensor is on."""
return self._state == self._config[CONF_VALUE_ON] return self._state == self._config[CONF_VALUE_ON]

View file

@ -41,7 +41,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup template binary sensors.""" """Set up template binary sensors."""
sensors = [] sensors = []
for device, device_config in config[CONF_SENSORS].items(): for device, device_config in config[CONF_SENSORS].items():
@ -57,15 +57,11 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
sensors.append( sensors.append(
BinarySensorTemplate( BinarySensorTemplate(
hass, hass, device, friendly_name, device_class, value_template,
device,
friendly_name,
device_class,
value_template,
entity_ids) entity_ids)
) )
if not sensors: if not sensors:
_LOGGER.error('No sensors added') _LOGGER.error("No sensors added")
return False return False
async_add_devices(sensors, True) async_add_devices(sensors, True)
@ -79,8 +75,8 @@ class BinarySensorTemplate(BinarySensorDevice):
value_template, entity_ids): value_template, entity_ids):
"""Initialize the Template binary sensor.""" """Initialize the Template binary sensor."""
self.hass = hass self.hass = hass
self.entity_id = async_generate_entity_id(ENTITY_ID_FORMAT, device, self.entity_id = async_generate_entity_id(
hass=hass) ENTITY_ID_FORMAT, device, hass=hass)
self._name = friendly_name self._name = friendly_name
self._device_class = device_class self._device_class = device_class
self._template = value_template self._template = value_template
@ -96,7 +92,7 @@ class BinarySensorTemplate(BinarySensorDevice):
@callback @callback
def template_bsensor_state_listener(entity, old_state, new_state): def template_bsensor_state_listener(entity, old_state, new_state):
"""Called when the target device changes state.""" """Handle the target device state changes."""
self.hass.async_add_job(self.async_update_ha_state(True)) self.hass.async_add_job(self.async_update_ha_state(True))
@callback @callback
@ -139,8 +135,8 @@ class BinarySensorTemplate(BinarySensorDevice):
if ex.args and ex.args[0].startswith( if ex.args and ex.args[0].startswith(
"UndefinedError: 'None' has no attribute"): "UndefinedError: 'None' has no attribute"):
# Common during HA startup - so just a warning # Common during HA startup - so just a warning
_LOGGER.warning('Could not render template %s,' _LOGGER.warning("Could not render template %s, "
' the state is unknown.', self._name) "the state is unknown", self._name)
return return
_LOGGER.error('Could not render template %s: %s', self._name, ex) _LOGGER.error("Could not render template %s: %s", self._name, ex)
self._state = False self._state = False

View file

@ -77,7 +77,7 @@ class ThresholdSensor(BinarySensorDevice):
# pylint: disable=invalid-name # pylint: disable=invalid-name
def async_threshold_sensor_state_listener( def async_threshold_sensor_state_listener(
entity, old_state, new_state): entity, old_state, new_state):
"""Called when the sensor changes state.""" """Handle sensor state changes."""
if new_state.state == STATE_UNKNOWN: if new_state.state == STATE_UNKNOWN:
return return

View file

@ -6,22 +6,18 @@ https://home-assistant.io/components/sensor.trend/
""" """
import asyncio import asyncio
import logging import logging
import voluptuous as vol import voluptuous as vol
from homeassistant.core import callback from homeassistant.core import callback
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.components.binary_sensor import ( from homeassistant.components.binary_sensor import (
BinarySensorDevice, BinarySensorDevice, ENTITY_ID_FORMAT, PLATFORM_SCHEMA,
ENTITY_ID_FORMAT,
PLATFORM_SCHEMA,
DEVICE_CLASSES_SCHEMA) DEVICE_CLASSES_SCHEMA)
from homeassistant.const import ( from homeassistant.const import (
ATTR_FRIENDLY_NAME, ATTR_FRIENDLY_NAME, ATTR_ENTITY_ID, CONF_SENSOR_CLASS,
ATTR_ENTITY_ID, CONF_DEVICE_CLASS, STATE_UNKNOWN,)
CONF_SENSOR_CLASS,
CONF_DEVICE_CLASS,
STATE_UNKNOWN,)
from homeassistant.helpers.deprecation import get_deprecated from homeassistant.helpers.deprecation import get_deprecated
from homeassistant.helpers.entity import generate_entity_id from homeassistant.helpers.entity import generate_entity_id
from homeassistant.helpers.event import track_state_change from homeassistant.helpers.event import track_state_change
@ -47,7 +43,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the trend sensors.""" """Set up the trend sensors."""
sensors = [] sensors = []
for device, device_config in config[CONF_SENSORS].items(): for device, device_config in config[CONF_SENSORS].items():
@ -60,13 +56,8 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
sensors.append( sensors.append(
SensorTrend( SensorTrend(
hass, hass, device, friendly_name, entity_id, attribute,
device, device_class, invert)
friendly_name,
entity_id,
attribute,
device_class,
invert)
) )
if not sensors: if not sensors:
_LOGGER.error("No sensors added") _LOGGER.error("No sensors added")
@ -82,8 +73,8 @@ class SensorTrend(BinarySensorDevice):
target_entity, attribute, device_class, invert): target_entity, attribute, device_class, invert):
"""Initialize the sensor.""" """Initialize the sensor."""
self._hass = hass self._hass = hass
self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, device_id, self.entity_id = generate_entity_id(
hass=hass) ENTITY_ID_FORMAT, device_id, hass=hass)
self._name = friendly_name self._name = friendly_name
self._target_entity = target_entity self._target_entity = target_entity
self._attribute = attribute self._attribute = attribute
@ -95,7 +86,7 @@ class SensorTrend(BinarySensorDevice):
@callback @callback
def trend_sensor_state_listener(entity, old_state, new_state): def trend_sensor_state_listener(entity, old_state, new_state):
"""Called when the target device changes state.""" """Handle the target device state changes."""
self.from_state = old_state self.from_state = old_state
self.to_state = new_state self.to_state = new_state
hass.async_add_job(self.async_update_ha_state(True)) hass.async_add_job(self.async_update_ha_state(True))

View file

@ -3,7 +3,6 @@ Support for VOC.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/binary_sensor.volvooncall/ https://home-assistant.io/components/binary_sensor.volvooncall/
""" """
import logging import logging
@ -14,7 +13,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup Volvo sensors.""" """Set up the Volvo sensors."""
if discovery_info is None: if discovery_info is None:
return return
add_devices([VolvoSensor(hass, *discovery_info)]) add_devices([VolvoSensor(hass, *discovery_info)])
@ -28,7 +27,7 @@ class VolvoSensor(VolvoEntity, BinarySensorDevice):
"""Return True if the binary sensor is on.""" """Return True if the binary sensor is on."""
val = getattr(self.vehicle, self._attribute) val = getattr(self.vehicle, self._attribute)
if self._attribute == 'bulb_failures': if self._attribute == 'bulb_failures':
return len(val) > 0 return bool(val)
elif self._attribute in ['doors', 'windows']: elif self._attribute in ['doors', 'windows']:
return any([val[key] for key in val if 'Open' in key]) return any([val[key] for key in val if 'Open' in key])
else: else:

View file

@ -29,7 +29,7 @@ def setup_platform(hass, config, add_devices_callback, discovery_info=None):
class WemoBinarySensor(BinarySensorDevice): class WemoBinarySensor(BinarySensorDevice):
"""Represents a WeMo binary sensor.""" """Representation a WeMo binary sensor."""
def __init__(self, device): def __init__(self, device):
"""Initialize the WeMo sensor.""" """Initialize the WeMo sensor."""
@ -41,10 +41,8 @@ class WemoBinarySensor(BinarySensorDevice):
wemo.SUBSCRIPTION_REGISTRY.on(self.wemo, None, self._update_callback) wemo.SUBSCRIPTION_REGISTRY.on(self.wemo, None, self._update_callback)
def _update_callback(self, _device, _type, _params): def _update_callback(self, _device, _type, _params):
"""Called by the Wemo device callback to update state.""" """Handle state changes."""
_LOGGER.info( _LOGGER.info("Subscription update for %s", _device)
'Subscription update for %s',
_device)
updated = self.wemo.subscription_update(_type, _params) updated = self.wemo.subscription_update(_type, _params)
self._update(force_update=(not updated)) self._update(force_update=(not updated))
@ -60,7 +58,7 @@ class WemoBinarySensor(BinarySensorDevice):
@property @property
def unique_id(self): def unique_id(self):
"""Return the id of this WeMo device.""" """Return the id of this WeMo device."""
return "{}.{}".format(self.__class__, self.wemo.serialnumber) return '{}.{}'.format(self.__class__, self.wemo.serialnumber)
@property @property
def name(self): def name(self):
@ -69,7 +67,7 @@ class WemoBinarySensor(BinarySensorDevice):
@property @property
def is_on(self): def is_on(self):
"""True if sensor is on.""" """Return true if sensor is on."""
return self._state return self._state
def update(self): def update(self):
@ -80,5 +78,5 @@ class WemoBinarySensor(BinarySensorDevice):
try: try:
self._state = self.wemo.get_state(force_update) self._state = self.wemo.get_state(force_update)
except AttributeError as err: except AttributeError as err:
_LOGGER.warning('Could not update status for %s (%s)', _LOGGER.warning(
self.name, err) "Could not update status for %s (%s)", self.name, err)

View file

@ -16,23 +16,23 @@ DEPENDENCIES = ['wink']
# These are the available sensors mapped to binary_sensor class # These are the available sensors mapped to binary_sensor class
SENSOR_TYPES = { SENSOR_TYPES = {
"opened": "opening", 'opened': 'opening',
"brightness": "light", 'brightness': 'light',
"vibration": "vibration", 'vibration': 'vibration',
"loudness": "sound", 'loudness': 'sound',
"noise": "sound", 'noise': 'sound',
"capturing_audio": "sound", 'capturing_audio': 'sound',
"liquid_detected": "moisture", 'liquid_detected': 'moisture',
"motion": "motion", 'motion': 'motion',
"presence": "occupancy", 'presence': 'occupancy',
"co_detected": "gas", 'co_detected': 'gas',
"smoke_detected": "smoke", 'smoke_detected': 'smoke',
"capturing_video": None 'capturing_video': None
} }
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Wink binary sensor platform.""" """Set up the Wink binary sensor platform."""
import pywink import pywink
for sensor in pywink.get_sensors(): for sensor in pywink.get_sensors():
@ -83,7 +83,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
if camera_sensor.capability() in SENSOR_TYPES: if camera_sensor.capability() in SENSOR_TYPES:
add_devices([WinkBinarySensorDevice(camera_sensor, hass)]) add_devices([WinkBinarySensorDevice(camera_sensor, hass)])
except AttributeError: except AttributeError:
_LOGGER.info("Device isn't a sensor, skipping.") _LOGGER.info("Device isn't a sensor, skipping")
class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity): class WinkBinarySensorDevice(WinkDevice, BinarySensorDevice, Entity):

View file

@ -11,10 +11,9 @@ import datetime
import voluptuous as vol import voluptuous as vol
from homeassistant.components.sensor import PLATFORM_SCHEMA from homeassistant.components.sensor import PLATFORM_SCHEMA
from homeassistant.const import ( from homeassistant.const import CONF_NAME, WEEKDAYS
STATE_ON, STATE_OFF, STATE_UNKNOWN, CONF_NAME, WEEKDAYS)
import homeassistant.util.dt as dt_util import homeassistant.util.dt as dt_util
from homeassistant.helpers.entity import Entity from homeassistant.components.binary_sensor import BinarySensorDevice
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
@ -66,15 +65,20 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
obj_holidays = getattr(holidays, country)(years=year) obj_holidays = getattr(holidays, country)(years=year)
if province: if province:
if province not in obj_holidays.PROVINCES and \ # 'state' and 'prov' are not interchangeable, so need to make
province not in obj_holidays.STATES: # sure we use the right one
if (hasattr(obj_holidays, "PROVINCES") and
province in obj_holidays.PROVINCES):
obj_holidays = getattr(holidays, country)(prov=province,
years=year)
elif (hasattr(obj_holidays, "STATES") and
province in obj_holidays.STATES):
obj_holidays = getattr(holidays, country)(state=province,
years=year)
else:
_LOGGER.error("There is no province/state %s in country %s", _LOGGER.error("There is no province/state %s in country %s",
province, country) province, country)
return False return False
else:
year = datetime.datetime.now().year
obj_holidays = getattr(holidays, country)(prov=province,
years=year)
_LOGGER.debug("Found the following holidays for your configuration:") _LOGGER.debug("Found the following holidays for your configuration:")
for date, name in sorted(obj_holidays.items()): for date, name in sorted(obj_holidays.items()):
@ -92,7 +96,7 @@ def day_to_string(day):
return None return None
class IsWorkdaySensor(Entity): class IsWorkdaySensor(BinarySensorDevice):
"""Implementation of a Workday sensor.""" """Implementation of a Workday sensor."""
def __init__(self, obj_holidays, workdays, excludes, name): def __init__(self, obj_holidays, workdays, excludes, name):
@ -101,7 +105,7 @@ class IsWorkdaySensor(Entity):
self._obj_holidays = obj_holidays self._obj_holidays = obj_holidays
self._workdays = workdays self._workdays = workdays
self._excludes = excludes self._excludes = excludes
self._state = STATE_UNKNOWN self._state = None
@property @property
def name(self): def name(self):
@ -109,7 +113,7 @@ class IsWorkdaySensor(Entity):
return self._name return self._name
@property @property
def state(self): def is_on(self):
"""Return the state of the device.""" """Return the state of the device."""
return self._state return self._state
@ -135,14 +139,14 @@ class IsWorkdaySensor(Entity):
def async_update(self): def async_update(self):
"""Get date and look whether it is a holiday.""" """Get date and look whether it is a holiday."""
# Default is no workday # Default is no workday
self._state = STATE_OFF self._state = False
# Get iso day of the week (1 = Monday, 7 = Sunday) # Get iso day of the week (1 = Monday, 7 = Sunday)
day = datetime.datetime.today().isoweekday() - 1 day = datetime.datetime.today().isoweekday() - 1
day_of_week = day_to_string(day) day_of_week = day_to_string(day)
if self.is_include(day_of_week, dt_util.now()): if self.is_include(day_of_week, dt_util.now()):
self._state = STATE_ON self._state = True
if self.is_exclude(day_of_week, dt_util.now()): if self.is_exclude(day_of_week, dt_util.now()):
self._state = STATE_OFF self._state = False

View file

@ -0,0 +1,89 @@
"""
Binary sensors on Zigbee Home Automation networks.
For more details on this platform, please refer to the documentation
at https://home-assistant.io/components/binary_sensor.zha/
"""
import asyncio
import logging
from homeassistant.components.binary_sensor import DOMAIN, BinarySensorDevice
from homeassistant.components import zha
_LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['zha']
# ZigBee Cluster Library Zone Type to Home Assistant device class
CLASS_MAPPING = {
0x000d: 'motion',
0x0015: 'opening',
0x0028: 'smoke',
0x002a: 'moisture',
0x002b: 'gas',
0x002d: 'vibration',
}
@asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Set up the Zigbee Home Automation binary sensors."""
discovery_info = zha.get_discovery_info(hass, discovery_info)
if discovery_info is None:
return
from bellows.zigbee.zcl.clusters.security import IasZone
clusters = discovery_info['clusters']
device_class = None
cluster = [c for c in clusters if isinstance(c, IasZone)][0]
if discovery_info['new_join']:
yield from cluster.bind()
ieee = cluster.endpoint.device.application.ieee
yield from cluster.write_attributes({'cie_addr': ieee})
try:
zone_type = yield from cluster['zone_type']
device_class = CLASS_MAPPING.get(zone_type, None)
except Exception: # pylint: disable=broad-except
# If we fail to read from the device, use a non-specific class
pass
sensor = BinarySensor(device_class, **discovery_info)
async_add_devices([sensor])
class BinarySensor(zha.Entity, BinarySensorDevice):
"""THe ZHA Binary Sensor."""
_domain = DOMAIN
def __init__(self, device_class, **kwargs):
"""Initialize the ZHA binary sensor."""
super().__init__(**kwargs)
self._device_class = device_class
from bellows.zigbee.zcl.clusters.security import IasZone
self._ias_zone_cluster = self._clusters[IasZone.cluster_id]
@property
def is_on(self) -> bool:
"""Return True if entity is on."""
if self._state == 'unknown':
return False
return bool(self._state)
@property
def device_class(self):
"""Return the class of this device, from component DEVICE_CLASSES."""
return self._device_class
def cluster_command(self, aps_frame, tsn, command_id, args):
"""Handle commands received to this cluster."""
if command_id == 0:
self._state = args[0] & 3
_LOGGER.debug("Updated alarm state: %s", self._state)
self.schedule_update_ha_state()
elif command_id == 1:
_LOGGER.debug("Enroll requested")
self.hass.add_job(self._ias_zone_cluster.enroll_response(0, 0))

View file

@ -23,7 +23,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the ZigBee binary sensor platform.""" """Set up the ZigBee binary sensor platform."""
add_devices( add_devices(
[ZigBeeBinarySensor(hass, ZigBeeDigitalInConfig(config))], True) [ZigBeeBinarySensor(hass, ZigBeeDigitalInConfig(config))], True)

View file

@ -20,7 +20,7 @@ DEPENDENCIES = []
def get_device(values, **kwargs): def get_device(values, **kwargs):
"""Create zwave entity device.""" """Create Z-Wave entity device."""
device_mapping = workaround.get_device_mapping(values.primary) device_mapping = workaround.get_device_mapping(values.primary)
if device_mapping == workaround.WORKAROUND_NO_OFF_EVENT: if device_mapping == workaround.WORKAROUND_NO_OFF_EVENT:
# Default the multiplier to 4 # Default the multiplier to 4
@ -45,12 +45,12 @@ class ZWaveBinarySensor(BinarySensorDevice, zwave.ZWaveDeviceEntity):
self._state = self.values.primary.data self._state = self.values.primary.data
def update_properties(self): def update_properties(self):
"""Callback on data changes for node values.""" """Handle data changes for node values."""
self._state = self.values.primary.data self._state = self.values.primary.data
@property @property
def is_on(self): def is_on(self):
"""Return True if the binary sensor is on.""" """Return true if the binary sensor is on."""
return self._state return self._state
@property @property
@ -69,7 +69,7 @@ class ZWaveTriggerSensor(ZWaveBinarySensor):
self.invalidate_after = None self.invalidate_after = None
def update_properties(self): def update_properties(self):
"""Called when a value for this entity's node has changed.""" """Handle value changes for this entity's node."""
self._state = self.values.primary.data self._state = self.values.primary.data
# only allow this value to be true for re_arm secs # only allow this value to be true for re_arm secs
if not self.hass: if not self.hass:
@ -83,7 +83,7 @@ class ZWaveTriggerSensor(ZWaveBinarySensor):
@property @property
def is_on(self): def is_on(self):
"""Return True if movement has happened within the rearm time.""" """Return true if movement has happened within the rearm time."""
return self._state and \ return self._state and \
(self.invalidate_after is None or (self.invalidate_after is None or
self.invalidate_after > dt_util.utcnow()) self.invalidate_after > dt_util.utcnow())

View file

@ -35,7 +35,7 @@ CONFIG_SCHEMA = vol.Schema({
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup(hass, config): def setup(hass, config):
"""Setup BloomSky component.""" """Set up the BloomSky component."""
api_key = config[DOMAIN][CONF_API_KEY] api_key = config[DOMAIN][CONF_API_KEY]
global BLOOMSKY global BLOOMSKY
@ -67,9 +67,8 @@ class BloomSky(object):
def refresh_devices(self): def refresh_devices(self):
"""Use the API to retrieve a list of devices.""" """Use the API to retrieve a list of devices."""
_LOGGER.debug("Fetching BloomSky update") _LOGGER.debug("Fetching BloomSky update")
response = requests.get(self.API_URL, response = requests.get(
headers={"Authorization": self._api_key}, self.API_URL, headers={"Authorization": self._api_key}, timeout=10)
timeout=10)
if response.status_code == 401: if response.status_code == 401:
raise RuntimeError("Invalid API_KEY") raise RuntimeError("Invalid API_KEY")
elif response.status_code != 200: elif response.status_code != 200:

View file

@ -7,12 +7,10 @@ https://home-assistant.io/components/calendar/
import asyncio import asyncio
import logging import logging
from datetime import timedelta from datetime import timedelta
import re import re
from homeassistant.components.google import (CONF_OFFSET, from homeassistant.components.google import (
CONF_DEVICE_ID, CONF_OFFSET, CONF_DEVICE_ID, CONF_NAME)
CONF_NAME)
from homeassistant.const import STATE_OFF, STATE_ON from homeassistant.const import STATE_OFF, STATE_ON
from homeassistant.helpers.config_validation import time_period_str from homeassistant.helpers.config_validation import time_period_str
from homeassistant.helpers.entity import Entity, generate_entity_id from homeassistant.helpers.entity import Entity, generate_entity_id
@ -22,16 +20,18 @@ from homeassistant.util import dt
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
SCAN_INTERVAL = timedelta(seconds=60)
DOMAIN = 'calendar' DOMAIN = 'calendar'
ENTITY_ID_FORMAT = DOMAIN + '.{}' ENTITY_ID_FORMAT = DOMAIN + '.{}'
SCAN_INTERVAL = timedelta(seconds=60)
@asyncio.coroutine @asyncio.coroutine
def async_setup(hass, config): def async_setup(hass, config):
"""Track states and offer events for calendars.""" """Track states and offer events for calendars."""
component = EntityComponent( component = EntityComponent(
logging.getLogger(__name__), DOMAIN, hass, SCAN_INTERVAL, DOMAIN) _LOGGER, DOMAIN, hass, SCAN_INTERVAL, DOMAIN)
yield from component.async_setup(config) yield from component.async_setup(config)
return True return True
@ -55,9 +55,8 @@ class CalendarEventDevice(Entity):
self._name = data.get(CONF_NAME) self._name = data.get(CONF_NAME)
self.dev_id = data.get(CONF_DEVICE_ID) self.dev_id = data.get(CONF_DEVICE_ID)
self._offset = data.get(CONF_OFFSET, DEFAULT_CONF_OFFSET) self._offset = data.get(CONF_OFFSET, DEFAULT_CONF_OFFSET)
self.entity_id = generate_entity_id(ENTITY_ID_FORMAT, self.entity_id = generate_entity_id(
self.dev_id, ENTITY_ID_FORMAT, self.dev_id, hass=hass)
hass=hass)
self._cal_data = { self._cal_data = {
'all_day': False, 'all_day': False,
@ -87,7 +86,7 @@ class CalendarEventDevice(Entity):
@property @property
def device_state_attributes(self): def device_state_attributes(self):
"""State Attributes for HA.""" """Return the device state attributes."""
start = self._cal_data.get('start', None) start = self._cal_data.get('start', None)
end = self._cal_data.get('end', None) end = self._cal_data.get('end', None)
start = start.strftime(DATE_STR_FORMAT) if start is not None else None start = start.strftime(DATE_STR_FORMAT) if start is not None else None

View file

@ -10,7 +10,7 @@ from homeassistant.components.google import CONF_DEVICE_ID, CONF_NAME
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo binary sensor platform.""" """Set up the Demo Calendar platform."""
calendar_data_future = DemoGoogleCalendarDataFuture() calendar_data_future = DemoGoogleCalendarDataFuture()
calendar_data_current = DemoGoogleCalendarDataCurrent() calendar_data_current = DemoGoogleCalendarDataCurrent()
add_devices([ add_devices([
@ -27,7 +27,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class DemoGoogleCalendarData(object): class DemoGoogleCalendarData(object):
"""Setup base class for data.""" """Representation of a Demo Calendar element."""
# pylint: disable=no-self-use # pylint: disable=no-self-use
def update(self): def update(self):
@ -36,7 +36,7 @@ class DemoGoogleCalendarData(object):
class DemoGoogleCalendarDataFuture(DemoGoogleCalendarData): class DemoGoogleCalendarDataFuture(DemoGoogleCalendarData):
"""Setup future data event.""" """Representation of a Demo Calendar for a future event."""
def __init__(self): def __init__(self):
"""Set the event to a future event.""" """Set the event to a future event."""
@ -55,7 +55,7 @@ class DemoGoogleCalendarDataFuture(DemoGoogleCalendarData):
class DemoGoogleCalendarDataCurrent(DemoGoogleCalendarData): class DemoGoogleCalendarDataCurrent(DemoGoogleCalendarData):
"""Create a current event we're in the middle of.""" """Representation of a Demo Calendar for a current event."""
def __init__(self): def __init__(self):
"""Set the event data.""" """Set the event data."""
@ -74,9 +74,9 @@ class DemoGoogleCalendarDataCurrent(DemoGoogleCalendarData):
class DemoGoogleCalendar(CalendarEventDevice): class DemoGoogleCalendar(CalendarEventDevice):
"""A Demo binary sensor.""" """Representation of a Demo Calendar element."""
def __init__(self, hass, calendar_data, data): def __init__(self, hass, calendar_data, data):
"""The same as a google calendar but without the api calls.""" """Initialize Google Calendar but without the API calls."""
self.data = calendar_data self.data = calendar_data
super().__init__(hass, data) super().__init__(hass, data)

View file

@ -9,25 +9,24 @@ import logging
from datetime import timedelta from datetime import timedelta
from homeassistant.components.calendar import CalendarEventDevice from homeassistant.components.calendar import CalendarEventDevice
from homeassistant.components.google import (CONF_CAL_ID, CONF_ENTITIES, from homeassistant.components.google import (
CONF_TRACK, TOKEN_FILE, CONF_CAL_ID, CONF_ENTITIES, CONF_TRACK, TOKEN_FILE,
GoogleCalendarService) GoogleCalendarService)
from homeassistant.util import Throttle, dt from homeassistant.util import Throttle, dt
_LOGGER = logging.getLogger(__name__)
DEFAULT_GOOGLE_SEARCH_PARAMS = { DEFAULT_GOOGLE_SEARCH_PARAMS = {
'orderBy': 'startTime', 'orderBy': 'startTime',
'maxResults': 1, 'maxResults': 1,
'singleEvents': True, 'singleEvents': True,
} }
# Return cached results if last scan was less then this time ago
MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15) MIN_TIME_BETWEEN_UPDATES = timedelta(minutes=15)
_LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, disc_info=None): def setup_platform(hass, config, add_devices, disc_info=None):
"""Setup the calendar platform for event devices.""" """Set up the calendar platform for event devices."""
if disc_info is None: if disc_info is None:
return return
@ -55,7 +54,7 @@ class GoogleCalendarData(object):
"""Class to utilize calendar service object to get next event.""" """Class to utilize calendar service object to get next event."""
def __init__(self, calendar_service, calendar_id, search=None): def __init__(self, calendar_service, calendar_id, search=None):
"""Setup how we are going to search the google calendar.""" """Set up how we are going to search the google calendar."""
self.calendar_service = calendar_service self.calendar_service = calendar_service
self.calendar_id = calendar_id self.calendar_id = calendar_id
self.search = search self.search = search

View file

@ -76,7 +76,7 @@ def async_get_image(hass, entity_id, timeout=10):
@asyncio.coroutine @asyncio.coroutine
def async_setup(hass, config): def async_setup(hass, config):
"""Setup the camera component.""" """Set up the camera component."""
component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL) component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)
hass.http.register_view(CameraImageView(component.entities)) hass.http.register_view(CameraImageView(component.entities))
@ -121,12 +121,12 @@ class Camera(Entity):
@property @property
def brand(self): def brand(self):
"""Camera brand.""" """Return the camera brand."""
return None return None
@property @property
def model(self): def model(self):
"""Camera model.""" """Return the camera model."""
return None return None
def camera_image(self): def camera_image(self):
@ -191,7 +191,7 @@ class Camera(Entity):
@property @property
def state(self): def state(self):
"""Camera state.""" """Return the camera state."""
if self.is_recording: if self.is_recording:
return STATE_RECORDING return STATE_RECORDING
elif self.is_streaming: elif self.is_streaming:
@ -201,7 +201,7 @@ class Camera(Entity):
@property @property
def state_attributes(self): def state_attributes(self):
"""Camera state attributes.""" """Return the camera state attributes."""
attr = { attr = {
'access_token': self.access_tokens[-1], 'access_token': self.access_tokens[-1],
} }
@ -233,7 +233,7 @@ class CameraView(HomeAssistantView):
@asyncio.coroutine @asyncio.coroutine
def get(self, request, entity_id): def get(self, request, entity_id):
"""Start a get request.""" """Start a GET request."""
camera = self.entities.get(entity_id) camera = self.entities.get(entity_id)
if camera is None: if camera is None:
@ -251,15 +251,15 @@ class CameraView(HomeAssistantView):
@asyncio.coroutine @asyncio.coroutine
def handle(self, request, camera): def handle(self, request, camera):
"""Hanlde the camera request.""" """Handle the camera request."""
raise NotImplementedError() raise NotImplementedError()
class CameraImageView(CameraView): class CameraImageView(CameraView):
"""Camera view to serve an image.""" """Camera view to serve an image."""
url = "/api/camera_proxy/{entity_id}" url = '/api/camera_proxy/{entity_id}'
name = "api:camera:image" name = 'api:camera:image'
@asyncio.coroutine @asyncio.coroutine
def handle(self, request, camera): def handle(self, request, camera):
@ -277,8 +277,8 @@ class CameraImageView(CameraView):
class CameraMjpegStream(CameraView): class CameraMjpegStream(CameraView):
"""Camera View to serve an MJPEG stream.""" """Camera View to serve an MJPEG stream."""
url = "/api/camera_proxy_stream/{entity_id}" url = '/api/camera_proxy_stream/{entity_id}'
name = "api:camera:stream" name = 'api:camera:stream'
@asyncio.coroutine @asyncio.coroutine
def handle(self, request, camera): def handle(self, request, camera):

View file

@ -21,7 +21,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup a Blink Camera.""" """Set up a Blink Camera."""
if discovery_info is None: if discovery_info is None:
return return
@ -49,19 +49,19 @@ class BlinkCamera(Camera):
@property @property
def name(self): def name(self):
"""A camera name.""" """Return the camera name."""
return self._name return self._name
@Throttle(MIN_TIME_BETWEEN_UPDATES) @Throttle(MIN_TIME_BETWEEN_UPDATES)
def request_image(self): def request_image(self):
"""An image request from Blink servers.""" """Request a new image from Blink servers."""
_LOGGER.info("Requesting new image from blink servers") _LOGGER.info("Requesting new image from blink servers")
image_url = self.check_for_motion() image_url = self.check_for_motion()
header = self.data.cameras[self._name].header header = self.data.cameras[self._name].header
self.response = requests.get(image_url, headers=header, stream=True) self.response = requests.get(image_url, headers=header, stream=True)
def check_for_motion(self): def check_for_motion(self):
"""A method to check if motion has been detected since last update.""" """Check if motion has been detected since last update."""
self.data.refresh() self.data.refresh()
notifs = self.data.cameras[self._name].notifications notifs = self.data.cameras[self._name].notifications
if notifs > self.notifications: if notifs > self.notifications:

View file

@ -16,7 +16,7 @@ DEPENDENCIES = ['bloomsky']
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup access to BloomSky cameras.""" """Set up access to BloomSky cameras."""
bloomsky = get_component('bloomsky') bloomsky = get_component('bloomsky')
for device in bloomsky.BLOOMSKY.devices.values(): for device in bloomsky.BLOOMSKY.devices.values():
add_devices([BloomSkyCamera(bloomsky.BLOOMSKY, device)]) add_devices([BloomSkyCamera(bloomsky.BLOOMSKY, device)])
@ -26,14 +26,14 @@ class BloomSkyCamera(Camera):
"""Representation of the images published from the BloomSky's camera.""" """Representation of the images published from the BloomSky's camera."""
def __init__(self, bs, device): def __init__(self, bs, device):
"""Setup for access to the BloomSky camera images.""" """Initialize access to the BloomSky camera images."""
super(BloomSkyCamera, self).__init__() super(BloomSkyCamera, self).__init__()
self._name = device['DeviceName'] self._name = device['DeviceName']
self._id = device['DeviceID'] self._id = device['DeviceID']
self._bloomsky = bs self._bloomsky = bs
self._url = "" self._url = ""
self._last_url = "" self._last_url = ""
# _last_image will store images as they are downloaded so that the # last_image will store images as they are downloaded so that the
# frequent updates in home-assistant don't keep poking the server # frequent updates in home-assistant don't keep poking the server
# to download the same image over and over. # to download the same image over and over.
self._last_image = "" self._last_image = ""

View file

@ -11,7 +11,7 @@ from homeassistant.components.camera import Camera
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo camera platform.""" """Set up the Demo camera platform."""
add_devices([ add_devices([
DemoCamera('Demo camera') DemoCamera('Demo camera')
]) ])
@ -29,8 +29,8 @@ class DemoCamera(Camera):
"""Return a faked still image response.""" """Return a faked still image response."""
now = dt_util.utcnow() now = dt_util.utcnow()
image_path = os.path.join(os.path.dirname(__file__), image_path = os.path.join(
'demo_{}.jpg'.format(now.second % 4)) os.path.dirname(__file__), 'demo_{}.jpg'.format(now.second % 4))
with open(image_path, 'rb') as file: with open(image_path, 'rb') as file:
return file.read() return file.read()

View file

@ -16,10 +16,10 @@ from homeassistant.components.ffmpeg import (
import homeassistant.helpers.config_validation as cv import homeassistant.helpers.config_validation as cv
from homeassistant.helpers.aiohttp_client import ( from homeassistant.helpers.aiohttp_client import (
async_aiohttp_proxy_stream) async_aiohttp_proxy_stream)
DEPENDENCIES = ['ffmpeg']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
DEPENDENCIES = ['ffmpeg']
DEFAULT_NAME = 'FFmpeg' DEFAULT_NAME = 'FFmpeg'
PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@ -31,7 +31,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a FFmpeg Camera.""" """Set up a FFmpeg camera."""
if not hass.data[DATA_FFMPEG].async_run_test(config.get(CONF_INPUT)): if not hass.data[DATA_FFMPEG].async_run_test(config.get(CONF_INPUT)):
return return
async_add_devices([FFmpegCamera(hass, config)]) async_add_devices([FFmpegCamera(hass, config)])

View file

@ -32,7 +32,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup a Foscam IP Camera.""" """Set up a Foscam IP Camera."""
add_devices([FoscamCamera(config)]) add_devices([FoscamCamera(config)])
@ -60,7 +60,7 @@ class FoscamCamera(Camera):
) )
self._name = device_info.get(CONF_NAME) self._name = device_info.get(CONF_NAME)
_LOGGER.info('Using the following URL for %s: %s', _LOGGER.info("Using the following URL for %s: %s",
self._name, uri_template.format('***', '***')) self._name, uri_template.format('***', '***'))
def camera_image(self): def camera_image(self):

View file

@ -43,7 +43,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine @asyncio.coroutine
# pylint: disable=unused-argument # pylint: disable=unused-argument
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a generic IP Camera.""" """Set up a generic IP Camera."""
async_add_devices([GenericCamera(hass, config)]) async_add_devices([GenericCamera(hass, config)])
@ -85,8 +85,8 @@ class GenericCamera(Camera):
try: try:
url = self._still_image_url.async_render() url = self._still_image_url.async_render()
except TemplateError as err: except TemplateError as err:
_LOGGER.error('Error parsing template %s: %s', _LOGGER.error(
self._still_image_url, err) "Error parsing template %s: %s", self._still_image_url, err)
return self._last_image return self._last_image
if url == self._last_url and self._limit_refetch: if url == self._last_url and self._limit_refetch:
@ -100,7 +100,7 @@ class GenericCamera(Camera):
response = requests.get(url, timeout=10, auth=self._auth) response = requests.get(url, timeout=10, auth=self._auth)
return response.content return response.content
except requests.exceptions.RequestException as error: except requests.exceptions.RequestException as error:
_LOGGER.error('Error getting camera image: %s', error) _LOGGER.error("Error getting camera image: %s", error)
return self._last_image return self._last_image
self._last_image = yield from self.hass.loop.run_in_executor( self._last_image = yield from self.hass.loop.run_in_executor(
@ -114,10 +114,10 @@ class GenericCamera(Camera):
url, auth=self._auth) url, auth=self._auth)
self._last_image = yield from response.read() self._last_image = yield from response.read()
except asyncio.TimeoutError: except asyncio.TimeoutError:
_LOGGER.error('Timeout getting camera image') _LOGGER.error("Timeout getting camera image")
return self._last_image return self._last_image
except aiohttp.ClientError as err: except aiohttp.ClientError as err:
_LOGGER.error('Error getting new camera image: %s', err) _LOGGER.error("Error getting new camera image: %s", err)
return self._last_image return self._last_image
self._last_url = url self._last_url = url

View file

@ -26,7 +26,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Camera.""" """Set up the Camera that works with local files."""
file_path = config[CONF_FILE_PATH] file_path = config[CONF_FILE_PATH]
# check filepath given is readable # check filepath given is readable
@ -38,7 +38,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class LocalFile(Camera): class LocalFile(Camera):
"""Local camera.""" """Representation of a local file camera."""
def __init__(self, name, file_path): def __init__(self, name, file_path):
"""Initialize Local File Camera component.""" """Initialize Local File Camera component."""

View file

@ -44,7 +44,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine @asyncio.coroutine
# pylint: disable=unused-argument # pylint: disable=unused-argument
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a MJPEG IP Camera.""" """Set up a MJPEG IP Camera."""
if discovery_info: if discovery_info:
config = PLATFORM_SCHEMA(discovery_info) config = PLATFORM_SCHEMA(discovery_info)
async_add_devices([MjpegCamera(hass, config)]) async_add_devices([MjpegCamera(hass, config)])
@ -102,10 +102,10 @@ class MjpegCamera(Camera):
return image return image
except asyncio.TimeoutError: except asyncio.TimeoutError:
_LOGGER.error('Timeout getting camera image') _LOGGER.error("Timeout getting camera image")
except aiohttp.ClientError as err: except aiohttp.ClientError as err:
_LOGGER.error('Error getting new camera image: %s', err) _LOGGER.error("Error getting new camera image: %s", err)
def camera_image(self): def camera_image(self):
"""Return a still image response from the camera.""" """Return a still image response from the camera."""

View file

@ -32,17 +32,17 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup the Camera.""" """Set up the MQTT Camera."""
topic = config[CONF_TOPIC] topic = config[CONF_TOPIC]
async_add_devices([MqttCamera(config[CONF_NAME], topic)]) async_add_devices([MqttCamera(config[CONF_NAME], topic)])
class MqttCamera(Camera): class MqttCamera(Camera):
"""MQTT camera.""" """representation of a MQTT camera."""
def __init__(self, name, topic): def __init__(self, name, topic):
"""Initialize Local File Camera component.""" """Initialize the MQTT Camera."""
super().__init__() super().__init__()
self._name = name self._name = name
@ -61,13 +61,13 @@ class MqttCamera(Camera):
return self._name return self._name
def async_added_to_hass(self): def async_added_to_hass(self):
"""Subscribe mqtt events. """Subscribe MQTT events.
This method must be run in the event loop and returns a coroutine. This method must be run in the event loop and returns a coroutine.
""" """
@callback @callback
def message_received(topic, payload, qos): def message_received(topic, payload, qos):
"""A new MQTT message has been received.""" """Handle new MQTT messages."""
self._last_image = payload self._last_image = payload
return mqtt.async_subscribe( return mqtt.async_subscribe(

View file

@ -1,5 +1,5 @@
""" """
Camera that loads a picture from a local file. Camera that loads a picture from Neato.
For more details about this platform, please refer to the documentation at For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/camera.neato/ https://home-assistant.io/components/camera.neato/
@ -18,12 +18,12 @@ DEPENDENCIES = ['neato']
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Camera.""" """Set up the Neato Camera."""
dev = [] dev = []
for robot in hass.data[NEATO_ROBOTS]: for robot in hass.data[NEATO_ROBOTS]:
if 'maps' in robot.traits: if 'maps' in robot.traits:
dev.append(NeatoCleaningMap(hass, robot)) dev.append(NeatoCleaningMap(hass, robot))
_LOGGER.debug('Adding robots for cleaning maps %s', dev) _LOGGER.debug("Adding robots for cleaning maps %s", dev)
add_devices(dev, True) add_devices(dev, True)
@ -34,7 +34,7 @@ class NeatoCleaningMap(Camera):
"""Initialize Neato cleaning map.""" """Initialize Neato cleaning map."""
super().__init__() super().__init__()
self.robot = robot self.robot = robot
self._robot_name = self.robot.name + ' Cleaning Map' self._robot_name = '{} {}'.format(self.robot.name, 'Cleaning Map')
self._robot_serial = self.robot.serial self._robot_serial = self.robot.serial
self.neato = hass.data[NEATO_LOGIN] self.neato = hass.data[NEATO_LOGIN]
self._image_url = None self._image_url = None
@ -53,7 +53,7 @@ class NeatoCleaningMap(Camera):
map_data = self.hass.data[NEATO_MAP_DATA] map_data = self.hass.data[NEATO_MAP_DATA]
image_url = map_data[self._robot_serial]['maps'][0]['url'] image_url = map_data[self._robot_serial]['maps'][0]['url']
if image_url == self._image_url: if image_url == self._image_url:
_LOGGER.debug('The map image_url is the same as old') _LOGGER.debug("The map image_url is the same as old")
return return
image = self.neato.download_map(image_url) image = self.neato.download_map(image_url)
self._image = image.read() self._image = image.read()

View file

@ -32,7 +32,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-argument # pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup access to Netatmo cameras.""" """Set up access to Netatmo cameras."""
netatmo = get_component('netatmo') netatmo = get_component('netatmo')
home = config.get(CONF_HOME) home = config.get(CONF_HOME)
verify_ssl = config.get(CONF_VERIFY_SSL, True) verify_ssl = config.get(CONF_VERIFY_SSL, True)
@ -55,7 +55,7 @@ class NetatmoCamera(Camera):
"""Representation of the images published from a Netatmo camera.""" """Representation of the images published from a Netatmo camera."""
def __init__(self, data, camera_name, home, camera_type, verify_ssl): def __init__(self, data, camera_name, home, camera_type, verify_ssl):
"""Setup for access to the Netatmo camera images.""" """Set up for access to the Netatmo camera images."""
super(NetatmoCamera, self).__init__() super(NetatmoCamera, self).__init__()
self._data = data self._data = data
self._camera_name = camera_name self._camera_name = camera_name
@ -64,10 +64,10 @@ class NetatmoCamera(Camera):
self._name = home + ' / ' + camera_name self._name = home + ' / ' + camera_name
else: else:
self._name = camera_name self._name = camera_name
camera_id = data.camera_data.cameraByName(camera=camera_name, camera_id = data.camera_data.cameraByName(
home=home)['id'] camera=camera_name, home=home)['id']
self._unique_id = "Welcome_camera {0} - {1}".format(self._name, self._unique_id = "Welcome_camera {0} - {1}".format(
camera_id) self._name, camera_id)
self._vpnurl, self._localurl = self._data.camera_data.cameraUrls( self._vpnurl, self._localurl = self._data.camera_data.cameraUrls(
camera=camera_name camera=camera_name
) )
@ -83,13 +83,13 @@ class NetatmoCamera(Camera):
response = requests.get('{0}/live/snapshot_720.jpg'.format( response = requests.get('{0}/live/snapshot_720.jpg'.format(
self._vpnurl), timeout=10, verify=self._verify_ssl) self._vpnurl), timeout=10, verify=self._verify_ssl)
else: else:
_LOGGER.error('Welcome VPN url is None') _LOGGER.error("Welcome VPN URL is None")
self._data.update() self._data.update()
(self._vpnurl, self._localurl) = \ (self._vpnurl, self._localurl) = \
self._data.camera_data.cameraUrls(camera=self._camera_name) self._data.camera_data.cameraUrls(camera=self._camera_name)
return None return None
except requests.exceptions.RequestException as error: except requests.exceptions.RequestException as error:
_LOGGER.error('Welcome url changed: %s', error) _LOGGER.error("Welcome URL changed: %s", error)
self._data.update() self._data.update()
(self._vpnurl, self._localurl) = \ (self._vpnurl, self._localurl) = \
self._data.camera_data.cameraUrls(camera=self._camera_name) self._data.camera_data.cameraUrls(camera=self._camera_name)
@ -103,12 +103,12 @@ class NetatmoCamera(Camera):
@property @property
def brand(self): def brand(self):
"""Camera brand.""" """Return the camera brand."""
return "Netatmo" return "Netatmo"
@property @property
def model(self): def model(self):
"""Camera model.""" """Return the camera model."""
if self._cameratype == "NOC": if self._cameratype == "NOC":
return "Presence" return "Presence"
elif self._cameratype == "NACamera": elif self._cameratype == "NACamera":

View file

@ -62,7 +62,7 @@ def kill_raspistill(*args):
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Raspberry Camera.""" """Set up the Raspberry Camera."""
if shutil.which("raspistill") is None: if shutil.which("raspistill") is None:
_LOGGER.error("'raspistill' was not found") _LOGGER.error("'raspistill' was not found")
return False return False

View file

@ -59,7 +59,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup a Synology IP Camera.""" """Set up a Synology IP Camera."""
verify_ssl = config.get(CONF_VERIFY_SSL) verify_ssl = config.get(CONF_VERIFY_SSL)
timeout = config.get(CONF_TIMEOUT) timeout = config.get(CONF_TIMEOUT)
websession_init = async_get_clientsession(hass, verify_ssl) websession_init = async_get_clientsession(hass, verify_ssl)
@ -140,16 +140,8 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
snapshot_path = camera['snapshot_path'] snapshot_path = camera['snapshot_path']
device = SynologyCamera( device = SynologyCamera(
hass, hass, websession, config, camera_id, camera['name'],
websession, snapshot_path, streaming_path, camera_path, auth_path, timeout
config,
camera_id,
camera['name'],
snapshot_path,
streaming_path,
camera_path,
auth_path,
timeout
) )
devices.append(device) devices.append(device)

View file

@ -41,13 +41,13 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
try: try:
cameras = nvrconn.index() cameras = nvrconn.index()
except nvr.NotAuthorized: except nvr.NotAuthorized:
_LOGGER.error('Authorization failure while connecting to NVR') _LOGGER.error("Authorization failure while connecting to NVR")
return False return False
except nvr.NvrError: except nvr.NvrError:
_LOGGER.error('NVR refuses to talk to me') _LOGGER.error("NVR refuses to talk to me")
return False return False
except requests.exceptions.ConnectionError as ex: except requests.exceptions.ConnectionError as ex:
_LOGGER.error('Unable to connect to NVR: %s', str(ex)) _LOGGER.error("Unable to connect to NVR: %s", str(ex))
return False return False
identifier = nvrconn.server_version >= (3, 2, 0) and 'id' or 'uuid' identifier = nvrconn.server_version >= (3, 2, 0) and 'id' or 'uuid'
@ -113,7 +113,7 @@ class UnifiVideoCamera(Camera):
store = uvc_store.get_info_store() store = uvc_store.get_info_store()
password = store.get_camera_password(self._uuid) password = store.get_camera_password(self._uuid)
if password is None: if password is None:
_LOGGER.debug('Logging into camera %(name)s with default password', _LOGGER.debug("Logging into camera %(name)s with default password",
dict(name=self._name)) dict(name=self._name))
password = 'ubnt' password = 'ubnt'
@ -125,11 +125,10 @@ class UnifiVideoCamera(Camera):
camera = None camera = None
for addr in addrs: for addr in addrs:
try: try:
camera = client_cls(addr, camera = client_cls(
caminfo['username'], addr, caminfo['username'], password)
password)
camera.login() camera.login()
_LOGGER.debug('Logged into UVC camera %(name)s via %(addr)s', _LOGGER.debug("Logged into UVC camera %(name)s via %(addr)s",
dict(name=self._name, addr=addr)) dict(name=self._name, addr=addr))
self._connect_addr = addr self._connect_addr = addr
break break
@ -140,7 +139,7 @@ class UnifiVideoCamera(Camera):
except uvc_camera.CameraAuthError: except uvc_camera.CameraAuthError:
pass pass
if not self._connect_addr: if not self._connect_addr:
_LOGGER.error('Unable to login to camera') _LOGGER.error("Unable to login to camera")
return None return None
self._camera = camera self._camera = camera
@ -157,14 +156,14 @@ class UnifiVideoCamera(Camera):
try: try:
return self._camera.get_snapshot() return self._camera.get_snapshot()
except uvc_camera.CameraConnectError: except uvc_camera.CameraConnectError:
_LOGGER.error('Unable to contact camera') _LOGGER.error("Unable to contact camera")
except uvc_camera.CameraAuthError: except uvc_camera.CameraAuthError:
if retry: if retry:
self._login() self._login()
return _get_image(retry=False) return _get_image(retry=False)
else: else:
_LOGGER.error('Unable to log into camera, unable ' _LOGGER.error(
'to get snapshot') "Unable to log into camera, unable to get snapshot")
raise raise
return _get_image() return _get_image()

View file

@ -17,7 +17,7 @@ _LOGGER = logging.getLogger(__name__)
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Camera.""" """Set up the Verisure Camera."""
if not int(hub.config.get(CONF_SMARTCAM, 1)): if not int(hub.config.get(CONF_SMARTCAM, 1)):
return False return False
directory_path = hass.config.config_dir directory_path = hass.config.config_dir
@ -33,7 +33,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
class VerisureSmartcam(Camera): class VerisureSmartcam(Camera):
"""Local camera.""" """Representation of a Verisure camera."""
def __init__(self, hass, device_id, directory_path): def __init__(self, hass, device_id, directory_path):
"""Initialize Verisure File Camera component.""" """Initialize Verisure File Camera component."""
@ -50,9 +50,9 @@ class VerisureSmartcam(Camera):
"""Return image response.""" """Return image response."""
self.check_imagelist() self.check_imagelist()
if not self._image: if not self._image:
_LOGGER.debug('No image to display') _LOGGER.debug("No image to display")
return return
_LOGGER.debug('Trying to open %s', self._image) _LOGGER.debug("Trying to open %s", self._image)
with open(self._image, 'rb') as file: with open(self._image, 'rb') as file:
return file.read() return file.read()
@ -64,35 +64,30 @@ class VerisureSmartcam(Camera):
return return
images = hub.smartcam_dict[self._device_id] images = hub.smartcam_dict[self._device_id]
new_image_id = images[0] new_image_id = images[0]
_LOGGER.debug('self._device_id=%s, self._images=%s, ' _LOGGER.debug("self._device_id=%s, self._images=%s, "
'self._new_image_id=%s', self._device_id, "self._new_image_id=%s", self._device_id,
images, new_image_id) images, new_image_id)
if (new_image_id == '-1' or if (new_image_id == '-1' or
self._image_id == new_image_id): self._image_id == new_image_id):
_LOGGER.debug('The image is the same, or loading image_id') _LOGGER.debug("The image is the same, or loading image_id")
return return
_LOGGER.debug('Download new image %s', new_image_id) _LOGGER.debug("Download new image %s", new_image_id)
hub.my_pages.smartcam.download_image(self._device_id, hub.my_pages.smartcam.download_image(
new_image_id, self._device_id, new_image_id, self._directory_path)
self._directory_path) _LOGGER.debug("Old image_id=%s", self._image_id)
_LOGGER.debug('Old image_id=%s', self._image_id)
self.delete_image(self) self.delete_image(self)
self._image_id = new_image_id self._image_id = new_image_id
self._image = os.path.join(self._directory_path, self._image = os.path.join(
'{}{}'.format( self._directory_path, '{}{}'.format(self._image_id, '.jpg'))
self._image_id,
'.jpg'))
def delete_image(self, event): def delete_image(self, event):
"""Delete an old image.""" """Delete an old image."""
remove_image = os.path.join(self._directory_path, remove_image = os.path.join(
'{}{}'.format( self._directory_path, '{}{}'.format(self._image_id, '.jpg'))
self._image_id,
'.jpg'))
try: try:
os.remove(remove_image) os.remove(remove_image)
_LOGGER.debug('Deleting old image %s', remove_image) _LOGGER.debug("Deleting old image %s", remove_image)
except OSError as error: except OSError as error:
if error.errno != errno.ENOENT: if error.errno != errno.ENOENT:
raise raise

View file

@ -51,21 +51,21 @@ def _get_image_url(hass, monitor, mode):
@asyncio.coroutine @asyncio.coroutine
# pylint: disable=unused-argument # pylint: disable=unused-argument
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup ZoneMinder cameras.""" """Set up the ZoneMinder cameras."""
cameras = [] cameras = []
monitors = zoneminder.get_state('api/monitors.json') monitors = zoneminder.get_state('api/monitors.json')
if not monitors: if not monitors:
_LOGGER.warning('Could not fetch monitors from ZoneMinder') _LOGGER.warning("Could not fetch monitors from ZoneMinder")
return return
for i in monitors['monitors']: for i in monitors['monitors']:
monitor = i['Monitor'] monitor = i['Monitor']
if monitor['Function'] == 'None': if monitor['Function'] == 'None':
_LOGGER.info('Skipping camera %s', monitor['Id']) _LOGGER.info("Skipping camera %s", monitor['Id'])
continue continue
_LOGGER.info('Initializing camera %s', monitor['Id']) _LOGGER.info("Initializing camera %s", monitor['Id'])
device_info = { device_info = {
CONF_NAME: monitor['Name'], CONF_NAME: monitor['Name'],
@ -75,7 +75,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
cameras.append(ZoneMinderCamera(hass, device_info, monitor)) cameras.append(ZoneMinderCamera(hass, device_info, monitor))
if not cameras: if not cameras:
_LOGGER.warning('No active cameras found') _LOGGER.warning("No active cameras found")
return return
async_add_devices(cameras) async_add_devices(cameras)
@ -97,18 +97,18 @@ class ZoneMinderCamera(MjpegCamera):
def update(self): def update(self):
"""Update our recording state from the ZM API.""" """Update our recording state from the ZM API."""
_LOGGER.debug('Updating camera state for monitor %i', self._monitor_id) _LOGGER.debug("Updating camera state for monitor %i", self._monitor_id)
status_response = zoneminder.get_state( status_response = zoneminder.get_state(
'api/monitors/alarm/id:%i/command:status.json' % self._monitor_id 'api/monitors/alarm/id:%i/command:status.json' % self._monitor_id
) )
if not status_response: if not status_response:
_LOGGER.warning('Could not get status for monitor %i', _LOGGER.warning("Could not get status for monitor %i",
self._monitor_id) self._monitor_id)
return return
if status_response['success'] is False: if not status_response.get("success", False):
_LOGGER.warning('Alarm status API call failed for monitor %i', _LOGGER.warning("Alarm status API call failed for monitor %i",
self._monitor_id) self._monitor_id)
return return

View file

@ -23,45 +23,46 @@ from homeassistant.const import (
ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, STATE_UNKNOWN, ATTR_ENTITY_ID, ATTR_TEMPERATURE, STATE_ON, STATE_OFF, STATE_UNKNOWN,
TEMP_CELSIUS) TEMP_CELSIUS)
DOMAIN = "climate" DOMAIN = 'climate'
ENTITY_ID_FORMAT = DOMAIN + ".{}" ENTITY_ID_FORMAT = DOMAIN + '.{}'
SCAN_INTERVAL = timedelta(seconds=60) SCAN_INTERVAL = timedelta(seconds=60)
SERVICE_SET_AWAY_MODE = "set_away_mode" SERVICE_SET_AWAY_MODE = 'set_away_mode'
SERVICE_SET_AUX_HEAT = "set_aux_heat" SERVICE_SET_AUX_HEAT = 'set_aux_heat'
SERVICE_SET_TEMPERATURE = "set_temperature" SERVICE_SET_TEMPERATURE = 'set_temperature'
SERVICE_SET_FAN_MODE = "set_fan_mode" SERVICE_SET_FAN_MODE = 'set_fan_mode'
SERVICE_SET_HOLD_MODE = "set_hold_mode" SERVICE_SET_HOLD_MODE = 'set_hold_mode'
SERVICE_SET_OPERATION_MODE = "set_operation_mode" SERVICE_SET_OPERATION_MODE = 'set_operation_mode'
SERVICE_SET_SWING_MODE = "set_swing_mode" SERVICE_SET_SWING_MODE = 'set_swing_mode'
SERVICE_SET_HUMIDITY = "set_humidity" SERVICE_SET_HUMIDITY = 'set_humidity'
STATE_HEAT = "heat" STATE_HEAT = 'heat'
STATE_COOL = "cool" STATE_COOL = 'cool'
STATE_IDLE = "idle" STATE_IDLE = 'idle'
STATE_AUTO = "auto" STATE_AUTO = 'auto'
STATE_DRY = "dry" STATE_DRY = 'dry'
STATE_FAN_ONLY = "fan_only" STATE_FAN_ONLY = 'fan_only'
ATTR_CURRENT_TEMPERATURE = "current_temperature" ATTR_CURRENT_TEMPERATURE = 'current_temperature'
ATTR_MAX_TEMP = "max_temp" ATTR_MAX_TEMP = 'max_temp'
ATTR_MIN_TEMP = "min_temp" ATTR_MIN_TEMP = 'min_temp'
ATTR_TARGET_TEMP_HIGH = "target_temp_high" ATTR_TARGET_TEMP_HIGH = 'target_temp_high'
ATTR_TARGET_TEMP_LOW = "target_temp_low" ATTR_TARGET_TEMP_LOW = 'target_temp_low'
ATTR_AWAY_MODE = "away_mode" ATTR_TARGET_TEMP_STEP = 'target_temp_step'
ATTR_AUX_HEAT = "aux_heat" ATTR_AWAY_MODE = 'away_mode'
ATTR_FAN_MODE = "fan_mode" ATTR_AUX_HEAT = 'aux_heat'
ATTR_FAN_LIST = "fan_list" ATTR_FAN_MODE = 'fan_mode'
ATTR_CURRENT_HUMIDITY = "current_humidity" ATTR_FAN_LIST = 'fan_list'
ATTR_HUMIDITY = "humidity" ATTR_CURRENT_HUMIDITY = 'current_humidity'
ATTR_MAX_HUMIDITY = "max_humidity" ATTR_HUMIDITY = 'humidity'
ATTR_MIN_HUMIDITY = "min_humidity" ATTR_MAX_HUMIDITY = 'max_humidity'
ATTR_HOLD_MODE = "hold_mode" ATTR_MIN_HUMIDITY = 'min_humidity'
ATTR_OPERATION_MODE = "operation_mode" ATTR_HOLD_MODE = 'hold_mode'
ATTR_OPERATION_LIST = "operation_list" ATTR_OPERATION_MODE = 'operation_mode'
ATTR_SWING_MODE = "swing_mode" ATTR_OPERATION_LIST = 'operation_list'
ATTR_SWING_LIST = "swing_list" ATTR_SWING_MODE = 'swing_mode'
ATTR_SWING_LIST = 'swing_list'
# The degree of precision for each platform # The degree of precision for each platform
PRECISION_WHOLE = 1 PRECISION_WHOLE = 1
@ -208,7 +209,7 @@ def set_swing_mode(hass, swing_mode, entity_id=None):
@asyncio.coroutine @asyncio.coroutine
def async_setup(hass, config): def async_setup(hass, config):
"""Setup climate devices.""" """Set up climate devices."""
component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL) component = EntityComponent(_LOGGER, DOMAIN, hass, SCAN_INTERVAL)
yield from component.async_setup(config) yield from component.async_setup(config)
@ -273,7 +274,7 @@ def async_setup(hass, config):
@asyncio.coroutine @asyncio.coroutine
def async_aux_heat_set_service(service): def async_aux_heat_set_service(service):
"""Set auxillary heater on target climate devices.""" """Set auxiliary heater on target climate devices."""
target_climate = component.async_extract_from_service(service) target_climate = component.async_extract_from_service(service)
aux_heat = service.data.get(ATTR_AUX_HEAT) aux_heat = service.data.get(ATTR_AUX_HEAT)
@ -419,6 +420,10 @@ class ClimateDevice(Entity):
ATTR_TEMPERATURE: ATTR_TEMPERATURE:
self._convert_for_display(self.target_temperature), self._convert_for_display(self.target_temperature),
} }
if self.target_temperature_step is not None:
data[ATTR_TARGET_TEMP_STEP] = self.target_temperature_step
target_temp_high = self.target_temperature_high target_temp_high = self.target_temperature_high
if target_temp_high is not None: if target_temp_high is not None:
data[ATTR_TARGET_TEMP_HIGH] = self._convert_for_display( data[ATTR_TARGET_TEMP_HIGH] = self._convert_for_display(
@ -467,12 +472,12 @@ class ClimateDevice(Entity):
@property @property
def unit_of_measurement(self): def unit_of_measurement(self):
"""The unit of measurement to display.""" """Return the unit of measurement to display."""
return self.hass.config.units.temperature_unit return self.hass.config.units.temperature_unit
@property @property
def temperature_unit(self): def temperature_unit(self):
"""The unit of measurement used by the platform.""" """Return the unit of measurement used by the platform."""
raise NotImplementedError raise NotImplementedError
@property @property
@ -492,7 +497,7 @@ class ClimateDevice(Entity):
@property @property
def operation_list(self): def operation_list(self):
"""List of available operation modes.""" """Return the list of available operation modes."""
return None return None
@property @property
@ -505,6 +510,11 @@ class ClimateDevice(Entity):
"""Return the temperature we try to reach.""" """Return the temperature we try to reach."""
return None return None
@property
def target_temperature_step(self):
"""Return the supported step of target temperature."""
return None
@property @property
def target_temperature_high(self): def target_temperature_high(self):
"""Return the highbound target temperature we try to reach.""" """Return the highbound target temperature we try to reach."""
@ -537,7 +547,7 @@ class ClimateDevice(Entity):
@property @property
def fan_list(self): def fan_list(self):
"""List of available fan modes.""" """Return the list of available fan modes."""
return None return None
@property @property
@ -547,7 +557,7 @@ class ClimateDevice(Entity):
@property @property
def swing_list(self): def swing_list(self):
"""List of available swing modes.""" """Return the list of available swing modes."""
return None return None
def set_temperature(self, **kwargs): def set_temperature(self, **kwargs):
@ -695,8 +705,8 @@ class ClimateDevice(Entity):
if temp is None or not isinstance(temp, Number): if temp is None or not isinstance(temp, Number):
return temp return temp
if self.temperature_unit != self.unit_of_measurement: if self.temperature_unit != self.unit_of_measurement:
temp = convert_temperature(temp, self.temperature_unit, temp = convert_temperature(
self.unit_of_measurement) temp, self.temperature_unit, self.unit_of_measurement)
# Round in the units appropriate # Round in the units appropriate
if self.precision == PRECISION_HALVES: if self.precision == PRECISION_HALVES:
return round(temp * 2) / 2.0 return round(temp * 2) / 2.0

View file

@ -10,14 +10,14 @@ from homeassistant.const import TEMP_CELSIUS, TEMP_FAHRENHEIT, ATTR_TEMPERATURE
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Demo climate devices.""" """Set up the Demo climate devices."""
add_devices([ add_devices([
DemoClimate("HeatPump", 68, TEMP_FAHRENHEIT, None, None, 77, DemoClimate('HeatPump', 68, TEMP_FAHRENHEIT, None, None, 77,
"Auto Low", None, None, "Auto", "heat", None, None, None), 'Auto Low', None, None, 'Auto', 'heat', None, None, None),
DemoClimate("Hvac", 21, TEMP_CELSIUS, True, None, 22, "On High", DemoClimate('Hvac', 21, TEMP_CELSIUS, True, None, 22, 'On High',
67, 54, "Off", "cool", False, None, None), 67, 54, 'Off', 'cool', False, None, None),
DemoClimate("Ecobee", None, TEMP_CELSIUS, None, None, 23, "Auto Low", DemoClimate('Ecobee', None, TEMP_CELSIUS, None, None, 23, 'Auto Low',
None, None, "Auto", "auto", None, 24, 21) None, None, 'Auto', 'auto', None, 24, 21)
]) ])
@ -41,15 +41,15 @@ class DemoClimate(ClimateDevice):
self._current_operation = current_operation self._current_operation = current_operation
self._aux = aux self._aux = aux
self._current_swing_mode = current_swing_mode self._current_swing_mode = current_swing_mode
self._fan_list = ["On Low", "On High", "Auto Low", "Auto High", "Off"] self._fan_list = ['On Low', 'On High', 'Auto Low', 'Auto High', 'Off']
self._operation_list = ["heat", "cool", "auto", "off"] self._operation_list = ['heat', 'cool', 'auto', 'off']
self._swing_list = ["Auto", "1", "2", "3", "Off"] self._swing_list = ['Auto', '1', '2', '3', 'Off']
self._target_temperature_high = target_temp_high self._target_temperature_high = target_temp_high
self._target_temperature_low = target_temp_low self._target_temperature_low = target_temp_low
@property @property
def should_poll(self): def should_poll(self):
"""Polling not needed for a demo climate device.""" """Return the polling state."""
return False return False
@property @property
@ -99,7 +99,7 @@ class DemoClimate(ClimateDevice):
@property @property
def operation_list(self): def operation_list(self):
"""List of available operation modes.""" """Return the list of available operation modes."""
return self._operation_list return self._operation_list
@property @property
@ -124,7 +124,7 @@ class DemoClimate(ClimateDevice):
@property @property
def fan_list(self): def fan_list(self):
"""List of available fan modes.""" """Return the list of available fan modes."""
return self._fan_list return self._fan_list
def set_temperature(self, **kwargs): def set_temperature(self, **kwargs):

View file

@ -45,7 +45,7 @@ RESUME_PROGRAM_SCHEMA = vol.Schema({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Ecobee Thermostat Platform.""" """Set up the Ecobee Thermostat Platform."""
if discovery_info is None: if discovery_info is None:
return return
data = ecobee.NETWORK data = ecobee.NETWORK
@ -197,19 +197,19 @@ class Thermostat(ClimateDevice):
if event['holdClimateRef'] == 'away': if event['holdClimateRef'] == 'away':
if int(event['endDate'][0:4]) - \ if int(event['endDate'][0:4]) - \
int(event['startDate'][0:4]) <= 1: int(event['startDate'][0:4]) <= 1:
# a temporary hold from away climate is a hold # A temporary hold from away climate is a hold
return 'away' return 'away'
else: else:
# a premanent hold from away climate is away_mode # A permanent hold from away climate is away_mode
return None return None
elif event['holdClimateRef'] != "": elif event['holdClimateRef'] != "":
# any other hold based on climate # Any other hold based on climate
return event['holdClimateRef'] return event['holdClimateRef']
else: else:
# any hold not based on a climate is a temp hold # Any hold not based on a climate is a temp hold
return TEMPERATURE_HOLD return TEMPERATURE_HOLD
elif event['type'].startswith('auto'): elif event['type'].startswith('auto'):
# all auto modes are treated as holds # All auto modes are treated as holds
return event['type'][4:].lower() return event['type'][4:].lower()
elif event['type'] == 'vacation': elif event['type'] == 'vacation':
self.vacation = event['name'] self.vacation = event['name']
@ -278,6 +278,11 @@ class Thermostat(ClimateDevice):
"""Return true if away mode is on.""" """Return true if away mode is on."""
return self.current_hold_mode == 'away' return self.current_hold_mode == 'away'
@property
def is_aux_heat_on(self):
"""Return true if aux heater."""
return 'auxHeat' in self.thermostat['equipmentStatus']
def turn_away_mode_on(self): def turn_away_mode_on(self):
"""Turn away on.""" """Turn away on."""
self.set_hold_mode('away') self.set_hold_mode('away')
@ -295,17 +300,16 @@ class Thermostat(ClimateDevice):
return return
elif hold_mode == 'None' or hold_mode is None: elif hold_mode == 'None' or hold_mode is None:
if hold == VACATION_HOLD: if hold == VACATION_HOLD:
self.data.ecobee.delete_vacation(self.thermostat_index, self.data.ecobee.delete_vacation(
self.vacation) self.thermostat_index, self.vacation)
else: else:
self.data.ecobee.resume_program(self.thermostat_index) self.data.ecobee.resume_program(self.thermostat_index)
else: else:
if hold_mode == TEMPERATURE_HOLD: if hold_mode == TEMPERATURE_HOLD:
self.set_temp_hold(int(self.current_temperature)) self.set_temp_hold(int(self.current_temperature))
else: else:
self.data.ecobee.set_climate_hold(self.thermostat_index, self.data.ecobee.set_climate_hold(
hold_mode, self.thermostat_index, hold_mode, self.hold_preference())
self.hold_preference())
self.update_without_throttle = True self.update_without_throttle = True
def set_auto_temp_hold(self, heat_temp, cool_temp): def set_auto_temp_hold(self, heat_temp, cool_temp):
@ -351,7 +355,7 @@ class Thermostat(ClimateDevice):
self.set_temp_hold(int(temp)) self.set_temp_hold(int(temp))
else: else:
_LOGGER.error( _LOGGER.error(
'Missing valid arguments for set_temperature in %s', kwargs) "Missing valid arguments for set_temperature in %s", kwargs)
def set_operation_mode(self, operation_mode): def set_operation_mode(self, operation_mode):
"""Set HVAC mode (auto, auxHeatOnly, cool, heat, off).""" """Set HVAC mode (auto, auxHeatOnly, cool, heat, off)."""
@ -360,14 +364,14 @@ class Thermostat(ClimateDevice):
def set_fan_min_on_time(self, fan_min_on_time): def set_fan_min_on_time(self, fan_min_on_time):
"""Set the minimum fan on time.""" """Set the minimum fan on time."""
self.data.ecobee.set_fan_min_on_time(self.thermostat_index, self.data.ecobee.set_fan_min_on_time(
fan_min_on_time) self.thermostat_index, fan_min_on_time)
self.update_without_throttle = True self.update_without_throttle = True
def resume_program(self, resume_all): def resume_program(self, resume_all):
"""Resume the thermostat schedule program.""" """Resume the thermostat schedule program."""
self.data.ecobee.resume_program(self.thermostat_index, self.data.ecobee.resume_program(
str(resume_all).lower()) self.thermostat_index, str(resume_all).lower())
self.update_without_throttle = True self.update_without_throttle = True
def hold_preference(self): def hold_preference(self):

View file

@ -21,15 +21,15 @@ REQUIREMENTS = ['python-eq3bt==0.1.5']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
STATE_BOOST = "boost" STATE_BOOST = 'boost'
STATE_AWAY = "away" STATE_AWAY = 'away'
STATE_MANUAL = "manual" STATE_MANUAL = 'manual'
ATTR_STATE_WINDOW_OPEN = "window_open" ATTR_STATE_WINDOW_OPEN = 'window_open'
ATTR_STATE_VALVE = "valve" ATTR_STATE_VALVE = 'valve'
ATTR_STATE_LOCKED = "is_locked" ATTR_STATE_LOCKED = 'is_locked'
ATTR_STATE_LOW_BAT = "low_battery" ATTR_STATE_LOW_BAT = 'low_battery'
ATTR_STATE_AWAY_END = "away_end" ATTR_STATE_AWAY_END = 'away_end'
DEVICE_SCHEMA = vol.Schema({ DEVICE_SCHEMA = vol.Schema({
vol.Required(CONF_MAC): cv.string, vol.Required(CONF_MAC): cv.string,
@ -42,7 +42,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the eQ-3 BLE thermostats.""" """Set up the eQ-3 BLE thermostats."""
devices = [] devices = []
for name, device_cfg in config[CONF_DEVICES].items(): for name, device_cfg in config[CONF_DEVICES].items():
@ -112,14 +112,14 @@ class EQ3BTSmartThermostat(ClimateDevice):
@property @property
def current_operation(self): def current_operation(self):
"""Current mode.""" """Return the current operation mode."""
if self._thermostat.mode < 0: if self._thermostat.mode < 0:
return None return None
return self.modes[self._thermostat.mode] return self.modes[self._thermostat.mode]
@property @property
def operation_list(self): def operation_list(self):
"""List of available operation modes.""" """Return the list of available operation modes."""
return [x for x in self.modes.values()] return [x for x in self.modes.values()]
def set_operation_mode(self, operation_mode): def set_operation_mode(self, operation_mode):

View file

@ -14,7 +14,8 @@ from homeassistant.components import switch
from homeassistant.components.climate import ( from homeassistant.components.climate import (
STATE_HEAT, STATE_COOL, STATE_IDLE, ClimateDevice, PLATFORM_SCHEMA) STATE_HEAT, STATE_COOL, STATE_IDLE, ClimateDevice, PLATFORM_SCHEMA)
from homeassistant.const import ( from homeassistant.const import (
ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF, ATTR_TEMPERATURE) ATTR_UNIT_OF_MEASUREMENT, STATE_ON, STATE_OFF, ATTR_TEMPERATURE,
CONF_NAME)
from homeassistant.helpers import condition from homeassistant.helpers import condition
from homeassistant.helpers.event import ( from homeassistant.helpers.event import (
async_track_state_change, async_track_time_interval) async_track_state_change, async_track_time_interval)
@ -27,7 +28,6 @@ DEPENDENCIES = ['switch', 'sensor']
DEFAULT_TOLERANCE = 0.3 DEFAULT_TOLERANCE = 0.3
DEFAULT_NAME = 'Generic Thermostat' DEFAULT_NAME = 'Generic Thermostat'
CONF_NAME = 'name'
CONF_HEATER = 'heater' CONF_HEATER = 'heater'
CONF_SENSOR = 'target_sensor' CONF_SENSOR = 'target_sensor'
CONF_MIN_TEMP = 'min_temp' CONF_MIN_TEMP = 'min_temp'
@ -56,7 +56,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
@asyncio.coroutine @asyncio.coroutine
def async_setup_platform(hass, config, async_add_devices, discovery_info=None): def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
"""Setup the generic thermostat.""" """Set up the generic thermostat platform."""
name = config.get(CONF_NAME) name = config.get(CONF_NAME)
heater_entity_id = config.get(CONF_HEATER) heater_entity_id = config.get(CONF_HEATER)
sensor_entity_id = config.get(CONF_SENSOR) sensor_entity_id = config.get(CONF_SENSOR)
@ -74,7 +74,7 @@ def async_setup_platform(hass, config, async_add_devices, discovery_info=None):
class GenericThermostat(ClimateDevice): class GenericThermostat(ClimateDevice):
"""Representation of a GenericThermostat device.""" """Representation of a Generic Thermostat device."""
def __init__(self, hass, name, heater_entity_id, sensor_entity_id, def __init__(self, hass, name, heater_entity_id, sensor_entity_id,
min_temp, max_temp, target_temp, ac_mode, min_cycle_duration, min_temp, max_temp, target_temp, ac_mode, min_cycle_duration,
@ -110,7 +110,7 @@ class GenericThermostat(ClimateDevice):
@property @property
def should_poll(self): def should_poll(self):
"""No polling needed.""" """Return the polling state."""
return False return False
@property @property
@ -175,7 +175,7 @@ class GenericThermostat(ClimateDevice):
@asyncio.coroutine @asyncio.coroutine
def _async_sensor_changed(self, entity_id, old_state, new_state): def _async_sensor_changed(self, entity_id, old_state, new_state):
"""Called when temperature changes.""" """Handle temperature changes."""
if new_state is None: if new_state is None:
return return
@ -185,14 +185,14 @@ class GenericThermostat(ClimateDevice):
@callback @callback
def _async_switch_changed(self, entity_id, old_state, new_state): def _async_switch_changed(self, entity_id, old_state, new_state):
"""Called when heater switch changes state.""" """Handle heater switch state changes."""
if new_state is None: if new_state is None:
return return
self.hass.async_add_job(self.async_update_ha_state()) self.hass.async_add_job(self.async_update_ha_state())
@callback @callback
def _async_keep_alive(self, time): def _async_keep_alive(self, time):
"""Called at constant intervals for keep-alive purposes.""" """Call at constant intervals for keep-alive purposes."""
if self.current_operation in [STATE_COOL, STATE_HEAT]: if self.current_operation in [STATE_COOL, STATE_HEAT]:
switch.async_turn_on(self.hass, self.heater_entity_id) switch.async_turn_on(self.hass, self.heater_entity_id)
else: else:

View file

@ -35,7 +35,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
# pylint: disable=unused-variable # pylint: disable=unused-variable
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the heatmiser thermostat.""" """Set up the heatmiser thermostat."""
from heatmiserV3 import heatmiser, connection from heatmiserV3 import heatmiser, connection
ipaddress = config.get(CONF_IPADDRESS) ipaddress = config.get(CONF_IPADDRESS)

View file

@ -14,17 +14,17 @@ DEPENDENCIES = ['homematic']
_LOGGER = logging.getLogger(__name__) _LOGGER = logging.getLogger(__name__)
STATE_MANUAL = "manual" STATE_MANUAL = 'manual'
STATE_BOOST = "boost" STATE_BOOST = 'boost'
STATE_COMFORT = "comfort" STATE_COMFORT = 'comfort'
STATE_LOWERING = "lowering" STATE_LOWERING = 'lowering'
HM_STATE_MAP = { HM_STATE_MAP = {
"AUTO_MODE": STATE_AUTO, 'AUTO_MODE': STATE_AUTO,
"MANU_MODE": STATE_MANUAL, 'MANU_MODE': STATE_MANUAL,
"BOOST_MODE": STATE_BOOST, 'BOOST_MODE': STATE_BOOST,
"COMFORT_MODE": STATE_COMFORT, 'COMFORT_MODE': STATE_COMFORT,
"LOWERING_MODE": STATE_LOWERING 'LOWERING_MODE': STATE_LOWERING
} }
HM_TEMP_MAP = [ HM_TEMP_MAP = [
@ -41,7 +41,7 @@ HM_CONTROL_MODE = 'CONTROL_MODE'
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Homematic thermostat platform.""" """Set up the Homematic thermostat platform."""
if discovery_info is None: if discovery_info is None:
return return
@ -76,10 +76,9 @@ class HMThermostat(HMDevice, ClimateDevice):
@property @property
def operation_list(self): def operation_list(self):
"""List of available operation modes.""" """Return the list of available operation modes."""
op_list = [] op_list = []
# generate list
for mode in self._hmdevice.ACTIONNODE: for mode in self._hmdevice.ACTIONNODE:
if mode in HM_STATE_MAP: if mode in HM_STATE_MAP:
op_list.append(HM_STATE_MAP.get(mode)) op_list.append(HM_STATE_MAP.get(mode))
@ -132,11 +131,9 @@ class HMThermostat(HMDevice, ClimateDevice):
def _init_data_struct(self): def _init_data_struct(self):
"""Generate a data dict (self._data) from the Homematic metadata.""" """Generate a data dict (self._data) from the Homematic metadata."""
# Add state to data dict
self._state = next(iter(self._hmdevice.WRITENODE.keys())) self._state = next(iter(self._hmdevice.WRITENODE.keys()))
self._data[self._state] = STATE_UNKNOWN self._data[self._state] = STATE_UNKNOWN
# support state
if HM_CONTROL_MODE in self._hmdevice.ATTRIBUTENODE: if HM_CONTROL_MODE in self._hmdevice.ATTRIBUTENODE:
self._data[HM_CONTROL_MODE] = STATE_UNKNOWN self._data[HM_CONTROL_MODE] = STATE_UNKNOWN

View file

@ -8,13 +8,12 @@ import logging
import socket import socket
import datetime import datetime
import voluptuous as vol
import requests import requests
import voluptuous as vol
from homeassistant.components.climate import (ClimateDevice, PLATFORM_SCHEMA, from homeassistant.components.climate import (
ATTR_FAN_MODE, ATTR_FAN_LIST, ClimateDevice, PLATFORM_SCHEMA, ATTR_FAN_MODE, ATTR_FAN_LIST,
ATTR_OPERATION_MODE, ATTR_OPERATION_MODE, ATTR_OPERATION_LIST)
ATTR_OPERATION_LIST)
from homeassistant.const import ( from homeassistant.const import (
CONF_PASSWORD, CONF_USERNAME, TEMP_CELSIUS, TEMP_FAHRENHEIT, CONF_PASSWORD, CONF_USERNAME, TEMP_CELSIUS, TEMP_FAHRENHEIT,
ATTR_TEMPERATURE) ATTR_TEMPERATURE)
@ -54,7 +53,7 @@ PLATFORM_SCHEMA = PLATFORM_SCHEMA.extend({
def setup_platform(hass, config, add_devices, discovery_info=None): def setup_platform(hass, config, add_devices, discovery_info=None):
"""Setup the Honeywell thermostat.""" """Set up the Honeywell thermostat."""
username = config.get(CONF_USERNAME) username = config.get(CONF_USERNAME)
password = config.get(CONF_PASSWORD) password = config.get(CONF_PASSWORD)
region = config.get(CONF_REGION) region = config.get(CONF_REGION)
@ -66,7 +65,7 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
def _setup_round(username, password, config, add_devices): def _setup_round(username, password, config, add_devices):
"""Setup rounding function.""" """Set up the rounding function."""
from evohomeclient import EvohomeClient from evohomeclient import EvohomeClient
away_temp = config.get(CONF_AWAY_TEMPERATURE) away_temp = config.get(CONF_AWAY_TEMPERATURE)
@ -87,16 +86,16 @@ def _setup_round(username, password, config, add_devices):
# config will be used later # config will be used later
def _setup_us(username, password, config, add_devices): def _setup_us(username, password, config, add_devices):
"""Setup user.""" """Set up the user."""
import somecomfort import somecomfort
try: try:
client = somecomfort.SomeComfort(username, password) client = somecomfort.SomeComfort(username, password)
except somecomfort.AuthError: except somecomfort.AuthError:
_LOGGER.error('Failed to login to honeywell account %s', username) _LOGGER.error("Failed to login to honeywell account %s", username)
return False return False
except somecomfort.SomeComfortError as ex: except somecomfort.SomeComfortError as ex:
_LOGGER.error('Failed to initialize honeywell client: %s', str(ex)) _LOGGER.error("Failed to initialize honeywell client: %s", str(ex))
return False return False
dev_id = config.get('thermostat') dev_id = config.get('thermostat')
@ -199,7 +198,7 @@ class RoundThermostat(ClimateDevice):
except StopIteration: except StopIteration:
_LOGGER.error("Did not receive any temperature data from the " _LOGGER.error("Did not receive any temperature data from the "
"evohomeclient API.") "evohomeclient API")
return return
self._current_temperature = data['temp'] self._current_temperature = data['temp']
@ -289,7 +288,7 @@ class HoneywellUSThermostat(ClimateDevice):
"setpoint_{}".format(mode), "setpoint_{}".format(mode),
temperature) temperature)
except somecomfort.SomeComfortError: except somecomfort.SomeComfortError:
_LOGGER.error('Temperature %.1f out of range', temperature) _LOGGER.error("Temperature %.1f out of range", temperature)
@property @property
def device_state_attributes(self): def device_state_attributes(self):
@ -369,8 +368,8 @@ class HoneywellUSThermostat(ClimateDevice):
raise exp raise exp
if not self._retry(): if not self._retry():
raise exp raise exp
_LOGGER.error("SomeComfort update failed, Retrying " _LOGGER.error(
"- Error: %s", exp) "SomeComfort update failed, Retrying - Error: %s", exp)
def _retry(self): def _retry(self):
"""Recreate a new somecomfort client. """Recreate a new somecomfort client.
@ -380,14 +379,14 @@ class HoneywellUSThermostat(ClimateDevice):
""" """
import somecomfort import somecomfort
try: try:
self._client = somecomfort.SomeComfort(self._username, self._client = somecomfort.SomeComfort(
self._password) self._username, self._password)
except somecomfort.AuthError: except somecomfort.AuthError:
_LOGGER.error('Failed to login to honeywell account %s', _LOGGER.error("Failed to login to honeywell account %s",
self._username) self._username)
return False return False
except somecomfort.SomeComfortError as ex: except somecomfort.SomeComfortError as ex:
_LOGGER.error('Failed to initialize honeywell client: %s', _LOGGER.error("Failed to initialize honeywell client: %s",
str(ex)) str(ex))
return False return False
@ -397,7 +396,7 @@ class HoneywellUSThermostat(ClimateDevice):
if device.name == self._device.name] if device.name == self._device.name]
if len(devices) != 1: if len(devices) != 1:
_LOGGER.error('Failed to find device %s', self._device.name) _LOGGER.error("Failed to find device %s", self._device.name)
return False return False
self._device = devices[0] self._device = devices[0]

View file

@ -61,7 +61,7 @@ class KNXThermostat(KNXMultiAddressDevice, ClimateDevice):
@property @property
def should_poll(self): def should_poll(self):
"""Polling is needed for the KNX thermostat.""" """Return the polling state, is needed for the KNX thermostat."""
return True return True
@property @property

Some files were not shown because too many files have changed in this diff Show more