diff --git a/custom_components/mega/__init__.py b/custom_components/mega/__init__.py index 61476a5..032a5ce 100644 --- a/custom_components/mega/__init__.py +++ b/custom_components/mega/__init__.py @@ -133,7 +133,7 @@ async def async_remove_entry(hass, entry) -> None: async def _save_service(hass: HomeAssistant, call: ServiceCall): - mega_id = call.data['mega_id'] + mega_id = call.data.get('mega_id') if mega_id: hub: MegaD = hass.data[DOMAIN][mega_id] await hub.save() @@ -144,8 +144,8 @@ async def _save_service(hass: HomeAssistant, call: ServiceCall): @bind_hass async def _get_port(hass: HomeAssistant, call: ServiceCall): - port = call.data['port'] - mega_id = call.data['mega_id'] + port = call.data.get('port') + mega_id = call.data.get('mega_id') if mega_id: hub: MegaD = hass.data[DOMAIN][mega_id] if port is None: @@ -162,9 +162,9 @@ async def _get_port(hass: HomeAssistant, call: ServiceCall): @bind_hass async def _run_cmd(hass: HomeAssistant, call: ServiceCall): - port = call.data['port'] - mega_id = call.data['mega_id'] - cmd = call.data['cmd'] + port = call.data.get('port') + mega_id = call.data.get('mega_id') + cmd = call.data.get('cmd') if mega_id: hub: MegaD = hass.data[DOMAIN][mega_id] await hub.send_command(port=port, cmd=cmd) diff --git a/custom_components/mega/binary_sensor.py b/custom_components/mega/binary_sensor.py index 72a5da5..9862c7d 100644 --- a/custom_components/mega/binary_sensor.py +++ b/custom_components/mega/binary_sensor.py @@ -1,4 +1,5 @@ """Platform for light integration.""" +import asyncio import logging import voluptuous as vol @@ -60,13 +61,16 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn mid = config_entry.data[CONF_ID] hub: MegaD = hass.data['mega'][mid] devices = [] - async for port, pty, m in hub.scan_ports(): - if pty == "0": - sensor = MegaBinarySensor(mega_id=mid, port=port) - devices.append(sensor) - async_add_devices(devices) + async def scan(): + async for port, pty, m in hub.scan_ports(): + if pty == "0": + sensor = MegaBinarySensor(mega_id=mid, port=port) + devices.append(sensor) + async_add_devices(devices) + + asyncio.create_task(scan()) class MegaBinarySensor(BinarySensorEntity, BaseMegaEntity): diff --git a/custom_components/mega/hub.py b/custom_components/mega/hub.py index b8e44a3..34832d9 100644 --- a/custom_components/mega/hub.py +++ b/custom_components/mega/hub.py @@ -140,36 +140,45 @@ class MegaD: async def save(self): await self.send_command(cmd='s') - async def get_port(self, port, get_value=False): - if get_value: - ftr = asyncio.get_event_loop().create_future() + async def get_port(self, port): + """ + Опрашивает порт с помощью mqtt. Ждет ответ, возвращает ответ. - def cb(msg): - try: - ftr.set_result(json.loads(msg.payload).get('value')) - except Exception as exc: - self.lg.warning(f'could not parse {msg.payload}: {exc}') - ftr.set_result(None) - unsub = await self.mqtt.async_subscribe( - topic=f'{self.mqtt_id}/{port}', - msg_callback=cb, - qos=1, - ) + :param port: + :return: + """ + ftr = asyncio.get_event_loop().create_future() - self.lg.debug( - f'get port: %s', port - ) - async with self.lck: - await self.mqtt.async_publish( - topic=f'{self.mqtt_id}/cmd', - payload=f'get:{port}', - qos=0, - retain=False, - ) - await asyncio.sleep(0.1) + def cb(msg): - if get_value: try: + if '"value":NA' in msg.payload.decode(): + ftr.set_result(None) + return + ret = json.loads(msg.payload).get('value') + ftr.set_result(ret) + except Exception as exc: + ret = None + self.lg.exception(f'while parsing response from port {port}: {msg.payload}') + ftr.set_result(None) + + self.lg.debug( + f'port: %s response: %s', port, ret + ) + + async with self.lck: + try: + unsub = await self.mqtt.async_subscribe( + topic=f'{self.mqtt_id}/{port}', + msg_callback=cb, + qos=1, + ) + await self.mqtt.async_publish( + topic=f'{self.mqtt_id}/cmd', + payload=f'get:{port}', + qos=1, + retain=False, + ) return await asyncio.wait_for(ftr, timeout=2) except asyncio.TimeoutError: self.lg.warning(f'timeout on port {port}') @@ -259,7 +268,8 @@ class MegaD: return pty, m async def scan_ports(self,): - for x in range(38): - ret = await self.scan_port(x) - if ret: - yield [x, *ret] + async with self.lck: + for x in range(38): + ret = await self.scan_port(x) + if ret: + yield [x, *ret] diff --git a/custom_components/mega/light.py b/custom_components/mega/light.py index a8a6da7..c038d54 100644 --- a/custom_components/mega/light.py +++ b/custom_components/mega/light.py @@ -1,4 +1,5 @@ """Platform for light integration.""" +import asyncio import logging import voluptuous as vol @@ -77,11 +78,15 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn mid = config_entry.data[CONF_ID] hub: MegaD = hass.data['mega'][mid] devices = [] - async for port, pty, m in hub.scan_ports(): - if pty == "1" and m in ['0', '1']: - light = MegaLight(mega_id=mid, port=port, dimmer=m == '1') - devices.append(light) - async_add_devices(devices) + + async def scan_ports(): + async for port, pty, m in hub.scan_ports(): + if pty == "1" and m in ['0', '1']: + light = MegaLight(mega_id=mid, port=port, dimmer=m == '1') + devices.append(light) + async_add_devices(devices) + + asyncio.create_task(scan_ports()) class MegaLight(LightEntity, BaseMegaEntity): diff --git a/custom_components/mega/sensor.py b/custom_components/mega/sensor.py index dcac222..e13a654 100644 --- a/custom_components/mega/sensor.py +++ b/custom_components/mega/sensor.py @@ -1,4 +1,5 @@ """Platform for light integration.""" +import asyncio import logging import voluptuous as vol @@ -85,30 +86,33 @@ async def async_setup_entry(hass: HomeAssistant, config_entry: ConfigEntry, asyn mid = config_entry.data[CONF_ID] hub: MegaD = hass.data['mega'][mid] devices = [] - async for port, pty, m in hub.scan_ports(): - if pty == "3": - values = await hub.get_port(port, get_value=True) - lg.debug(f'values: %s', values) - if values is None: - continue - if isinstance(values, str) and TEMP_PATT.search(values): - values = {TEMP: values} - elif not isinstance(values, dict): - values = {None: values} - for key in values: - hub.lg.debug(f'add sensor {W1}:{key}') - sensor = _make_entity( - mid=mid, - port=port, - conf={ - CONF_TYPE: W1, - CONF_KEY: key, - }) - devices.append(sensor) - hub.sensors.append(sensor) - async_add_devices(devices) + async def scan(): + async for port, pty, m in hub.scan_ports(): + if pty == "3": + values = await hub.get_port(port) + lg.debug(f'values: %s', values) + if values is None: + continue + if isinstance(values, str) and TEMP_PATT.search(values): + values = {TEMP: values} + elif not isinstance(values, dict): + values = {None: values} + for key in values: + hub.lg.debug(f'add sensor {W1}:{key}') + sensor = _make_entity( + mid=mid, + port=port, + conf={ + CONF_TYPE: W1, + CONF_KEY: key, + }) + devices.append(sensor) + hub.sensors.append(sensor) + async_add_devices(devices) + + asyncio.create_task(scan()) class Mega1WSensor(BaseMegaEntity):