Fix invalid state (#16558)

* Fix invalid state

* Make slightly more efficient in unsubscribing

* Use uuid4"
This commit is contained in:
Paulus Schoutsen
2018-09-11 21:40:35 +02:00
committed by GitHub
parent 629c4a0bf5
commit 06af76404f
3 changed files with 45 additions and 7 deletions

View File

@@ -29,7 +29,7 @@ from voluptuous.humanize import humanize_error
from homeassistant.const import (
ATTR_DOMAIN, ATTR_FRIENDLY_NAME, ATTR_NOW, ATTR_SERVICE,
ATTR_SERVICE_DATA, EVENT_CALL_SERVICE,
ATTR_SERVICE_CALL_ID, ATTR_SERVICE_DATA, EVENT_CALL_SERVICE,
EVENT_HOMEASSISTANT_START, EVENT_HOMEASSISTANT_STOP,
EVENT_SERVICE_EXECUTED, EVENT_SERVICE_REGISTERED, EVENT_STATE_CHANGED,
EVENT_TIME_CHANGED, MATCH_ALL, EVENT_HOMEASSISTANT_CLOSE,
@@ -1042,10 +1042,12 @@ class ServiceRegistry:
This method is a coroutine.
"""
context = context or Context()
call_id = uuid.uuid4().hex
event_data = {
ATTR_DOMAIN: domain.lower(),
ATTR_SERVICE: service.lower(),
ATTR_SERVICE_DATA: service_data,
ATTR_SERVICE_CALL_ID: call_id,
}
if not blocking:
@@ -1058,8 +1060,9 @@ class ServiceRegistry:
@callback
def service_executed(event: Event) -> None:
"""Handle an executed service."""
if event.context == context:
if event.data[ATTR_SERVICE_CALL_ID] == call_id:
fut.set_result(True)
unsub()
unsub = self._hass.bus.async_listen(
EVENT_SERVICE_EXECUTED, service_executed)
@@ -1069,7 +1072,8 @@ class ServiceRegistry:
done, _ = await asyncio.wait([fut], timeout=SERVICE_CALL_LIMIT)
success = bool(done)
unsub()
if not success:
unsub()
return success
async def _event_to_service_call(self, event: Event) -> None:
@@ -1077,6 +1081,7 @@ class ServiceRegistry:
service_data = event.data.get(ATTR_SERVICE_DATA) or {}
domain = event.data.get(ATTR_DOMAIN).lower() # type: ignore
service = event.data.get(ATTR_SERVICE).lower() # type: ignore
call_id = event.data.get(ATTR_SERVICE_CALL_ID)
if not self.has_service(domain, service):
if event.origin == EventOrigin.local:
@@ -1088,12 +1093,17 @@ class ServiceRegistry:
def fire_service_executed() -> None:
"""Fire service executed event."""
if not call_id:
return
data = {ATTR_SERVICE_CALL_ID: call_id}
if (service_handler.is_coroutinefunction or
service_handler.is_callback):
self._hass.bus.async_fire(EVENT_SERVICE_EXECUTED, {},
self._hass.bus.async_fire(EVENT_SERVICE_EXECUTED, data,
EventOrigin.local, event.context)
else:
self._hass.bus.fire(EVENT_SERVICE_EXECUTED, {},
self._hass.bus.fire(EVENT_SERVICE_EXECUTED, data,
EventOrigin.local, event.context)
try: