Skip to content

Commit a2ff161

Browse files
Merge pull request #235 from Necroneco/async
Migrate to asyncio
2 parents fbb33ae + aecad4e commit a2ff161

File tree

2 files changed

+31
-20
lines changed

2 files changed

+31
-20
lines changed

custom_components/aqara_gateway/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import voluptuous as vol
55

66
from homeassistant.config_entries import ConfigEntry
7-
from homeassistant.const import MAJOR_VERSION, MINOR_VERSION, STATE_UNKNOWN, EVENT_HOMEASSISTANT_STOP
7+
from homeassistant.const import MAJOR_VERSION, MINOR_VERSION, EVENT_HOMEASSISTANT_STOP
88
from homeassistant.core import HomeAssistant, Event
99
from homeassistant.helpers import config_validation as cv
1010
from homeassistant.helpers.entity import Entity
@@ -66,7 +66,7 @@ async def async_setup_entry(hass: HomeAssistant, entry: ConfigEntry):
6666
hass.async_create_task(hass.config_entries.async_forward_entry_setup(
6767
entry, domain))
6868

69-
gateway.start()
69+
gateway.start(hass, entry)
7070

7171
await hass.data[DOMAIN][entry.entry_id].async_connect()
7272

custom_components/aqara_gateway/core/gateway.py

Lines changed: 29 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
""" Aqara Gateway """
2+
import asyncio
23
# pylint: disable=broad-except
34
import logging
45
import socket
56
import time
67
import json
78
import re
8-
from threading import Thread
99
from typing import Optional
1010
from random import randint
1111
from paho.mqtt.client import Client, MQTTMessage
1212

13-
from homeassistant.core import Event
14-
from homeassistant.const import CONF_NAME, CONF_PASSWORD
13+
from homeassistant.config_entries import ConfigEntry
14+
from homeassistant.core import Event, HomeAssistant
15+
from homeassistant.const import CONF_NAME, CONF_PASSWORD, MAJOR_VERSION, MINOR_VERSION
1516
from homeassistant.components.light import ATTR_HS_COLOR, ATTR_RGB_COLOR, ATTR_BRIGHTNESS
1617

1718
from .shell import (
@@ -34,13 +35,14 @@
3435
MD5_MOSQUITTO_G2HPRO_ARMV7L = '9cd591ec76f85c4d96b744eb99943eb3'
3536
MD5_MOSQUITTO_MIPSEL = 'e0ce4757cfcccb079d89134381fd11b0'
3637

37-
class Gateway(Thread):
38+
class Gateway:
3839
# pylint: disable=too-many-instance-attributes, unused-argument
3940
""" Aqara Gateway """
4041

41-
def __init__(self, hass, host: str, config: dict, **options):
42+
main_task: asyncio.Task | None = None # for HA < 2023.3
43+
44+
def __init__(self, hass: HomeAssistant, host: str, config: dict, **options):
4245
"""Initialize the Xiaomi/Aqara device."""
43-
super().__init__(daemon=True)
4446
self.hass = hass
4547
self.host = host
4648
self.options = options
@@ -94,9 +96,12 @@ def stop(self):
9496
""" stop function """
9597
self.enabled = False
9698

97-
async def async_connect(self) -> str:
99+
if self.main_task: # HA < 2023.3
100+
self.main_task.cancel()
101+
102+
async def async_connect(self):
98103
"""Connect to the host. Does not process messages yet."""
99-
result: int = None
104+
result: int | None = None
100105
try:
101106
result = await self.hass.async_add_executor_job(
102107
self._mqttc.connect,
@@ -125,7 +130,13 @@ def stop():
125130

126131
await self.hass.async_add_executor_job(stop)
127132

128-
def run(self):
133+
def start(self, hass: HomeAssistant, config_entry: ConfigEntry):
134+
if (MAJOR_VERSION, MINOR_VERSION) >= (2023, 3):
135+
config_entry.async_create_background_task(hass, self.run(), f"{DOMAIN} gateway.run")
136+
else:
137+
self.main_task = hass.loop.create_task(self.run())
138+
139+
async def run(self):
129140
""" Main thread loop. """
130141
telnetshell = False
131142
if "telnet" not in self.hass.data[DOMAIN]:
@@ -136,14 +147,14 @@ def run(self):
136147
if not self._check_port(23):
137148
if self.host in self.hass.data[DOMAIN]["telnet"]:
138149
self.hass.data[DOMAIN]["telnet"].remove(self.host)
139-
time.sleep(30)
150+
await asyncio.sleep(30)
140151
continue
141152

142153
telnetshell = True
143154
devices = self._prepare_gateway(get_devices=True)
144155
if isinstance(devices, list):
145156
self._gw_topic = "gw/{}/".format(devices[0]['mac'][2:].upper())
146-
self.setup_devices(devices)
157+
await self.setup_devices(devices)
147158
break
148159

149160
if telnetshell:
@@ -154,7 +165,7 @@ def run(self):
154165
if not self._mqtt_connect() or not self._prepare_gateway():
155166
if self.host in self.hass.data[DOMAIN]["mqtt"]:
156167
self.hass.data[DOMAIN]["mqtt"].remove(self.host)
157-
time.sleep(60)
168+
await asyncio.sleep(60)
158169
continue
159170

160171
self._mqttc.loop_start()
@@ -319,7 +330,7 @@ def _get_devices(self, shell):
319330

320331
return devices
321332

322-
def setup_devices(self, devices: list):
333+
async def setup_devices(self, devices: list):
323334
"""Add devices to hass."""
324335
for device in devices:
325336
timeout = 300
@@ -349,7 +360,7 @@ def setup_devices(self, devices: list):
349360

350361
# wait domain init
351362
while domain not in self.setups and timeout > 0:
352-
time.sleep(1)
363+
await asyncio.sleep(1)
353364
timeout = timeout - 1
354365
attr = param[2]
355366
if (attr in ('illuminance', 'light') and
@@ -360,7 +371,7 @@ def setup_devices(self, devices: list):
360371

361372
if self.options.get('stats'):
362373
while 'sensor' not in self.setups:
363-
time.sleep(1)
374+
await asyncio.sleep(1)
364375
self.setups['sensor'](self, device, device['type'])
365376

366377
def add_stats(self, ieee: str, handler):
@@ -467,7 +478,7 @@ def on_disconnect(self, client, userdata, ret):
467478
self.hass.data[DOMAIN]["mqtt"].remove(self.host)
468479
self.available = False
469480
# self.process_gateway_stats()
470-
self.run()
481+
self.hass.create_task(self.run())
471482

472483
def on_message(self, client: Client, userdata, msg: MQTTMessage):
473484
# pylint: disable=unused-argument
@@ -575,7 +586,7 @@ def _process_devices_info(self, prop, value):
575586
'model_ver': dev['model_ver'],
576587
'status': dev['status']
577588
}
578-
self.setup_devices([device])
589+
self.hass.create_task(self.setup_devices([device]))
579590
break
580591

581592
def _process_message(self, data: dict):
@@ -739,7 +750,7 @@ def _process_message(self, data: dict):
739750
device['mac'] = '0x' + device['mac']
740751
device['type'] = 'zigbee'
741752
device['init'] = payload
742-
self.setup_devices([device])
753+
self.hass.create_task(self.setup_devices([device]))
743754

744755
async def _handle_device_remove(self, payload: dict):
745756
"""Remove device from Hass. """

0 commit comments

Comments
 (0)