Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
573a446
change to webhook
dgomes Nov 3, 2018
090dc9c
dont persist webhook url in attributes
dgomes Nov 9, 2018
7c13081
remove orphan attribute
dgomes Nov 9, 2018
64ada1e
bump total connect client to 0.22 (#18344)
uchagani Nov 10, 2018
210eab1
WeMo - Change name of discovery option (#18348)
sqldiablo Nov 10, 2018
8bd281d
Update credstash.py (#18349)
iamtpage Nov 10, 2018
132bb79
Update HAP-python to 2.4.0 (#18355)
cdce8p Nov 10, 2018
e75f9b3
add heartbeat support to mysensors (#18359)
inetAnt Nov 10, 2018
f236e14
Upgrade pytest and pytest-sugar (#18338)
scop Nov 10, 2018
667b41d
Show battery_level as a percent vs a decimal (#18328)
chriskacerguis Nov 10, 2018
fa12718
Bump python-avion dependency
mjg59 Nov 10, 2018
d953312
Merge pull request #18364 from mjg59/avion
mjg59 Nov 11, 2018
a85a0b0
update tests
dgomes Nov 11, 2018
a805a6e
update tests
dgomes Nov 11, 2018
82f9e86
add warning
dgomes Nov 11, 2018
efd04fe
hound fixes
dgomes Nov 11, 2018
f0a0ce5
Better error handling in Tibber (#18363)
Danielhiversen Nov 11, 2018
9f966d1
block till done
dgomes Nov 11, 2018
e210ae7
trying to fix travis test
dgomes Nov 11, 2018
9c92151
Upgrade async_upnp_client to 0.13.2 (#18377)
StevenLooman Nov 11, 2018
47f3bad
trying to fix travis test
dgomes Nov 11, 2018
b8c06ad
Fix including from sub dir (#18378)
bramkragten Nov 11, 2018
9411fca
Add more type hints to helpers (#18350)
scop Nov 11, 2018
5b9a9d8
Return color information in Alexa Smart Home response (#18368)
jackwilsdon Nov 11, 2018
9cb6464
catch key error when saving image (#18365)
hunterjm Nov 11, 2018
02cc6a2
Fix hangouts notify (#18372)
MartinHjelmare Nov 11, 2018
372470f
Fix and improvment of Swiss Hydrological Data component (#17166)
Bouni Nov 11, 2018
81e0e34
change to webhook
dgomes Nov 3, 2018
01de2b8
dont persist webhook url in attributes
dgomes Nov 9, 2018
4e025a2
remove orphan attribute
dgomes Nov 9, 2018
2b81c64
update tests
dgomes Nov 11, 2018
ba66d56
update tests
dgomes Nov 11, 2018
a765934
add warning
dgomes Nov 11, 2018
196f1dc
hound fixes
dgomes Nov 11, 2018
bc5c536
block till done
dgomes Nov 11, 2018
b4d8c91
trying to fix travis test
dgomes Nov 11, 2018
4c81a3d
trying to fix travis test
dgomes Nov 11, 2018
8b34bd1
finally realised there was 8206
dgomes Nov 11, 2018
01f8d62
finally realised there was 8206
dgomes Nov 11, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
STATE_ALARM_ARMED_CUSTOM_BYPASS)


REQUIREMENTS = ['total_connect_client==0.20']
REQUIREMENTS = ['total_connect_client==0.22']

_LOGGER = logging.getLogger(__name__)

Expand Down
20 changes: 20 additions & 0 deletions homeassistant/components/alexa/smart_home.py
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,26 @@ class _AlexaColorController(_AlexaInterface):
def name(self):
return 'Alexa.ColorController'

def properties_supported(self):
return [{'name': 'color'}]

def properties_retrievable(self):
return True

def get_property(self, name):
if name != 'color':
raise _UnsupportedProperty(name)

hue, saturation = self.entity.attributes.get(
light.ATTR_HS_COLOR, (0, 0))

return {
'hue': hue,
'saturation': saturation / 100.0,
'brightness': self.entity.attributes.get(
light.ATTR_BRIGHTNESS, 0) / 255.0,
}


class _AlexaColorTemperatureController(_AlexaInterface):
"""Implements Alexa.ColorTemperatureController.
Expand Down
105 changes: 42 additions & 63 deletions homeassistant/components/camera/push.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,29 +11,26 @@
import voluptuous as vol

from homeassistant.components.camera import Camera, PLATFORM_SCHEMA,\
STATE_IDLE, STATE_RECORDING
STATE_IDLE, STATE_RECORDING, DOMAIN
from homeassistant.core import callback
from homeassistant.components.http.view import KEY_AUTHENTICATED,\
HomeAssistantView
from homeassistant.const import CONF_NAME, CONF_TIMEOUT,\
HTTP_NOT_FOUND, HTTP_UNAUTHORIZED, HTTP_BAD_REQUEST
from homeassistant.const import CONF_NAME, CONF_TIMEOUT, CONF_WEBHOOK_ID
from homeassistant.helpers import config_validation as cv
from homeassistant.helpers.event import async_track_point_in_utc_time
import homeassistant.util.dt as dt_util

DEPENDENCIES = ['webhook']

_LOGGER = logging.getLogger(__name__)

DEPENDENCIES = ['http']
RECEIVED_DATA = 'push_camera_received'

CONF_BUFFER_SIZE = 'buffer'
CONF_IMAGE_FIELD = 'field'
CONF_TOKEN = 'token'

DEFAULT_NAME = "Push Camera"

ATTR_FILENAME = 'filename'
ATTR_LAST_TRIP = 'last_trip'
ATTR_TOKEN = 'token'

PUSH_CAMERA_DATA = 'push_camera'

Expand All @@ -43,7 +40,7 @@
vol.Optional(CONF_TIMEOUT, default=timedelta(seconds=5)): vol.All(
cv.time_period, cv.positive_timedelta),
vol.Optional(CONF_IMAGE_FIELD, default='image'): cv.string,
vol.Optional(CONF_TOKEN): vol.All(cv.string, vol.Length(min=8)),
vol.Required(CONF_WEBHOOK_ID): cv.string,
})


Expand All @@ -53,69 +50,44 @@ async def async_setup_platform(hass, config, async_add_entities,
if PUSH_CAMERA_DATA not in hass.data:
hass.data[PUSH_CAMERA_DATA] = {}

cameras = [PushCamera(config[CONF_NAME],
webhook_id = config.get(CONF_WEBHOOK_ID)

cameras = [PushCamera(hass,
config[CONF_NAME],
config[CONF_BUFFER_SIZE],
config[CONF_TIMEOUT],
config.get(CONF_TOKEN))]
config[CONF_IMAGE_FIELD],
webhook_id)]

hass.http.register_view(CameraPushReceiver(hass,
config[CONF_IMAGE_FIELD]))
try:
hass.components.webhook.async_register(DOMAIN, 'push', webhook_id, handle_webhook)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line too long (90 > 79 characters)

except ValueError:
_LOGGER.error("In <%s>, webhook_id <%s> already used",
config[CONF_NAME], webhook_id)
return

async_add_entities(cameras)


class CameraPushReceiver(HomeAssistantView):
"""Handle pushes from remote camera."""

url = "/api/camera_push/{entity_id}"
name = 'api:camera_push:camera_entity'
requires_auth = False

def __init__(self, hass, image_field):
"""Initialize CameraPushReceiver with camera entity."""
self._cameras = hass.data[PUSH_CAMERA_DATA]
self._image = image_field

async def post(self, request, entity_id):
"""Accept the POST from Camera."""
_camera = self._cameras.get(entity_id)

if _camera is None:
_LOGGER.error("Unknown %s", entity_id)
status = HTTP_NOT_FOUND if request[KEY_AUTHENTICATED]\
else HTTP_UNAUTHORIZED
return self.json_message('Unknown {}'.format(entity_id),
status)

# Supports HA authentication and token based
# when token has been configured
authenticated = (request[KEY_AUTHENTICATED] or
(_camera.token is not None and
request.query.get('token') == _camera.token))

if not authenticated:
return self.json_message(
'Invalid authorization credentials for {}'.format(entity_id),
HTTP_UNAUTHORIZED)

try:
data = await request.post()
_LOGGER.debug("Received Camera push: %s", data[self._image])
await _camera.update_image(data[self._image].file.read(),
data[self._image].filename)
except ValueError as value_error:
_LOGGER.error("Unknown value %s", value_error)
return self.json_message('Invalid POST', HTTP_BAD_REQUEST)
except KeyError as key_error:
_LOGGER.error('In your POST message %s', key_error)
return self.json_message('{} missing'.format(self._image),
HTTP_BAD_REQUEST)
async def handle_webhook(hass, webhook_id, request):
"""Handle incoming webhook POST with image files."""
data = dict(await request.post())
camera = hass.data[PUSH_CAMERA_DATA][webhook_id]

if camera.image_field not in data:
_LOGGER.warning("Webhook call without POST parameter <%s>",
camera.image_field)
return

await camera.update_image(data[camera.image_field].file.read(),
data[camera.image_field].filename)


class PushCamera(Camera):
"""The representation of a Push camera."""

def __init__(self, name, buffer_size, timeout, token):
def __init__(self, hass, name, buffer_size, timeout, image_field,
webhook_id):
"""Initialize push camera component."""
super().__init__()
self._name = name
Expand All @@ -126,11 +98,19 @@ def __init__(self, name, buffer_size, timeout, token):
self._timeout = timeout
self.queue = deque([], buffer_size)
self._current_image = None
self.token = token
self._image_field = image_field
self.webhook_id = webhook_id
self.webhook_url = \
hass.components.webhook.async_generate_url(webhook_id)

async def async_added_to_hass(self):
"""Call when entity is added to hass."""
self.hass.data[PUSH_CAMERA_DATA][self.entity_id] = self
self.hass.data[PUSH_CAMERA_DATA][self.webhook_id] = self

@property
def image_field(self):
"""HTTP field containing the image file."""
return self._image_field

@property
def state(self):
Expand Down Expand Up @@ -189,6 +169,5 @@ def device_state_attributes(self):
name: value for name, value in (
(ATTR_LAST_TRIP, self._last_trip),
(ATTR_FILENAME, self._filename),
(ATTR_TOKEN, self.token),
) if value is not None
}
2 changes: 1 addition & 1 deletion homeassistant/components/homekit/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from .util import (
show_setup_message, validate_entity_config, validate_media_player_features)

REQUIREMENTS = ['HAP-python==2.2.2']
REQUIREMENTS = ['HAP-python==2.4.0']

_LOGGER = logging.getLogger(__name__)

Expand Down
7 changes: 2 additions & 5 deletions homeassistant/components/homekit/type_switches.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
import logging

from pyhap.const import (
CATEGORY_OUTLET, CATEGORY_SWITCH)
CATEGORY_FAUCET, CATEGORY_OUTLET, CATEGORY_SHOWER_HEAD,
CATEGORY_SPRINKLER, CATEGORY_SWITCH)

from homeassistant.components.script import ATTR_CAN_CANCEL
from homeassistant.components.switch import DOMAIN
Expand All @@ -20,10 +21,6 @@

_LOGGER = logging.getLogger(__name__)

CATEGORY_SPRINKLER = 28
CATEGORY_FAUCET = 29
CATEGORY_SHOWER_HEAD = 30

VALVE_TYPE = {
TYPE_FAUCET: (CATEGORY_FAUCET, 3),
TYPE_SHOWER: (CATEGORY_SHOWER_HEAD, 2),
Expand Down
3 changes: 2 additions & 1 deletion homeassistant/components/image_processing/tensorflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -246,7 +246,8 @@ def _save_image(self, image, matches, paths):

for category, values in matches.items():
# Draw custom category regions/areas
if self._category_areas[category] != [0, 0, 1, 1]:
if (category in self._category_areas
and self._category_areas[category] != [0, 0, 1, 1]):
label = "{} Detection Area".format(category.capitalize())
draw_box(draw, self._category_areas[category], img_width,
img_height, label, (0, 255, 0))
Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/light/avion.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
CONF_USERNAME)
import homeassistant.helpers.config_validation as cv

REQUIREMENTS = ['antsar-avion==0.9.1']
REQUIREMENTS = ['avion==0.10']

_LOGGER = logging.getLogger(__name__)

Expand Down
2 changes: 1 addition & 1 deletion homeassistant/components/media_player/dlna_dmr.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
import homeassistant.helpers.config_validation as cv
from homeassistant.util import get_local_ip

REQUIREMENTS = ['async-upnp-client==0.13.1']
REQUIREMENTS = ['async-upnp-client==0.13.2']

_LOGGER = logging.getLogger(__name__)

Expand Down
2 changes: 2 additions & 0 deletions homeassistant/components/mysensors/device.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
ATTR_DESCRIPTION = 'description'
ATTR_DEVICE = 'device'
ATTR_NODE_ID = 'node_id'
ATTR_HEARTBEAT = 'heartbeat'
MYSENSORS_PLATFORM_DEVICES = 'mysensors_devices_{}'


Expand Down Expand Up @@ -51,6 +52,7 @@ def device_state_attributes(self):
child = node.children[self.child_id]
attr = {
ATTR_BATTERY_LEVEL: node.battery_level,
ATTR_HEARTBEAT: node.heartbeat,
ATTR_CHILD_ID: self.child_id,
ATTR_DESCRIPTION: child.description,
ATTR_DEVICE: self.gateway.device,
Expand Down
6 changes: 6 additions & 0 deletions homeassistant/components/mysensors/handler.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,12 @@ async def handle_battery_level(hass, hass_config, msg):
_handle_node_update(hass, msg)


@HANDLERS.register('I_HEARTBEAT_RESPONSE')
async def handle_heartbeat(hass, hass_config, msg):
"""Handle an heartbeat."""
_handle_node_update(hass, msg)


@HANDLERS.register('I_SKETCH_NAME')
async def handle_sketch_name(hass, hass_config, msg):
"""Handle an internal sketch name message."""
Expand Down
13 changes: 4 additions & 9 deletions homeassistant/components/notify/hangouts.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,12 @@
import voluptuous as vol

from homeassistant.components.notify import (ATTR_TARGET, PLATFORM_SCHEMA,
NOTIFY_SERVICE_SCHEMA,
BaseNotificationService,
ATTR_MESSAGE, ATTR_DATA)

from homeassistant.components.hangouts.const \
import (DOMAIN, SERVICE_SEND_MESSAGE, MESSAGE_DATA_SCHEMA,
TARGETS_SCHEMA, CONF_DEFAULT_CONVERSATIONS)
import (DOMAIN, SERVICE_SEND_MESSAGE, TARGETS_SCHEMA,
CONF_DEFAULT_CONVERSATIONS)

_LOGGER = logging.getLogger(__name__)

Expand All @@ -25,11 +24,6 @@
vol.Required(CONF_DEFAULT_CONVERSATIONS): [TARGETS_SCHEMA]
})

NOTIFY_SERVICE_SCHEMA = NOTIFY_SERVICE_SCHEMA.extend({
vol.Optional(ATTR_TARGET): [TARGETS_SCHEMA],
vol.Optional(ATTR_DATA, default={}): MESSAGE_DATA_SCHEMA
})


def get_service(hass, config, discovery_info=None):
"""Get the Hangouts notification service."""
Expand Down Expand Up @@ -61,8 +55,9 @@ def send_message(self, message="", **kwargs):
service_data = {
ATTR_TARGET: target_conversations,
ATTR_MESSAGE: messages,
ATTR_DATA: kwargs[ATTR_DATA]
}
if kwargs[ATTR_DATA]:
service_data[ATTR_DATA] = kwargs[ATTR_DATA]

return self.hass.services.call(
DOMAIN, SERVICE_SEND_MESSAGE, service_data=service_data)
Loading