Merge pull request #22969 from home-assistant/rc

0.91.3
This commit is contained in:
Pascal Vizeli 2019-04-10 16:42:00 +02:00 committed by GitHub
commit 536356ceec
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 94 additions and 30 deletions

View File

@ -79,7 +79,7 @@ def setup_platform(hass, config, add_entities, discovery_info=None):
) )
) )
add_entities(sensors, True) add_entities(sensors, True)
def get_opening_type(zone): def get_opening_type(zone):

View File

@ -70,7 +70,18 @@ class HassIOIngress(HomeAssistantView):
self, request: web.Request, token: str, path: str self, request: web.Request, token: str, path: str
) -> web.WebSocketResponse: ) -> web.WebSocketResponse:
"""Ingress route for websocket.""" """Ingress route for websocket."""
ws_server = web.WebSocketResponse() if hdrs.SEC_WEBSOCKET_PROTOCOL in request.headers:
req_protocols = [
str(proto.strip())
for proto in
request.headers[hdrs.SEC_WEBSOCKET_PROTOCOL].split(",")
]
else:
req_protocols = ()
ws_server = web.WebSocketResponse(
protocols=req_protocols, autoclose=False, autoping=False
)
await ws_server.prepare(request) await ws_server.prepare(request)
# Preparing # Preparing
@ -83,7 +94,8 @@ class HassIOIngress(HomeAssistantView):
# Start proxy # Start proxy
async with self._websession.ws_connect( async with self._websession.ws_connect(
url, headers=source_header url, headers=source_header, protocols=req_protocols,
autoclose=False, autoping=False,
) as ws_client: ) as ws_client:
# Proxy requests # Proxy requests
await asyncio.wait( await asyncio.wait(
@ -205,14 +217,17 @@ def _is_websocket(request: web.Request) -> bool:
async def _websocket_forward(ws_from, ws_to): async def _websocket_forward(ws_from, ws_to):
"""Handle websocket message directly.""" """Handle websocket message directly."""
async for msg in ws_from: try:
if msg.type == aiohttp.WSMsgType.TEXT: async for msg in ws_from:
await ws_to.send_str(msg.data) if msg.type == aiohttp.WSMsgType.TEXT:
elif msg.type == aiohttp.WSMsgType.BINARY: await ws_to.send_str(msg.data)
await ws_to.send_bytes(msg.data) elif msg.type == aiohttp.WSMsgType.BINARY:
elif msg.type == aiohttp.WSMsgType.PING: await ws_to.send_bytes(msg.data)
await ws_to.ping() elif msg.type == aiohttp.WSMsgType.PING:
elif msg.type == aiohttp.WSMsgType.PONG: await ws_to.ping()
await ws_to.pong() elif msg.type == aiohttp.WSMsgType.PONG:
elif ws_to.closed: await ws_to.pong()
await ws_to.close(code=ws_to.close_code, message=msg.extra) elif ws_to.closed:
await ws_to.close(code=ws_to.close_code, message=msg.extra)
except RuntimeError:
_LOGGER.debug("Ingress Websocket runtime error")

View File

@ -8,9 +8,10 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
from .const import (ATTR_SENSOR_STATE, from .const import (ATTR_SENSOR_STATE,
ATTR_SENSOR_TYPE_BINARY_SENSOR as ENTITY_TYPE, ATTR_SENSOR_TYPE_BINARY_SENSOR as ENTITY_TYPE,
ATTR_SENSOR_UNIQUE_ID,
DATA_DEVICES, DOMAIN) DATA_DEVICES, DOMAIN)
from .entity import MobileAppEntity from .entity import MobileAppEntity, sensor_id
DEPENDENCIES = ['mobile_app'] DEPENDENCIES = ['mobile_app']
@ -36,6 +37,16 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
if data[CONF_WEBHOOK_ID] != webhook_id: if data[CONF_WEBHOOK_ID] != webhook_id:
return return
unique_id = sensor_id(data[CONF_WEBHOOK_ID],
data[ATTR_SENSOR_UNIQUE_ID])
entity = hass.data[DOMAIN][ENTITY_TYPE][unique_id]
if 'added' in entity:
return
entity['added'] = True
device = hass.data[DOMAIN][DATA_DEVICES][data[CONF_WEBHOOK_ID]] device = hass.data[DOMAIN][DATA_DEVICES][data[CONF_WEBHOOK_ID]]
async_add_entities([MobileAppBinarySensor(data, device, config_entry)]) async_add_entities([MobileAppBinarySensor(data, device, config_entry)])

View File

@ -13,6 +13,11 @@ from .const import (ATTR_DEVICE_ID, ATTR_DEVICE_NAME, ATTR_MANUFACTURER,
DOMAIN, SIGNAL_SENSOR_UPDATE) DOMAIN, SIGNAL_SENSOR_UPDATE)
def sensor_id(webhook_id, unique_id):
"""Return a unique sensor ID."""
return "{}_{}".format(webhook_id, unique_id)
class MobileAppEntity(Entity): class MobileAppEntity(Entity):
"""Representation of an mobile app entity.""" """Representation of an mobile app entity."""
@ -22,8 +27,8 @@ class MobileAppEntity(Entity):
self._device = device self._device = device
self._entry = entry self._entry = entry
self._registration = entry.data self._registration = entry.data
self._sensor_id = "{}_{}".format(self._registration[CONF_WEBHOOK_ID], self._sensor_id = sensor_id(self._registration[CONF_WEBHOOK_ID],
config[ATTR_SENSOR_UNIQUE_ID]) config[ATTR_SENSOR_UNIQUE_ID])
self._entity_type = config[ATTR_SENSOR_TYPE] self._entity_type = config[ATTR_SENSOR_TYPE]
self.unsub_dispatcher = None self.unsub_dispatcher = None
@ -94,5 +99,10 @@ class MobileAppEntity(Entity):
@callback @callback
def _handle_update(self, data): def _handle_update(self, data):
"""Handle async event updates.""" """Handle async event updates."""
incoming_id = sensor_id(data[CONF_WEBHOOK_ID],
data[ATTR_SENSOR_UNIQUE_ID])
if incoming_id != self._sensor_id:
return
self._config = data self._config = data
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()

View File

@ -7,9 +7,10 @@ from homeassistant.helpers.dispatcher import async_dispatcher_connect
from .const import (ATTR_SENSOR_STATE, from .const import (ATTR_SENSOR_STATE,
ATTR_SENSOR_TYPE_SENSOR as ENTITY_TYPE, ATTR_SENSOR_TYPE_SENSOR as ENTITY_TYPE,
ATTR_SENSOR_UOM, DATA_DEVICES, DOMAIN) ATTR_SENSOR_UNIQUE_ID, ATTR_SENSOR_UOM, DATA_DEVICES,
DOMAIN)
from .entity import MobileAppEntity from .entity import MobileAppEntity, sensor_id
DEPENDENCIES = ['mobile_app'] DEPENDENCIES = ['mobile_app']
@ -35,6 +36,16 @@ async def async_setup_entry(hass, config_entry, async_add_entities):
if data[CONF_WEBHOOK_ID] != webhook_id: if data[CONF_WEBHOOK_ID] != webhook_id:
return return
unique_id = sensor_id(data[CONF_WEBHOOK_ID],
data[ATTR_SENSOR_UNIQUE_ID])
entity = hass.data[DOMAIN][ENTITY_TYPE][unique_id]
if 'added' in entity:
return
entity['added'] = True
device = hass.data[DOMAIN][DATA_DEVICES][data[CONF_WEBHOOK_ID]] device = hass.data[DOMAIN][DATA_DEVICES][data[CONF_WEBHOOK_ID]]
async_add_entities([MobileAppSensor(data, device, config_entry)]) async_add_entities([MobileAppSensor(data, device, config_entry)])

View File

@ -4,6 +4,8 @@ import logging
from aiohttp.web import HTTPBadRequest, Response, Request from aiohttp.web import HTTPBadRequest, Response, Request
import voluptuous as vol import voluptuous as vol
from homeassistant.components.cloud import (async_remote_ui_url,
CloudNotAvailable)
from homeassistant.components.device_tracker import (ATTR_ATTRIBUTES, from homeassistant.components.device_tracker import (ATTR_ATTRIBUTES,
ATTR_DEV_ID, ATTR_DEV_ID,
DOMAIN as DT_DOMAIN, DOMAIN as DT_DOMAIN,
@ -31,14 +33,15 @@ from .const import (ATTR_ALTITUDE, ATTR_BATTERY, ATTR_COURSE, ATTR_DEVICE_ID,
ATTR_TEMPLATE_VARIABLES, ATTR_VERTICAL_ACCURACY, ATTR_TEMPLATE_VARIABLES, ATTR_VERTICAL_ACCURACY,
ATTR_WEBHOOK_DATA, ATTR_WEBHOOK_ENCRYPTED, ATTR_WEBHOOK_DATA, ATTR_WEBHOOK_ENCRYPTED,
ATTR_WEBHOOK_ENCRYPTED_DATA, ATTR_WEBHOOK_TYPE, ATTR_WEBHOOK_ENCRYPTED_DATA, ATTR_WEBHOOK_TYPE,
CONF_SECRET, DATA_CONFIG_ENTRIES, DATA_DELETED_IDS, CONF_CLOUDHOOK_URL, CONF_REMOTE_UI_URL, CONF_SECRET,
DATA_STORE, DOMAIN, ERR_ENCRYPTION_REQUIRED, DATA_CONFIG_ENTRIES, DATA_DELETED_IDS, DATA_STORE, DOMAIN,
ERR_SENSOR_DUPLICATE_UNIQUE_ID, ERR_SENSOR_NOT_REGISTERED, ERR_ENCRYPTION_REQUIRED, ERR_SENSOR_DUPLICATE_UNIQUE_ID,
SIGNAL_SENSOR_UPDATE, WEBHOOK_PAYLOAD_SCHEMA, ERR_SENSOR_NOT_REGISTERED, SIGNAL_SENSOR_UPDATE,
WEBHOOK_SCHEMAS, WEBHOOK_TYPES, WEBHOOK_TYPE_CALL_SERVICE, WEBHOOK_PAYLOAD_SCHEMA, WEBHOOK_SCHEMAS, WEBHOOK_TYPES,
WEBHOOK_TYPE_FIRE_EVENT, WEBHOOK_TYPE_GET_CONFIG, WEBHOOK_TYPE_CALL_SERVICE, WEBHOOK_TYPE_FIRE_EVENT,
WEBHOOK_TYPE_GET_ZONES, WEBHOOK_TYPE_REGISTER_SENSOR, WEBHOOK_TYPE_GET_CONFIG, WEBHOOK_TYPE_GET_ZONES,
WEBHOOK_TYPE_RENDER_TEMPLATE, WEBHOOK_TYPE_UPDATE_LOCATION, WEBHOOK_TYPE_REGISTER_SENSOR, WEBHOOK_TYPE_RENDER_TEMPLATE,
WEBHOOK_TYPE_UPDATE_LOCATION,
WEBHOOK_TYPE_UPDATE_REGISTRATION, WEBHOOK_TYPE_UPDATE_REGISTRATION,
WEBHOOK_TYPE_UPDATE_SENSOR_STATES) WEBHOOK_TYPE_UPDATE_SENSOR_STATES)
@ -96,6 +99,9 @@ async def handle_webhook(hass: HomeAssistantType, webhook_id: str,
data = webhook_payload data = webhook_payload
_LOGGER.debug("Received webhook payload for type %s: %s", webhook_type,
data)
if webhook_type in WEBHOOK_SCHEMAS: if webhook_type in WEBHOOK_SCHEMAS:
try: try:
data = WEBHOOK_SCHEMAS[webhook_type](webhook_payload) data = WEBHOOK_SCHEMAS[webhook_type](webhook_payload)
@ -286,7 +292,7 @@ async def handle_webhook(hass: HomeAssistantType, webhook_id: str,
hass_config = hass.config.as_dict() hass_config = hass.config.as_dict()
return webhook_response({ resp = {
'latitude': hass_config['latitude'], 'latitude': hass_config['latitude'],
'longitude': hass_config['longitude'], 'longitude': hass_config['longitude'],
'elevation': hass_config['elevation'], 'elevation': hass_config['elevation'],
@ -296,4 +302,15 @@ async def handle_webhook(hass: HomeAssistantType, webhook_id: str,
'components': hass_config['components'], 'components': hass_config['components'],
'version': hass_config['version'], 'version': hass_config['version'],
'theme_color': MANIFEST_JSON['theme_color'], 'theme_color': MANIFEST_JSON['theme_color'],
}, registration=registration, headers=headers) }
if CONF_CLOUDHOOK_URL in registration:
resp[CONF_CLOUDHOOK_URL] = registration[CONF_CLOUDHOOK_URL]
try:
resp[CONF_REMOTE_UI_URL] = async_remote_ui_url(hass)
except CloudNotAvailable:
pass
return webhook_response(resp, registration=registration,
headers=headers)

View File

@ -2,7 +2,7 @@
"""Constants used by Home Assistant components.""" """Constants used by Home Assistant components."""
MAJOR_VERSION = 0 MAJOR_VERSION = 0
MINOR_VERSION = 91 MINOR_VERSION = 91
PATCH_VERSION = '2' PATCH_VERSION = '3'
__short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION) __short_version__ = '{}.{}'.format(MAJOR_VERSION, MINOR_VERSION)
__version__ = '{}.{}'.format(__short_version__, PATCH_VERSION) __version__ = '{}.{}'.format(__short_version__, PATCH_VERSION)
REQUIRED_PYTHON_VER = (3, 5, 3) REQUIRED_PYTHON_VER = (3, 5, 3)