diff --git a/kasa/cli/listen.py b/kasa/cli/listen.py index 3dcf80f6..b50dbbfe 100644 --- a/kasa/cli/listen.py +++ b/kasa/cli/listen.py @@ -1,7 +1,7 @@ -"""Module for cli light control commands.""" +"""Module for cli listen commands.""" import asyncio -import sys +from contextlib import suppress from typing import cast import asyncclick as click @@ -15,12 +15,12 @@ from kasa.eventtype import EventType from .common import echo, error, pass_dev_or_child -async def aioinput(string: str): +async def wait_on_keyboard_interrupt(msg: str): """Non loop blocking get input.""" - loop = asyncio.get_event_loop() - await loop.run_in_executor(None, lambda s=string: sys.stdout.write(s + " ")) # type: ignore[misc] + echo(msg + ", press Ctrl-C to cancel\n") - return await loop.run_in_executor(None, sys.stdin.readline) + with suppress(asyncio.CancelledError): + await asyncio.Event().wait() @click.command() @@ -68,15 +68,15 @@ async def listen( listen_ip: str | None, event_types: list[EventType] | None, ) -> None: - """Commands to control light settings.""" + """Listen for events like motion, triggers or alarms.""" try: import onvif # type: ignore[import-untyped] # noqa: F401 except ImportError: - error("python-kasa must be installed with [onvif] extra for listen.") + error("python-kasa must be installed with onvif extra for listen.") - from kasa.smartcam.modules.listen import EventType, Listen + from kasa.smartcam.modules.onviflisten import OnvifListen - listen: Listen = cast(Listen, dev.modules.get(Listen._module_name())) + listen: OnvifListen = cast(OnvifListen, dev.modules.get(OnvifListen._module_name())) if not listen: error(f"Device {dev.host} does not support listening for events.") @@ -92,7 +92,9 @@ async def listen( event_types=event_types, ) - await aioinput("Listening, press enter to cancel\n") + msg = f"Listening for events on {listen.listening_address}" - echo("Stopping listener") + await wait_on_keyboard_interrupt(msg) + + echo("\nStopping listener") await listen.stop() diff --git a/kasa/cli/main.py b/kasa/cli/main.py index a121a482..58d96764 100755 --- a/kasa/cli/main.py +++ b/kasa/cli/main.py @@ -253,7 +253,9 @@ async def cli( if target != DEFAULT_TARGET and host: error("--target is not a valid option for single host discovery") - logging_config: dict[str, Any] = {"level": logging.WARNING} + logging_config: dict[str, Any] = { + "level": logging.DEBUG if debug > 0 else logging.INFO + } try: from rich.logging import RichHandler @@ -268,7 +270,6 @@ async def cli( # The configuration should be converted to use dictConfig, # but this keeps mypy happy for now logging.basicConfig(**logging_config) # type: ignore - logging.getLogger("kasa").setLevel(logging.DEBUG if debug > 0 else logging.INFO) if ctx.invoked_subcommand == "discover": return diff --git a/kasa/smartcam/modules/listen.py b/kasa/smartcam/modules/onviflisten.py similarity index 97% rename from kasa/smartcam/modules/listen.py rename to kasa/smartcam/modules/onviflisten.py index d37586fb..2f657afa 100644 --- a/kasa/smartcam/modules/listen.py +++ b/kasa/smartcam/modules/onviflisten.py @@ -20,6 +20,8 @@ from ...exceptions import KasaException from ..smartcammodule import SmartCamModule _LOGGER = logging.getLogger(__name__) +logging.getLogger("aiohttp").setLevel(logging.WARNING) +logging.getLogger("httpx").setLevel(logging.WARNING) DEFAULT_LISTEN_PORT = 28002 @@ -31,7 +33,7 @@ TOPIC_EVENT_TYPE = { } -class Listen(SmartCamModule): +class OnvifListen(SmartCamModule): """Implementation of lens mask module.""" manager: NotificationManager diff --git a/kasa/smartcam/smartcamdevice.py b/kasa/smartcam/smartcamdevice.py index 15eb8c19..a4715b80 100644 --- a/kasa/smartcam/smartcamdevice.py +++ b/kasa/smartcam/smartcamdevice.py @@ -133,9 +133,11 @@ class SmartCamDevice(SmartDevice): import onvif # type: ignore[import-untyped] # noqa: F401 except ImportError: return - from .modules.listen import Listen + from .modules.onviflisten import OnvifListen - self._modules[Listen._module_name()] = Listen(self, Listen._module_name()) + self._modules[OnvifListen._module_name()] = OnvifListen( + self, OnvifListen._module_name() + ) async def _initialize_modules(self) -> None: """Initialize modules based on component negotiation response."""