"""Use aiounifi as a CLI.""" import argparse import asyncio from asyncio.timeouts import timeout import logging from ssl import SSLContext import aiohttp import aiounifi from aiounifi.controller import Controller from aiounifi.models.configuration import Configuration LOGGER = logging.getLogger(__name__) async def unifi_controller( host: str, username: str, password: str, port: int, site: str, session: aiohttp.ClientSession, ssl_context: SSLContext | None = None, ) -> Controller | None: """Set up UniFi controller and verify credentials.""" controller = Controller( Configuration( session, host, username=username, password=password, port=port, site=site, ssl_context=ssl_context if ssl_context is not None else False, ) ) try: async with timeout(10): await controller.login() return controller except aiounifi.LoginRequired: LOGGER.warning("Connected to UniFi at %s but couldn't log in", host) except aiounifi.Unauthorized: LOGGER.warning("Connected to UniFi at %s but not registered", host) except (TimeoutError, aiounifi.RequestError): LOGGER.exception("Error connecting to the UniFi controller at %s", host) except aiounifi.AiounifiException: LOGGER.exception("Unknown UniFi communication error occurred") return None async def main( host: str, username: str, password: str, port: int, site: str, ssl_context: SSLContext | None = None, ) -> None: """CLI method for library.""" LOGGER.info("Starting aioUniFi") websession = aiohttp.ClientSession(cookie_jar=aiohttp.CookieJar(unsafe=True)) controller = await unifi_controller( host=host, username=username, password=password, port=port, site=site, session=websession, ssl_context=ssl_context, ) if not controller: LOGGER.error("Couldn't connect to UniFi controller") await websession.close() return await asyncio.gather( *( controller.clients.update(), controller.clients_all.update(), controller.devices.update(), controller.dpi_apps.update(), controller.dpi_groups.update(), controller.port_forwarding.update(), controller.sites.update(), controller.system_information.update(), controller.traffic_rules.update(), controller.traffic_routes.update(), controller.vouchers.update(), controller.wlans.update(), ), return_exceptions=True, ) ws_task = asyncio.create_task(controller.start_websocket()) try: while True: await asyncio.sleep(1) except asyncio.CancelledError: pass finally: ws_task.cancel() await websession.close() if __name__ == "__main__": parser = argparse.ArgumentParser() parser.add_argument("host", type=str) parser.add_argument("username", type=str) parser.add_argument("password", type=str) parser.add_argument("-p", "--port", type=int, default=8443) parser.add_argument("-s", "--site", type=str, default="default") parser.add_argument("-D", "--debug", action="store_true") args = parser.parse_args() LOG_LEVEL = logging.INFO if args.debug: LOG_LEVEL = logging.DEBUG logging.basicConfig(format="%(message)s", level=LOG_LEVEL) LOGGER.info( "%s, %s, %s, %i, %s", args.host, args.username, args.password, args.port, args.site, ) try: asyncio.run( main( host=args.host, username=args.username, password=args.password, port=args.port, site=args.site, ) ) except KeyboardInterrupt: LOGGER.info("Keyboard interrupt")