Factored Client code out & implemented LIRC network listener

This commit is contained in:
Martin Bauer
2019-06-19 19:22:06 +02:00
parent 20f43f4294
commit 1a746d1438
9 changed files with 322 additions and 70 deletions

View File

@@ -2,10 +2,10 @@
import logging
import voluptuous as vol
import asyncio
from collections import defaultdict
import homeassistant.helpers.config_validation as cv
from homeassistant.const import CONF_HOST, CONF_PORT, EVENT_HOMEASSISTANT_STOP
from homeassistant.const import CONF_HOST, CONF_PORT
from ..reconnecting_client import ReconnectingClient
_LOGGER = logging.getLogger(__name__)
CONF_CUL_DEVICE_NAME = 'cul_device_name'
@@ -23,28 +23,20 @@ CONFIG_SCHEMA = vol.Schema({
async def async_setup(hass, config):
connection = FhemConnection(hass, config)
connection = FhemConnection(hass, config[DOMAIN])
hass.data[DATA_FHEM] = connection
await connection.start()
return True
class FhemConnection:
class FhemConnection(ReconnectingClient):
def __init__(self, hass, config):
self.hass = hass
self._host = config[DOMAIN][CONF_HOST]
self._port = config[DOMAIN][CONF_PORT]
self._cul_device_name = config[DOMAIN][CONF_CUL_DEVICE_NAME]
self.connected = False
self.reconnect_time_start = 1
self.reconnect_time_max = 60
self.reconnect_time = self.reconnect_time_start
super().__init__(hass, config[CONF_HOST], config[CONF_PORT], "FHEM",
receive_line_callback=self._process_line,
connection_status_changed_callback=self._update_all_devices)
self._cul_device_name = config[CONF_CUL_DEVICE_NAME]
self._devices = defaultdict(list)
self._run = False
self._writer = None
self._connection_last_state = 'UNKNOWN'
def register_device(self, id, d):
self._devices[id].append(d)
@@ -53,56 +45,11 @@ class FhemConnection:
"displayattr .*\n".encode(),
])
async def _update_all_devices(self):
async def _update_all_devices(self, _):
for device_list in self._devices.values():
for device in device_list:
await device.async_update_ha_state()
async def start(self):
self._run = True
self.hass.bus.async_listen_once(EVENT_HOMEASSISTANT_STOP, self.stop)
self.hass.loop.create_task(self._connection())
async def stop(self):
self._run = False
self.connected = False
async def _connection(self):
try:
reader, writer = await asyncio.open_connection(self._host, self._port)
_LOGGER.info("Connected to FHEM {}:{}".format(self._host, self._port))
self._connection_last_state = 'CONNECTED'
self._writer = writer
self.connected = True
await self._update_all_devices()
self.reconnect_time = self.reconnect_time_start
writer.writelines([
"displayattr .*\n".encode(),
"inform on\n".encode(),
])
while self._run:
line = await reader.readline()
if not line:
_LOGGER.warning("FHEM disconnected: {}".format(line))
raise OSError("Disconnect")
line = line.decode()
_LOGGER.debug("FHEM received line: {}".format(line))
await self._process_line(line)
except OSError:
if self._connection_last_state != 'FAILED':
self.hass.components.persistent_notification.async_create("FHEM connection failed",
title="No FHEM connection")
_LOGGER.error("Connection to FHEM failed {}:{}".format(self._host, self._port))
self._connection_last_state = 'FAILED'
self.connected = False
await self._update_all_devices()
await asyncio.sleep(self.reconnect_time)
self.reconnect_time = min(2 * self.reconnect_time, self.reconnect_time_max)
self.hass.loop.create_task(self._connection())
async def _process_line(self, line):
if line.startswith(self._cul_device_name + " "): # Status update message
_, device_name, command = line.split(" ", 2)
@@ -127,7 +74,7 @@ class FhemConnection:
:param arguments: string or list of strings containing command parameters
"""
arguments = " ".join([str(a) for a in arguments])
self._writer.write("set {} {}\n".format(id, arguments).encode())
self.write_line("set {} {}\n".format(id, arguments))
def device_error_reporting(hass, received_line, component_type, component_name):