2021-09-14 09:53:37 +02:00
|
|
|
import asyncio
|
|
|
|
import logging
|
|
|
|
from datetime import datetime
|
|
|
|
from typing import Optional
|
|
|
|
|
|
|
|
from aioesphomeapi import APIClient, ReconnectLogic, APIConnectionError, LogLevel
|
|
|
|
import zeroconf
|
|
|
|
|
|
|
|
from esphome.const import CONF_KEY, CONF_PORT, CONF_PASSWORD, __version__
|
|
|
|
from esphome.util import safe_print
|
|
|
|
from . import CONF_ENCRYPTION
|
|
|
|
|
|
|
|
_LOGGER = logging.getLogger(__name__)
|
|
|
|
|
|
|
|
|
|
|
|
async def async_run_logs(config, address):
|
|
|
|
conf = config["api"]
|
2021-09-15 08:48:27 +02:00
|
|
|
port: int = int(conf[CONF_PORT])
|
2021-09-14 09:53:37 +02:00
|
|
|
password: str = conf[CONF_PASSWORD]
|
|
|
|
noise_psk: Optional[str] = None
|
|
|
|
if CONF_ENCRYPTION in conf:
|
|
|
|
noise_psk = conf[CONF_ENCRYPTION][CONF_KEY]
|
|
|
|
_LOGGER.info("Starting log output from %s using esphome API", address)
|
|
|
|
cli = APIClient(
|
|
|
|
address,
|
|
|
|
port,
|
|
|
|
password,
|
|
|
|
client_info=f"ESPHome Logs {__version__}",
|
|
|
|
noise_psk=noise_psk,
|
|
|
|
)
|
|
|
|
first_connect = True
|
|
|
|
|
|
|
|
def on_log(msg):
|
|
|
|
time_ = datetime.now().time().strftime("[%H:%M:%S]")
|
|
|
|
text = msg.message.decode("utf8", "backslashreplace")
|
|
|
|
safe_print(time_ + text)
|
|
|
|
|
|
|
|
async def on_connect():
|
|
|
|
nonlocal first_connect
|
|
|
|
try:
|
|
|
|
await cli.subscribe_logs(
|
|
|
|
on_log,
|
|
|
|
log_level=LogLevel.LOG_LEVEL_VERY_VERBOSE,
|
|
|
|
dump_config=first_connect,
|
|
|
|
)
|
|
|
|
first_connect = False
|
|
|
|
except APIConnectionError:
|
|
|
|
cli.disconnect()
|
|
|
|
|
2023-07-04 02:57:44 +02:00
|
|
|
async def on_disconnect(expected_disconnect: bool) -> None:
|
2021-09-14 09:53:37 +02:00
|
|
|
_LOGGER.warning("Disconnected from API")
|
|
|
|
|
|
|
|
zc = zeroconf.Zeroconf()
|
|
|
|
reconnect = ReconnectLogic(
|
|
|
|
client=cli,
|
|
|
|
on_connect=on_connect,
|
|
|
|
on_disconnect=on_disconnect,
|
|
|
|
zeroconf_instance=zc,
|
|
|
|
)
|
|
|
|
await reconnect.start()
|
|
|
|
|
|
|
|
try:
|
|
|
|
while True:
|
|
|
|
await asyncio.sleep(60)
|
|
|
|
except KeyboardInterrupt:
|
|
|
|
await reconnect.stop()
|
|
|
|
zc.close()
|
|
|
|
|
|
|
|
|
|
|
|
def run_logs(config, address):
|
|
|
|
asyncio.run(async_run_logs(config, address))
|