MQTT Python 3.5 Async Await Syntax (#12815)

* MQTT Async Await

* Remove unused decorator.
This commit is contained in:
Otto Winter 2018-03-02 00:06:26 +01:00 committed by Paulus Schoutsen
parent de3c76983a
commit d3386907a4
2 changed files with 41 additions and 52 deletions

View File

@ -228,17 +228,16 @@ def publish_template(hass: HomeAssistantType, topic, payload_template,
hass.services.call(DOMAIN, SERVICE_PUBLISH, data) hass.services.call(DOMAIN, SERVICE_PUBLISH, data)
@asyncio.coroutine
@bind_hass @bind_hass
def async_subscribe(hass: HomeAssistantType, topic: str, async def async_subscribe(hass: HomeAssistantType, topic: str,
msg_callback: MessageCallbackType, msg_callback: MessageCallbackType,
qos: int = DEFAULT_QOS, qos: int = DEFAULT_QOS,
encoding: str = 'utf-8'): encoding: str = 'utf-8'):
"""Subscribe to an MQTT topic. """Subscribe to an MQTT topic.
Call the return value to unsubscribe. Call the return value to unsubscribe.
""" """
async_remove = yield from hass.data[DATA_MQTT].async_subscribe( async_remove = await hass.data[DATA_MQTT].async_subscribe(
topic, msg_callback, qos, encoding) topic, msg_callback, qos, encoding)
return async_remove return async_remove
@ -259,16 +258,15 @@ def subscribe(hass: HomeAssistantType, topic: str,
return remove return remove
@asyncio.coroutine async def _async_setup_server(hass: HomeAssistantType,
def _async_setup_server(hass: HomeAssistantType, config: ConfigType):
config: ConfigType):
"""Try to start embedded MQTT broker. """Try to start embedded MQTT broker.
This method is a coroutine. This method is a coroutine.
""" """
conf = config.get(DOMAIN, {}) # type: ConfigType conf = config.get(DOMAIN, {}) # type: ConfigType
server = yield from async_prepare_setup_platform( server = await async_prepare_setup_platform(
hass, config, DOMAIN, 'server') hass, config, DOMAIN, 'server')
if server is None: if server is None:
@ -276,37 +274,35 @@ def _async_setup_server(hass: HomeAssistantType,
return None return None
success, broker_config = \ success, broker_config = \
yield from server.async_start(hass, conf.get(CONF_EMBEDDED)) await server.async_start(hass, conf.get(CONF_EMBEDDED))
if not success: if not success:
return None return None
return broker_config return broker_config
@asyncio.coroutine async def _async_setup_discovery(hass: HomeAssistantType,
def _async_setup_discovery(hass: HomeAssistantType, config: ConfigType) -> bool:
config: ConfigType):
"""Try to start the discovery of MQTT devices. """Try to start the discovery of MQTT devices.
This method is a coroutine. This method is a coroutine.
""" """
conf = config.get(DOMAIN, {}) # type: ConfigType conf = config.get(DOMAIN, {}) # type: ConfigType
discovery = yield from async_prepare_setup_platform( discovery = await async_prepare_setup_platform(
hass, config, DOMAIN, 'discovery') hass, config, DOMAIN, 'discovery')
if discovery is None: if discovery is None:
_LOGGER.error("Unable to load MQTT discovery") _LOGGER.error("Unable to load MQTT discovery")
return False return False
success = yield from discovery.async_start( success = await discovery.async_start(
hass, conf[CONF_DISCOVERY_PREFIX], config) # type: bool hass, conf[CONF_DISCOVERY_PREFIX], config) # type: bool
return success return success
@asyncio.coroutine async def async_setup(hass: HomeAssistantType, config: ConfigType) -> bool:
def async_setup(hass: HomeAssistantType, config: ConfigType):
"""Start the MQTT protocol service.""" """Start the MQTT protocol service."""
conf = config.get(DOMAIN) # type: Optional[ConfigType] conf = config.get(DOMAIN) # type: Optional[ConfigType]
@ -321,7 +317,7 @@ def async_setup(hass: HomeAssistantType, config: ConfigType):
if CONF_EMBEDDED not in conf and CONF_BROKER in conf: if CONF_EMBEDDED not in conf and CONF_BROKER in conf:
broker_config = None broker_config = None
else: else:
broker_config = yield from _async_setup_server(hass, config) broker_config = await _async_setup_server(hass, config)
if CONF_BROKER in conf: if CONF_BROKER in conf:
broker = conf[CONF_BROKER] # type: str broker = conf[CONF_BROKER] # type: str
@ -392,19 +388,17 @@ def async_setup(hass: HomeAssistantType, config: ConfigType):
"Please check your settings and the broker itself") "Please check your settings and the broker itself")
return False return False
@asyncio.coroutine async def async_stop_mqtt(event: Event):
def async_stop_mqtt(event: Event):
"""Stop MQTT component.""" """Stop MQTT component."""
yield from hass.data[DATA_MQTT].async_disconnect() await hass.data[DATA_MQTT].async_disconnect()
hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_stop_mqtt) hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, async_stop_mqtt)
success = yield from hass.data[DATA_MQTT].async_connect() # type: bool success = await hass.data[DATA_MQTT].async_connect() # type: bool
if not success: if not success:
return False return False
@asyncio.coroutine async def async_publish_service(call: ServiceCall):
def async_publish_service(call: ServiceCall):
"""Handle MQTT publish service calls.""" """Handle MQTT publish service calls."""
msg_topic = call.data[ATTR_TOPIC] # type: str msg_topic = call.data[ATTR_TOPIC] # type: str
payload = call.data.get(ATTR_PAYLOAD) payload = call.data.get(ATTR_PAYLOAD)
@ -422,7 +416,7 @@ def async_setup(hass: HomeAssistantType, config: ConfigType):
msg_topic, payload_template, exc) msg_topic, payload_template, exc)
return return
yield from hass.data[DATA_MQTT].async_publish( await hass.data[DATA_MQTT].async_publish(
msg_topic, payload, qos, retain) msg_topic, payload, qos, retain)
hass.services.async_register( hass.services.async_register(
@ -430,7 +424,7 @@ def async_setup(hass: HomeAssistantType, config: ConfigType):
schema=MQTT_PUBLISH_SCHEMA) schema=MQTT_PUBLISH_SCHEMA)
if conf.get(CONF_DISCOVERY): if conf.get(CONF_DISCOVERY):
yield from _async_setup_discovery(hass, config) await _async_setup_discovery(hass, config)
return True return True
@ -505,25 +499,23 @@ class MQTT(object):
if will_message is not None: if will_message is not None:
self._mqttc.will_set(*attr.astuple(will_message)) self._mqttc.will_set(*attr.astuple(will_message))
@asyncio.coroutine async def async_publish(self, topic: str, payload: PublishPayloadType,
def async_publish(self, topic: str, payload: PublishPayloadType, qos: int, qos: int, retain: bool) -> None:
retain: bool):
"""Publish a MQTT message. """Publish a MQTT message.
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.
""" """
with (yield from self._paho_lock): async with self._paho_lock:
yield from self.hass.async_add_job( await self.hass.async_add_job(
self._mqttc.publish, topic, payload, qos, retain) self._mqttc.publish, topic, payload, qos, retain)
@asyncio.coroutine async def async_connect(self) -> bool:
def async_connect(self):
"""Connect to the host. Does process messages yet. """Connect to the host. Does process messages yet.
This method is a coroutine. This method is a coroutine.
""" """
result = None # type: int result = None # type: int
result = yield from self.hass.async_add_job( result = await self.hass.async_add_job(
self._mqttc.connect, self.broker, self.port, self.keepalive) self._mqttc.connect, self.broker, self.port, self.keepalive)
if result != 0: if result != 0:
@ -547,9 +539,9 @@ class MQTT(object):
return self.hass.async_add_job(stop) return self.hass.async_add_job(stop)
@asyncio.coroutine async def async_subscribe(self, topic: str,
def async_subscribe(self, topic: str, msg_callback: MessageCallbackType, msg_callback: MessageCallbackType,
qos: int, encoding: str): qos: int, encoding: str) -> Callable[[], None]:
"""Set up a subscription to a topic with the provided qos. """Set up a subscription to a topic with the provided qos.
This method is a coroutine. This method is a coroutine.
@ -560,10 +552,10 @@ class MQTT(object):
subscription = Subscription(topic, msg_callback, qos, encoding) subscription = Subscription(topic, msg_callback, qos, encoding)
self.subscriptions.append(subscription) self.subscriptions.append(subscription)
yield from self._async_perform_subscription(topic, qos) await self._async_perform_subscription(topic, qos)
@callback @callback
def async_remove(): def async_remove() -> None:
"""Remove subscription.""" """Remove subscription."""
if subscription not in self.subscriptions: if subscription not in self.subscriptions:
raise HomeAssistantError("Can't remove subscription twice") raise HomeAssistantError("Can't remove subscription twice")
@ -576,27 +568,24 @@ class MQTT(object):
return async_remove return async_remove
@asyncio.coroutine async def _async_unsubscribe(self, topic: str) -> None:
def _async_unsubscribe(self, topic: str):
"""Unsubscribe from a topic. """Unsubscribe from a topic.
This method is a coroutine. This method is a coroutine.
""" """
with (yield from self._paho_lock): async with self._paho_lock:
result = None # type: int result = None # type: int
result, _ = yield from self.hass.async_add_job( result, _ = await self.hass.async_add_job(
self._mqttc.unsubscribe, topic) self._mqttc.unsubscribe, topic)
_raise_on_error(result) _raise_on_error(result)
@asyncio.coroutine async def _async_perform_subscription(self, topic: str, qos: int) -> None:
def _async_perform_subscription(self, topic: str,
qos: int):
"""Perform a paho-mqtt subscription.""" """Perform a paho-mqtt subscription."""
_LOGGER.debug("Subscribing to %s", topic) _LOGGER.debug("Subscribing to %s", topic)
with (yield from self._paho_lock): async with self._paho_lock:
result = None # type: int result = None # type: int
result, _ = yield from self.hass.async_add_job( result, _ = await self.hass.async_add_job(
self._mqttc.subscribe, topic, qos) self._mqttc.subscribe, topic, qos)
_raise_on_error(result) _raise_on_error(result)
@ -721,8 +710,7 @@ class MqttAvailability(Entity):
self._payload_available = payload_available self._payload_available = payload_available
self._payload_not_available = payload_not_available self._payload_not_available = payload_not_available
@asyncio.coroutine async def async_added_to_hass(self) -> None:
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.
@ -740,7 +728,7 @@ class MqttAvailability(Entity):
self.async_schedule_update_ha_state() self.async_schedule_update_ha_state()
if self._availability_topic is not None: if self._availability_topic is not None:
yield from async_subscribe( await async_subscribe(
self.hass, self._availability_topic, self.hass, self._availability_topic,
availability_message_received, self._availability_qos) availability_message_received, self._availability_qos)

View File

@ -28,6 +28,7 @@ def async_mock_mqtt_client(hass, config=None):
with mock.patch('paho.mqtt.client.Client') as mock_client: with mock.patch('paho.mqtt.client.Client') as mock_client:
mock_client().connect.return_value = 0 mock_client().connect.return_value = 0
mock_client().subscribe.return_value = (0, 0) mock_client().subscribe.return_value = (0, 0)
mock_client().unsubscribe.return_value = (0, 0)
mock_client().publish.return_value = (0, 0) mock_client().publish.return_value = (0, 0)
result = yield from async_setup_component(hass, mqtt.DOMAIN, { result = yield from async_setup_component(hass, mqtt.DOMAIN, {
mqtt.DOMAIN: config mqtt.DOMAIN: config