Merge remote-tracking branch 'balloob/dev' into update_notify

Conflicts:
	homeassistant/components/frontend/version.py
	homeassistant/components/frontend/www_static/frontend.html
This commit is contained in:
Ryan Kraus 2015-11-15 17:00:35 -05:00
commit 9b5385c565
12 changed files with 232 additions and 32 deletions

View File

@ -84,6 +84,7 @@ omit =
homeassistant/components/sensor/glances.py
homeassistant/components/sensor/mysensors.py
homeassistant/components/sensor/openweathermap.py
homeassistant/components/switch/orvibo.py
homeassistant/components/sensor/rest.py
homeassistant/components/sensor/rpi_gpio.py
homeassistant/components/sensor/sabnzbd.py

View File

@ -87,7 +87,10 @@ def setup(hass, config):
if camera:
response = camera.camera_image()
handler.wfile.write(response)
if response is not None:
handler.wfile.write(response)
else:
handler.send_response(HTTP_NOT_FOUND)
else:
handler.send_response(HTTP_NOT_FOUND)
@ -129,7 +132,8 @@ def setup(hass, config):
while True:
img_bytes = camera.camera_image()
if img_bytes is None:
continue
headers_str = '\r\n'.join((
'Content-length: {}'.format(len(img_bytes)),
'Content-type: image/jpeg',

View File

@ -42,11 +42,19 @@ class GenericCamera(Camera):
def camera_image(self):
""" Return a still image reponse from the camera. """
if self._username and self._password:
response = requests.get(
self._still_image_url,
auth=HTTPBasicAuth(self._username, self._password))
try:
response = requests.get(
self._still_image_url,
auth=HTTPBasicAuth(self._username, self._password))
except requests.exceptions.RequestException as error:
_LOGGER.error('Error getting camera image: %s', error)
return None
else:
response = requests.get(self._still_image_url)
try:
response = requests.get(self._still_image_url)
except requests.exceptions.RequestException as error:
_LOGGER.error('Error getting camera image: %s', error)
return None
return response.content

File diff suppressed because one or more lines are too long

View File

@ -37,6 +37,7 @@ CONF_EVENT_DATA = "event_data"
CONF_DELAY = "delay"
ATTR_LAST_ACTION = 'last_action'
ATTR_CAN_CANCEL = 'can_cancel'
_LOGGER = logging.getLogger(__name__)
@ -113,6 +114,8 @@ class Script(ToggleEntity):
self._cur = -1
self._last_action = None
self._listener = None
self._can_cancel = not any(CONF_DELAY in action for action
in self.sequence)
@property
def should_poll(self):
@ -126,7 +129,9 @@ class Script(ToggleEntity):
@property
def state_attributes(self):
""" Returns the state attributes. """
attrs = {}
attrs = {
ATTR_CAN_CANCEL: self._can_cancel
}
if self._last_action:
attrs[ATTR_LAST_ACTION] = self._last_action

View File

@ -70,6 +70,10 @@ def setup_platform(hass, config, add_devices, discovery_info=None):
elif value.command_class == zwave.COMMAND_CLASS_SENSOR_MULTILEVEL:
add_devices([ZWaveMultilevelSensor(value)])
elif (value.command_class == zwave.COMMAND_CLASS_METER and
value.type == zwave.TYPE_DECIMAL):
add_devices([ZWaveMultilevelSensor(value)])
class ZWaveSensor(Entity):
""" Represents a Z-Wave sensor. """

View File

@ -16,7 +16,8 @@ from homeassistant.helpers.entity import ToggleEntity
from homeassistant.const import (
STATE_ON, SERVICE_TURN_ON, SERVICE_TURN_OFF, ATTR_ENTITY_ID)
from homeassistant.components import group, discovery, wink, isy994, verisure
from homeassistant.components import (
group, discovery, wink, isy994, verisure, zwave)
DOMAIN = 'switch'
DEPENDENCIES = []
@ -38,7 +39,8 @@ DISCOVERY_PLATFORMS = {
discovery.SERVICE_WEMO: 'wemo',
wink.DISCOVER_SWITCHES: 'wink',
isy994.DISCOVER_SWITCHES: 'isy994',
verisure.DISCOVER_SWITCHES: 'verisure'
verisure.DISCOVER_SWITCHES: 'verisure',
zwave.DISCOVER_SWITCHES: 'zwave',
}
PROP_TO_ATTR = {

View File

@ -0,0 +1,75 @@
"""
homeassistant.components.switch.orvibo
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Support for Orvibo S20 Wifi Smart Switches.
For more details about this platform, please refer to the documentation at
https://home-assistant.io/components/switch.orvibo/
"""
import logging
from homeassistant.components.switch import SwitchDevice
from orvibo.s20 import S20, S20Exception
DEFAULT_NAME = "Orvibo S20 Switch"
REQUIREMENTS = ['orvibo==1.0.0']
_LOGGER = logging.getLogger(__name__)
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices_callback, discovery_info=None):
""" Find and return S20 switches. """
if config.get('host') is None:
_LOGGER.error("Missing required variable: host")
return
try:
s20 = S20(config.get('host'))
add_devices_callback([S20Switch(config.get('name', DEFAULT_NAME),
s20)])
except S20Exception:
_LOGGER.exception("S20 couldn't be initialized")
class S20Switch(SwitchDevice):
""" Represents an S20 switch. """
def __init__(self, name, s20):
self._name = name
self._s20 = s20
self._state = False
@property
def should_poll(self):
""" Poll. """
return True
@property
def name(self):
""" The name of the switch. """
return self._name
@property
def is_on(self):
""" True if device is on. """
return self._state
def update(self):
""" Update device state. """
try:
self._state = self._s20.on
except S20Exception:
_LOGGER.exception("Error while fetching S20 state")
def turn_on(self, **kwargs):
""" Turn the device on. """
try:
self._s20.on = True
except S20Exception:
_LOGGER.exception("Error while turning on S20")
def turn_off(self, **kwargs):
""" Turn the device off. """
try:
self._s20.on = False
except S20Exception:
_LOGGER.exception("Error while turning off S20")

View File

@ -0,0 +1,76 @@
"""
homeassistant.components.switch.zwave
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Zwave platform that handles simple binary switches.
"""
# pylint: disable=import-error
from openzwave.network import ZWaveNetwork
from pydispatch import dispatcher
import homeassistant.components.zwave as zwave
from homeassistant.components.switch import SwitchDevice
# pylint: disable=unused-argument
def setup_platform(hass, config, add_devices, discovery_info=None):
""" Find and return demo switches. """
if discovery_info is None:
return
node = zwave.NETWORK.nodes[discovery_info[zwave.ATTR_NODE_ID]]
value = node.values[discovery_info[zwave.ATTR_VALUE_ID]]
if value.command_class != zwave.COMMAND_CLASS_SWITCH_BINARY:
return
if value.type != zwave.TYPE_BOOL:
return
if value.genre != zwave.GENRE_USER:
return
value.set_change_verified(False)
add_devices([ZwaveSwitch(value)])
class ZwaveSwitch(SwitchDevice):
""" Provides a zwave switch. """
def __init__(self, value):
self._value = value
self._node = value.node
self._state = value.data
dispatcher.connect(
self._value_changed, ZWaveNetwork.SIGNAL_VALUE_CHANGED)
def _value_changed(self, value):
""" Called when a value has changed on the network. """
if self._value.value_id == value.value_id:
self._state = value.data
self.update_ha_state()
@property
def should_poll(self):
""" No polling needed for a demo switch. """
return False
@property
def name(self):
""" Returns the name of the device if any. """
name = self._node.name or "{}".format(self._node.product_name)
return "{}".format(name or self._value.label)
@property
def is_on(self):
""" True if device is on. """
return self._state
def turn_on(self, **kwargs):
""" Turn the device on. """
self._node.set_switch(self._value.value_id, True)
def turn_off(self, **kwargs):
""" Turn the device off. """
self._node.set_switch(self._value.value_id, False)

View File

@ -20,13 +20,18 @@ REQUIREMENTS = ['pydispatcher==2.0.5']
CONF_USB_STICK_PATH = "usb_path"
DEFAULT_CONF_USB_STICK_PATH = "/zwaveusbstick"
CONF_DEBUG = "debug"
CONF_POLLING_INTERVAL = "polling_interval"
DISCOVER_SENSORS = "zwave.sensors"
DISCOVER_SWITCHES = "zwave.switch"
DISCOVER_LIGHTS = "zwave.light"
COMMAND_CLASS_SWITCH_MULTILEVEL = 38
COMMAND_CLASS_SWITCH_BINARY = 37
COMMAND_CLASS_SENSOR_BINARY = 48
COMMAND_CLASS_SENSOR_MULTILEVEL = 49
COMMAND_CLASS_METER = 50
COMMAND_CLASS_BATTERY = 128
GENRE_WHATEVER = None
@ -35,20 +40,28 @@ GENRE_USER = "User"
TYPE_WHATEVER = None
TYPE_BYTE = "Byte"
TYPE_BOOL = "Bool"
TYPE_DECIMAL = "Decimal"
# list of tuple (DOMAIN, discovered service, supported command
# classes, value type)
DISCOVERY_COMPONENTS = [
('sensor',
DISCOVER_SENSORS,
[COMMAND_CLASS_SENSOR_BINARY, COMMAND_CLASS_SENSOR_MULTILEVEL],
[COMMAND_CLASS_SENSOR_BINARY,
COMMAND_CLASS_SENSOR_MULTILEVEL,
COMMAND_CLASS_METER],
TYPE_WHATEVER,
GENRE_WHATEVER),
GENRE_USER),
('light',
DISCOVER_LIGHTS,
[COMMAND_CLASS_SWITCH_MULTILEVEL],
TYPE_BYTE,
GENRE_USER),
('switch',
DISCOVER_SWITCHES,
[COMMAND_CLASS_SWITCH_BINARY],
TYPE_BOOL,
GENRE_USER),
]
ATTR_NODE_ID = "node_id"
@ -165,6 +178,10 @@ def setup(hass, config):
""" Called when Home Assistant starts up. """
NETWORK.start()
polling_interval = config[DOMAIN].get(CONF_POLLING_INTERVAL, None)
if polling_interval is not None:
NETWORK.setPollInterval(polling_interval)
hass.bus.listen_once(EVENT_HOMEASSISTANT_STOP, stop_zwave)
hass.bus.listen_once(EVENT_HOMEASSISTANT_START, start_zwave)

View File

@ -156,3 +156,6 @@ evohomeclient==0.2.3
# Pushetta (notify.pushetta)
pushetta==1.0.15
# Orvibo S10
orvibo==1.0.0

View File

@ -88,6 +88,8 @@ class TestScript(unittest.TestCase):
self.assertEqual(1, len(calls))
self.assertEqual('world', calls[0].data.get('hello'))
self.assertEqual(
True, self.hass.states.get(ENTITY_ID).attributes.get('can_cancel'))
def test_calling_service_old(self):
calls = []
@ -172,6 +174,9 @@ class TestScript(unittest.TestCase):
self.hass.pool.block_till_done()
self.assertTrue(script.is_on(self.hass, ENTITY_ID))
self.assertEqual(
False,
self.hass.states.get(ENTITY_ID).attributes.get('can_cancel'))
self.assertEqual(
event,