74 lines
2.9 KiB
Python
74 lines
2.9 KiB
Python
|
import asyncio
|
||
|
import logging
|
||
|
from homeassistant.const import EVENT_HOMEASSISTANT_STOP
|
||
|
|
||
|
|
||
|
_LOGGER = logging.getLogger(__name__)
|
||
|
|
||
|
|
||
|
class ReconnectingClient:
|
||
|
|
||
|
def __init__(self, hass, host, port, connection_name, receive_line_callback, connection_status_changed_callback):
|
||
|
self.connected = False
|
||
|
self.reconnect_time_start = 1
|
||
|
self.reconnect_time_max = 60
|
||
|
self.reconnect_time = self.reconnect_time_start
|
||
|
self.hass = hass
|
||
|
self._host = host
|
||
|
self._port = port
|
||
|
self._receive_line_callback = receive_line_callback
|
||
|
self._connection_status_changed_callback = connection_status_changed_callback
|
||
|
self._run = False
|
||
|
self._writer = None
|
||
|
self._connection_last_state = 'UNKNOWN'
|
||
|
self._connection_name = connection_name
|
||
|
|
||
|
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
|
||
|
|
||
|
def write_line(self, line):
|
||
|
if self._writer:
|
||
|
line += '\n'
|
||
|
self._writer.write(line.encode())
|
||
|
|
||
|
async def _connection(self):
|
||
|
try:
|
||
|
reader, writer = await asyncio.open_connection(self._host, self._port)
|
||
|
_LOGGER.info("Connected to {} {}:{}".format(self._connection_name, self._host, self._port))
|
||
|
self._connection_last_state = 'CONNECTED'
|
||
|
|
||
|
self._writer = writer
|
||
|
self.connected = True
|
||
|
await self._connection_status_changed_callback('connected')
|
||
|
|
||
|
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:
|
||
|
raise OSError("Disconnect")
|
||
|
line = line.decode()
|
||
|
_LOGGER.debug("{} received line: {}".format(self._connection_name, line))
|
||
|
await self._receive_line_callback(line)
|
||
|
except OSError:
|
||
|
if self._connection_last_state != 'FAILED':
|
||
|
notification_text = "{} connection to {}:{} failed".format(self._connection_name,self._host, self._port)
|
||
|
self.hass.components.persistent_notification.async_create(notification_text, title="No connection")
|
||
|
_LOGGER.error("Connection to {} failed {}:{}".format(self._connection_name, self._host, self._port))
|
||
|
await self._connection_status_changed_callback('disconnected')
|
||
|
self._connection_last_state = 'FAILED'
|
||
|
|
||
|
self.connected = False
|
||
|
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())
|