From 01f08aafce5ac1310f0277079e96ff4d8cb17f57 Mon Sep 17 00:00:00 2001 From: Harry Tung Date: Wed, 17 Jul 2024 18:43:05 -0700 Subject: [PATCH 01/12] Added option to completely skip rtsp discovery in autodiscover --- src/framegrab/cli/autodiscover.py | 2 +- src/framegrab/grabber.py | 33 +++++++++++++++++-------------- 2 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/framegrab/cli/autodiscover.py b/src/framegrab/cli/autodiscover.py index becd236..27dc13c 100644 --- a/src/framegrab/cli/autodiscover.py +++ b/src/framegrab/cli/autodiscover.py @@ -23,7 +23,7 @@ @click.option( "--rtsp_discover_modes", type=click.Choice(PREVIEW_RTSP_COMMAND_CHOICES, case_sensitive=False), - default="light", + default="disable", show_default=True, ) def autodiscover(preview: str, rtsp_discover_modes: str = "light"): diff --git a/src/framegrab/grabber.py b/src/framegrab/grabber.py index b8736ba..d195b8c 100644 --- a/src/framegrab/grabber.py +++ b/src/framegrab/grabber.py @@ -274,7 +274,7 @@ def create_grabber(config: dict, autogenerate_name: bool = True, warmup_delay: f @staticmethod def autodiscover( - warmup_delay: float = 1.0, rtsp_discover_modes: AutodiscoverModes = AutodiscoverModes.light + warmup_delay: float = 1.0, rtsp_discover_modes: Union[AutodiscoverModes, None] = None ) -> dict: """Autodiscovers cameras and returns a dictionary of FrameGrabber objects @@ -290,7 +290,8 @@ def autodiscover( light: Only try first two usernames and passwords ("admin:admin" and no username/password). complete_fast: Try the entire DEFAULT_CREDENTIALS without delays in between. complete_slow: Try the entire DEFAULT_CREDENTIALS with a delay of 1 seconds in between. - Defaults to AutodiscoverModes.light. + None: Will not search for rtsp streams + Defaults to None. """ autodiscoverable_input_types = ( InputTypes.REALSENSE, @@ -304,20 +305,22 @@ def autodiscover( for input_type in autodiscoverable_input_types: logger.info(f"Autodiscovering {input_type} cameras...") + # If the input type is RTSP and rtsp_discover_modes is provided, use RTSPDiscovery to find the cameras if input_type == InputTypes.RTSP: - onvif_devices = RTSPDiscovery.discover_onvif_devices(auto_discover_modes=rtsp_discover_modes) - for device in onvif_devices: - for index, rtsp_url in enumerate(device.rtsp_urls): - grabber = FrameGrabber.create_grabber( - { - "input_type": input_type, - "id": {"rtsp_url": rtsp_url}, - "name": f"RTSP Camera - {device.ip} - {index}", - }, - autogenerate_name=False, - warmup_delay=0, - ) - grabber_list.append(grabber) + if rtsp_discover_modes is not None: + onvif_devices = RTSPDiscovery.discover_onvif_devices(auto_discover_modes=rtsp_discover_modes) + for device in onvif_devices: + for index, rtsp_url in enumerate(device.rtsp_urls): + grabber = FrameGrabber.create_grabber( + { + "input_type": input_type, + "id": {"rtsp_url": rtsp_url}, + "name": f"RTSP Camera - {device.ip} - {index}", + }, + autogenerate_name=False, + warmup_delay=0, + ) + grabber_list.append(grabber) continue for _ in range( From c95bc228133201f6c06d0df5ae3495659e65ad06 Mon Sep 17 00:00:00 2001 From: Auto-format Bot Date: Thu, 18 Jul 2024 01:51:48 +0000 Subject: [PATCH 02/12] Automatically reformatting code with black and isort --- src/framegrab/grabber.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/framegrab/grabber.py b/src/framegrab/grabber.py index d195b8c..6c65eb5 100644 --- a/src/framegrab/grabber.py +++ b/src/framegrab/grabber.py @@ -273,9 +273,7 @@ def create_grabber(config: dict, autogenerate_name: bool = True, warmup_delay: f return grabber @staticmethod - def autodiscover( - warmup_delay: float = 1.0, rtsp_discover_modes: Union[AutodiscoverModes, None] = None - ) -> dict: + def autodiscover(warmup_delay: float = 1.0, rtsp_discover_modes: Union[AutodiscoverModes, None] = None) -> dict: """Autodiscovers cameras and returns a dictionary of FrameGrabber objects warmup_delay (float, optional): The number of seconds to wait after creating the grabbers. USB From cd8f87f2802999e97ae9138723afd4e944b56efb Mon Sep 17 00:00:00 2001 From: Harry Tung Date: Wed, 17 Jul 2024 18:55:18 -0700 Subject: [PATCH 03/12] Bumped version --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 17ed964..f5dac64 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "framegrab" -version = "0.5.4" +version = "0.5.5" description = "Easily grab frames from cameras or streams" authors = ["Groundlight "] license = "MIT" From d59cfa52479eca653f0aff4b6985ff10d90f6bd4 Mon Sep 17 00:00:00 2001 From: Harry Tung Date: Thu, 18 Jul 2024 11:32:31 -0700 Subject: [PATCH 04/12] Changed AutoDiscoverModes name --- src/framegrab/__init__.py | 4 ++-- src/framegrab/cli/autodiscover.py | 10 +++++----- src/framegrab/cli/clitools.py | 4 ++-- src/framegrab/grabber.py | 10 +++++----- src/framegrab/rtsp_discovery.py | 20 ++++++++++---------- test/test_rtsp_discovery.py | 4 ++-- 6 files changed, 26 insertions(+), 26 deletions(-) diff --git a/src/framegrab/__init__.py b/src/framegrab/__init__.py index a2f8870..844f249 100644 --- a/src/framegrab/__init__.py +++ b/src/framegrab/__init__.py @@ -2,7 +2,7 @@ from .exceptions import GrabError from .grabber import FrameGrabber from .motion import MotionDetector -from .rtsp_discovery import AutodiscoverModes, ONVIFDeviceInfo, RTSPDiscovery +from .rtsp_discovery import AutodiscoverMode, ONVIFDeviceInfo, RTSPDiscovery try: import importlib.metadata @@ -20,6 +20,6 @@ "MotionDetector", "GrabError" "RTSPDiscovery", "ONVIFDeviceInfo", - "AutodiscoverModes", + "AutodiscoverMode", "preview_image", ] diff --git a/src/framegrab/cli/autodiscover.py b/src/framegrab/cli/autodiscover.py index 27dc13c..9fb2b8b 100644 --- a/src/framegrab/cli/autodiscover.py +++ b/src/framegrab/cli/autodiscover.py @@ -10,7 +10,7 @@ PREVIEW_RTSP_COMMAND_CHOICES, preview_image, ) -from framegrab.rtsp_discovery import AutodiscoverModes +from framegrab.rtsp_discovery import AutodiscoverMode @click.command() @@ -21,17 +21,17 @@ show_default=True, ) @click.option( - "--rtsp_discover_modes", + "--rtsp_discover_mode", type=click.Choice(PREVIEW_RTSP_COMMAND_CHOICES, case_sensitive=False), - default="disable", + default="light", show_default=True, ) -def autodiscover(preview: str, rtsp_discover_modes: str = "light"): +def autodiscover(preview: str, rtsp_discover_mode: str = "light"): """Automatically discover cameras connected to the current host (e.g. USB).""" # Print message to stderr click.echo("Discovering cameras...", err=True) - grabbers = FrameGrabber.autodiscover(rtsp_discover_modes=rtsp_discover_modes) + grabbers = FrameGrabber.autodiscover(rtsp_discover_mode=rtsp_discover_mode) yaml_config = { "image_sources": [], diff --git a/src/framegrab/cli/clitools.py b/src/framegrab/cli/clitools.py index 882b17a..d11dabe 100644 --- a/src/framegrab/cli/clitools.py +++ b/src/framegrab/cli/clitools.py @@ -5,7 +5,7 @@ from imgcat import imgcat from PIL import Image -from framegrab.rtsp_discovery import AutodiscoverModes +from framegrab.rtsp_discovery import AutodiscoverMode def imgcat_preview(name: str, frame): @@ -46,7 +46,7 @@ def null_preview(name: str, frame): } PREVIEW_COMMAND_CHOICES = list(_PREVIEW_COMMANDS.keys()) -PREVIEW_RTSP_COMMAND_CHOICES = [mode.value for mode in AutodiscoverModes] +PREVIEW_RTSP_COMMAND_CHOICES = [mode.value for mode in AutodiscoverMode] def preview_image(frame, title: str, output_type: str): diff --git a/src/framegrab/grabber.py b/src/framegrab/grabber.py index 6c65eb5..9c21b03 100644 --- a/src/framegrab/grabber.py +++ b/src/framegrab/grabber.py @@ -14,7 +14,7 @@ import yaml from .exceptions import GrabError -from .rtsp_discovery import AutodiscoverModes, RTSPDiscovery +from .rtsp_discovery import AutodiscoverMode, RTSPDiscovery from .unavailable_module import UnavailableModule logger = logging.getLogger(__name__) @@ -273,7 +273,7 @@ def create_grabber(config: dict, autogenerate_name: bool = True, warmup_delay: f return grabber @staticmethod - def autodiscover(warmup_delay: float = 1.0, rtsp_discover_modes: Union[AutodiscoverModes, None] = None) -> dict: + def autodiscover(warmup_delay: float = 1.0, rtsp_discover_mode: Union[AutodiscoverMode, None] = None) -> dict: """Autodiscovers cameras and returns a dictionary of FrameGrabber objects warmup_delay (float, optional): The number of seconds to wait after creating the grabbers. USB @@ -281,7 +281,7 @@ def autodiscover(warmup_delay: float = 1.0, rtsp_discover_modes: Union[Autodisco might result in dark or blurry images. Defaults to 1.0. Only happens if there are any generic_usb cameras in the config list. - rtsp_discover_modes (AutodiscoverModes, optional): Options to try different default credentials + rtsp_discover_mode (AutodiscoverMode, optional): Options to try different default credentials stored in DEFAULT_CREDENTIALS for RTSP cameras. Consists of four options: disable: Disable guessing camera credentials. @@ -305,8 +305,8 @@ def autodiscover(warmup_delay: float = 1.0, rtsp_discover_modes: Union[Autodisco # If the input type is RTSP and rtsp_discover_modes is provided, use RTSPDiscovery to find the cameras if input_type == InputTypes.RTSP: - if rtsp_discover_modes is not None: - onvif_devices = RTSPDiscovery.discover_onvif_devices(auto_discover_modes=rtsp_discover_modes) + if rtsp_discover_mode is not None: + onvif_devices = RTSPDiscovery.discover_onvif_devices(auto_discover_mode=rtsp_discover_mode) for device in onvif_devices: for index, rtsp_url in enumerate(device.rtsp_urls): grabber = FrameGrabber.create_grabber( diff --git a/src/framegrab/rtsp_discovery.py b/src/framegrab/rtsp_discovery.py index a1a65d3..70b11b6 100644 --- a/src/framegrab/rtsp_discovery.py +++ b/src/framegrab/rtsp_discovery.py @@ -27,7 +27,7 @@ ] -class AutodiscoverModes(str, Enum): +class AutodiscoverMode(str, Enum): """ Enum for camera discovery modes. Options to try different default credentials stored in DEFAULT_CREDENTIALS. Consists of four options: @@ -67,13 +67,13 @@ class RTSPDiscovery: @staticmethod def discover_onvif_devices( - auto_discover_modes: AutodiscoverModes = AutodiscoverModes.disable, + auto_discover_mode: AutodiscoverMode = AutodiscoverMode.disable, ) -> List[ONVIFDeviceInfo]: """ Uses WSDiscovery to find ONVIF supported devices. Parameters: - auto_discover_modes (AutodiscoverModes, optional): Options to try different default credentials stored in DEFAULT_CREDENTIALS. + auto_discover_mode (AutodiscoverMode, optional): Options to try different default credentials stored in DEFAULT_CREDENTIALS. Consists of four options: disable: Disable guessing camera credentials. light: Only try first two usernames and passwords ("admin:admin" and no username/password). @@ -100,8 +100,8 @@ def discover_onvif_devices( logger.debug(f"Found ONVIF service at {xaddr}") device_ip = ONVIFDeviceInfo(ip=ip, port=port, username="", password="", xaddr=xaddr, rtsp_urls=[]) - if auto_discover_modes is not AutodiscoverModes.disable: - RTSPDiscovery._try_logins(device=device_ip, auto_discover_modes=auto_discover_modes) + if auto_discover_mode is not AutodiscoverMode.disable: + RTSPDiscovery._try_logins(device=device_ip, auto_discover_mode=auto_discover_mode) device_ips.append(device_ip) wsd.stop() @@ -151,13 +151,13 @@ def generate_rtsp_urls(device: ONVIFDeviceInfo) -> List[str]: device.rtsp_urls = rtsp_urls return rtsp_urls - def _try_logins(device: ONVIFDeviceInfo, auto_discover_modes: AutodiscoverModes) -> bool: + def _try_logins(device: ONVIFDeviceInfo, auto_discover_mode: AutodiscoverMode) -> bool: """ Fetch RTSP URLs from an ONVIF supported device, given a username/password. Parameters: device (ONVIFDeviceInfo): Pydantic Model that stores information about camera RTSP address, port number, username, and password. - auto_discover_modes (AutodiscoverModes | None, optional): Options to try different default credentials stored in DEFAULT_CREDENTIALS. + auto_discover_mode (AutodiscoverMode | None, optional): Options to try different default credentials stored in DEFAULT_CREDENTIALS. Consists of four options: disable: Disable guessing camera credentials. light: Only try first two usernames and passwords ("admin:admin" and no username/password). @@ -170,10 +170,10 @@ def _try_logins(device: ONVIFDeviceInfo, auto_discover_modes: AutodiscoverModes) credentials = DEFAULT_CREDENTIALS - if auto_discover_modes == AutodiscoverModes.disable: + if auto_discover_mode == AutodiscoverMode.disable: return False - if auto_discover_modes == AutodiscoverModes.light: + if auto_discover_mode == AutodiscoverMode.light: credentials = DEFAULT_CREDENTIALS[:2] for username, password in credentials: @@ -187,7 +187,7 @@ def _try_logins(device: ONVIFDeviceInfo, auto_discover_modes: AutodiscoverModes) logger.debug(f"RTSP URL fetched successfully with {username}:{password} for device IP {device.ip}") return True - if auto_discover_modes == AutodiscoverModes.complete_slow: + if auto_discover_mode == AutodiscoverMode.complete_slow: time.sleep(1) # Return False when there are no correct credentials diff --git a/test/test_rtsp_discovery.py b/test/test_rtsp_discovery.py index 4957d94..448b28b 100644 --- a/test/test_rtsp_discovery.py +++ b/test/test_rtsp_discovery.py @@ -2,7 +2,7 @@ from wsdiscovery.service import Service from unittest.mock import patch -from framegrab.rtsp_discovery import RTSPDiscovery, ONVIFDeviceInfo, AutodiscoverModes +from framegrab.rtsp_discovery import RTSPDiscovery, ONVIFDeviceInfo, AutodiscoverMode class TestRTSPDiscovery(unittest.TestCase): @@ -27,5 +27,5 @@ def test_generate_rtsp_urls(self): def test_try_logins(self): device = ONVIFDeviceInfo(ip="0") - assert False == RTSPDiscovery._try_logins(device=device, auto_discover_modes=AutodiscoverModes.complete_fast) + assert False == RTSPDiscovery._try_logins(device=device, auto_discover_mode=AutodiscoverMode.complete_fast) assert device.rtsp_urls == [] From 712338325a3a22023ea807ac5879eefa833a09d8 Mon Sep 17 00:00:00 2001 From: Harry Tung Date: Thu, 18 Jul 2024 12:01:34 -0700 Subject: [PATCH 05/12] Modified AutodiscoverMode to have another option to completely disable discovery --- src/framegrab/cli/autodiscover.py | 4 ++-- src/framegrab/grabber.py | 11 ++++++----- src/framegrab/rtsp_discovery.py | 31 ++++++++++++++++++++----------- 3 files changed, 28 insertions(+), 18 deletions(-) diff --git a/src/framegrab/cli/autodiscover.py b/src/framegrab/cli/autodiscover.py index 9fb2b8b..1fb512b 100644 --- a/src/framegrab/cli/autodiscover.py +++ b/src/framegrab/cli/autodiscover.py @@ -23,10 +23,10 @@ @click.option( "--rtsp_discover_mode", type=click.Choice(PREVIEW_RTSP_COMMAND_CHOICES, case_sensitive=False), - default="light", + default="disable", show_default=True, ) -def autodiscover(preview: str, rtsp_discover_mode: str = "light"): +def autodiscover(preview: str, rtsp_discover_mode: str = "disable"): """Automatically discover cameras connected to the current host (e.g. USB).""" # Print message to stderr click.echo("Discovering cameras...", err=True) diff --git a/src/framegrab/grabber.py b/src/framegrab/grabber.py index 9c21b03..8774682 100644 --- a/src/framegrab/grabber.py +++ b/src/framegrab/grabber.py @@ -273,7 +273,7 @@ def create_grabber(config: dict, autogenerate_name: bool = True, warmup_delay: f return grabber @staticmethod - def autodiscover(warmup_delay: float = 1.0, rtsp_discover_mode: Union[AutodiscoverMode, None] = None) -> dict: + def autodiscover(warmup_delay: float = 1.0, rtsp_discover_mode: AutodiscoverMode = AutodiscoverMode.disable) -> dict: """Autodiscovers cameras and returns a dictionary of FrameGrabber objects warmup_delay (float, optional): The number of seconds to wait after creating the grabbers. USB @@ -283,13 +283,14 @@ def autodiscover(warmup_delay: float = 1.0, rtsp_discover_mode: Union[Autodiscov rtsp_discover_mode (AutodiscoverMode, optional): Options to try different default credentials stored in DEFAULT_CREDENTIALS for RTSP cameras. - Consists of four options: - disable: Disable guessing camera credentials. + Consists of five options: + disable: No discovery. + ip_only: Only discover the IP address of the camera. light: Only try first two usernames and passwords ("admin:admin" and no username/password). complete_fast: Try the entire DEFAULT_CREDENTIALS without delays in between. complete_slow: Try the entire DEFAULT_CREDENTIALS with a delay of 1 seconds in between. - None: Will not search for rtsp streams - Defaults to None. + Defaults to ip_only. + Defaults to disable. """ autodiscoverable_input_types = ( InputTypes.REALSENSE, diff --git a/src/framegrab/rtsp_discovery.py b/src/framegrab/rtsp_discovery.py index 70b11b6..f3191e1 100644 --- a/src/framegrab/rtsp_discovery.py +++ b/src/framegrab/rtsp_discovery.py @@ -30,14 +30,16 @@ class AutodiscoverMode(str, Enum): """ Enum for camera discovery modes. Options to try different default credentials stored in DEFAULT_CREDENTIALS. - Consists of four options: - disable: Disable guessing camera credentials. + Consists of five options: + disable: No discovery. + ip_only: Only discover the IP address of the camera. light: Only try first two usernames and passwords ("admin:admin" and no username/password). complete_fast: Try the entire DEFAULT_CREDENTIALS without delays in between. complete_slow: Try the entire DEFAULT_CREDENTIALS with a delay of 1 seconds in between. """ disable = "disable" + ip_only = "ip_only" light = "light" complete_fast = "complete_fast" complete_slow = "complete_slow" @@ -67,19 +69,20 @@ class RTSPDiscovery: @staticmethod def discover_onvif_devices( - auto_discover_mode: AutodiscoverMode = AutodiscoverMode.disable, + auto_discover_mode: AutodiscoverMode = AutodiscoverMode.ip_only, ) -> List[ONVIFDeviceInfo]: """ Uses WSDiscovery to find ONVIF supported devices. Parameters: auto_discover_mode (AutodiscoverMode, optional): Options to try different default credentials stored in DEFAULT_CREDENTIALS. - Consists of four options: - disable: Disable guessing camera credentials. + Consists of five options: + disable: No discovery. + ip_only: Only discover the IP address of the camera. light: Only try first two usernames and passwords ("admin:admin" and no username/password). complete_fast: Try the entire DEFAULT_CREDENTIALS without delays in between. complete_slow: Try the entire DEFAULT_CREDENTIALS with a delay of 1 seconds in between. - Defaults to disable. + Defaults to ip_only. Returns: List[ONVIFDeviceInfo]: A list of ONVIFDeviceInfos with IP address, port number, and ONVIF service address. @@ -87,6 +90,11 @@ def discover_onvif_devices( device_ips = [] logger.debug("Starting WSDiscovery for ONVIF devices") + + if auto_discover_mode == AutodiscoverMode.disable: + logger.debug("ONVIF device discovery disabled") + return device_ips + wsd = WSDiscovery() wsd.start() types = [QName("http://www.onvif.org/ver10/network/wsdl", "NetworkVideoTransmitter")] @@ -100,7 +108,7 @@ def discover_onvif_devices( logger.debug(f"Found ONVIF service at {xaddr}") device_ip = ONVIFDeviceInfo(ip=ip, port=port, username="", password="", xaddr=xaddr, rtsp_urls=[]) - if auto_discover_mode is not AutodiscoverMode.disable: + if auto_discover_mode is not AutodiscoverMode.ip_only: RTSPDiscovery._try_logins(device=device_ip, auto_discover_mode=auto_discover_mode) device_ips.append(device_ip) @@ -157,9 +165,10 @@ def _try_logins(device: ONVIFDeviceInfo, auto_discover_mode: AutodiscoverMode) - Parameters: device (ONVIFDeviceInfo): Pydantic Model that stores information about camera RTSP address, port number, username, and password. - auto_discover_mode (AutodiscoverMode | None, optional): Options to try different default credentials stored in DEFAULT_CREDENTIALS. - Consists of four options: - disable: Disable guessing camera credentials. + auto_discover_mode (AutodiscoverMode): Options to try different default credentials stored in DEFAULT_CREDENTIALS. + Consists of five options: + disable: No discovery. + ip_only: Only discover the IP address of the camera. light: Only try first two usernames and passwords ("admin:admin" and no username/password). complete_fast: Try the entire DEFAULT_CREDENTIALS without delays in between. complete_slow: Try the entire DEFAULT_CREDENTIALS with a delay of 1 seconds in between. @@ -170,7 +179,7 @@ def _try_logins(device: ONVIFDeviceInfo, auto_discover_mode: AutodiscoverMode) - credentials = DEFAULT_CREDENTIALS - if auto_discover_mode == AutodiscoverMode.disable: + if auto_discover_mode == AutodiscoverMode.ip_only or auto_discover_mode == AutodiscoverMode.disable: return False if auto_discover_mode == AutodiscoverMode.light: From e9e6528397bbc6f9ad277bf081a8f2481c2d22b3 Mon Sep 17 00:00:00 2001 From: Auto-format Bot Date: Thu, 18 Jul 2024 19:02:01 +0000 Subject: [PATCH 06/12] Automatically reformatting code with black and isort --- src/framegrab/grabber.py | 4 +++- src/framegrab/rtsp_discovery.py | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/framegrab/grabber.py b/src/framegrab/grabber.py index 8774682..0ab6ba9 100644 --- a/src/framegrab/grabber.py +++ b/src/framegrab/grabber.py @@ -273,7 +273,9 @@ def create_grabber(config: dict, autogenerate_name: bool = True, warmup_delay: f return grabber @staticmethod - def autodiscover(warmup_delay: float = 1.0, rtsp_discover_mode: AutodiscoverMode = AutodiscoverMode.disable) -> dict: + def autodiscover( + warmup_delay: float = 1.0, rtsp_discover_mode: AutodiscoverMode = AutodiscoverMode.disable + ) -> dict: """Autodiscovers cameras and returns a dictionary of FrameGrabber objects warmup_delay (float, optional): The number of seconds to wait after creating the grabbers. USB diff --git a/src/framegrab/rtsp_discovery.py b/src/framegrab/rtsp_discovery.py index f3191e1..c600ed8 100644 --- a/src/framegrab/rtsp_discovery.py +++ b/src/framegrab/rtsp_discovery.py @@ -90,11 +90,11 @@ def discover_onvif_devices( device_ips = [] logger.debug("Starting WSDiscovery for ONVIF devices") - + if auto_discover_mode == AutodiscoverMode.disable: logger.debug("ONVIF device discovery disabled") return device_ips - + wsd = WSDiscovery() wsd.start() types = [QName("http://www.onvif.org/ver10/network/wsdl", "NetworkVideoTransmitter")] From 2f201c62f960f20673b8f4321b6470d95da294a0 Mon Sep 17 00:00:00 2001 From: Harry Tung Date: Thu, 18 Jul 2024 12:11:49 -0700 Subject: [PATCH 07/12] Updated README.md --- README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f7b1e73..14657b4 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ The table below shows all available configurations and the cameras to which they In addition to the configurations in the table above, you can set any Basler camera property by including `options.basler.`. For example, it's common to set `options.basler.PixelFormat` to `RGB8`. ### Autodiscovery -Autodiscovery automatically connects to all cameras that are plugged into your machine or discoverable on the network, including `generic_usb`, `realsense` and `basler` cameras. Default configurations will be loaded for each camera. Please note that RTSP streams cannot be discovered in this manner; RTSP URLs must be specified in the configurations or can be discovered using a separate tool below. +Autodiscovery automatically connects to all cameras that are plugged into your machine or discoverable on the network, including `generic_usb`, `realsense`, `basler`, and ONVIF supported `RTSP` cameras. Default configurations will be loaded for each camera. Note that discovery of RTSP cameras will be disabled by default but can be enabled by setting `rtsp_discover_mode`. Refer to [RTSP Discovery](#rtsp-discovery) section for different options. Autodiscovery is great for simple applications where you don't need to set any special options on your cameras. It's also a convenient method for finding the serial numbers of your cameras (if the serial number isn't printed on the camera). ```python @@ -196,9 +196,10 @@ from framegrab import RTSPDiscovery, ONVIFDeviceInfo devices = RTSPDiscovery.discover_onvif_devices() ``` -The `discover_onvif_devices()` will provide a list of devices that it finds in the `ONVIFDeviceInfo` format. An optional mode `auto_discover_modes` can be used to try different default credentials to fetch RTSP URLs: +The `discover_onvif_devices()` will provide a list of devices that it finds in the `ONVIFDeviceInfo` format. An optional mode `auto_discover_mode` can be used to try different default credentials to fetch RTSP URLs: -- disable: Disable guessing camera credentials. +- disable: No discovery. +- ip_only: Only discover the IP address of the camera. - light: Only try first two usernames and passwords ("admin:admin" and no username/password). - complete_fast: Try the entire DEFAULT_CREDENTIALS without delays in between. - complete_slow: Try the entire DEFAULT_CREDENTIALS with a delay of 1 seconds in between. From cb0be8077ec90ca402d2c06cf89f2f6d2cca4b70 Mon Sep 17 00:00:00 2001 From: Harry Tung Date: Thu, 18 Jul 2024 12:56:43 -0700 Subject: [PATCH 08/12] Changed disable to off to be more clear --- README.md | 2 +- src/framegrab/cli/autodiscover.py | 2 +- src/framegrab/grabber.py | 6 +++--- src/framegrab/rtsp_discovery.py | 12 ++++++------ 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index 14657b4..cac9644 100644 --- a/README.md +++ b/README.md @@ -198,7 +198,7 @@ devices = RTSPDiscovery.discover_onvif_devices() The `discover_onvif_devices()` will provide a list of devices that it finds in the `ONVIFDeviceInfo` format. An optional mode `auto_discover_mode` can be used to try different default credentials to fetch RTSP URLs: -- disable: No discovery. +- off: No discovery. - ip_only: Only discover the IP address of the camera. - light: Only try first two usernames and passwords ("admin:admin" and no username/password). - complete_fast: Try the entire DEFAULT_CREDENTIALS without delays in between. diff --git a/src/framegrab/cli/autodiscover.py b/src/framegrab/cli/autodiscover.py index 1fb512b..557d300 100644 --- a/src/framegrab/cli/autodiscover.py +++ b/src/framegrab/cli/autodiscover.py @@ -23,7 +23,7 @@ @click.option( "--rtsp_discover_mode", type=click.Choice(PREVIEW_RTSP_COMMAND_CHOICES, case_sensitive=False), - default="disable", + default="off", show_default=True, ) def autodiscover(preview: str, rtsp_discover_mode: str = "disable"): diff --git a/src/framegrab/grabber.py b/src/framegrab/grabber.py index 0ab6ba9..62c2479 100644 --- a/src/framegrab/grabber.py +++ b/src/framegrab/grabber.py @@ -274,7 +274,7 @@ def create_grabber(config: dict, autogenerate_name: bool = True, warmup_delay: f @staticmethod def autodiscover( - warmup_delay: float = 1.0, rtsp_discover_mode: AutodiscoverMode = AutodiscoverMode.disable + warmup_delay: float = 1.0, rtsp_discover_mode: AutodiscoverMode = AutodiscoverMode.off ) -> dict: """Autodiscovers cameras and returns a dictionary of FrameGrabber objects @@ -286,13 +286,13 @@ def autodiscover( rtsp_discover_mode (AutodiscoverMode, optional): Options to try different default credentials stored in DEFAULT_CREDENTIALS for RTSP cameras. Consists of five options: - disable: No discovery. + off: No discovery. ip_only: Only discover the IP address of the camera. light: Only try first two usernames and passwords ("admin:admin" and no username/password). complete_fast: Try the entire DEFAULT_CREDENTIALS without delays in between. complete_slow: Try the entire DEFAULT_CREDENTIALS with a delay of 1 seconds in between. Defaults to ip_only. - Defaults to disable. + Defaults to off. """ autodiscoverable_input_types = ( InputTypes.REALSENSE, diff --git a/src/framegrab/rtsp_discovery.py b/src/framegrab/rtsp_discovery.py index c600ed8..5b0be19 100644 --- a/src/framegrab/rtsp_discovery.py +++ b/src/framegrab/rtsp_discovery.py @@ -31,14 +31,14 @@ class AutodiscoverMode(str, Enum): """ Enum for camera discovery modes. Options to try different default credentials stored in DEFAULT_CREDENTIALS. Consists of five options: - disable: No discovery. + off: No discovery. ip_only: Only discover the IP address of the camera. light: Only try first two usernames and passwords ("admin:admin" and no username/password). complete_fast: Try the entire DEFAULT_CREDENTIALS without delays in between. complete_slow: Try the entire DEFAULT_CREDENTIALS with a delay of 1 seconds in between. """ - disable = "disable" + off = "off" ip_only = "ip_only" light = "light" complete_fast = "complete_fast" @@ -77,7 +77,7 @@ def discover_onvif_devices( Parameters: auto_discover_mode (AutodiscoverMode, optional): Options to try different default credentials stored in DEFAULT_CREDENTIALS. Consists of five options: - disable: No discovery. + off: No discovery. ip_only: Only discover the IP address of the camera. light: Only try first two usernames and passwords ("admin:admin" and no username/password). complete_fast: Try the entire DEFAULT_CREDENTIALS without delays in between. @@ -91,7 +91,7 @@ def discover_onvif_devices( device_ips = [] logger.debug("Starting WSDiscovery for ONVIF devices") - if auto_discover_mode == AutodiscoverMode.disable: + if auto_discover_mode == AutodiscoverMode.off: logger.debug("ONVIF device discovery disabled") return device_ips @@ -167,7 +167,7 @@ def _try_logins(device: ONVIFDeviceInfo, auto_discover_mode: AutodiscoverMode) - device (ONVIFDeviceInfo): Pydantic Model that stores information about camera RTSP address, port number, username, and password. auto_discover_mode (AutodiscoverMode): Options to try different default credentials stored in DEFAULT_CREDENTIALS. Consists of five options: - disable: No discovery. + off: No discovery. ip_only: Only discover the IP address of the camera. light: Only try first two usernames and passwords ("admin:admin" and no username/password). complete_fast: Try the entire DEFAULT_CREDENTIALS without delays in between. @@ -179,7 +179,7 @@ def _try_logins(device: ONVIFDeviceInfo, auto_discover_mode: AutodiscoverMode) - credentials = DEFAULT_CREDENTIALS - if auto_discover_mode == AutodiscoverMode.ip_only or auto_discover_mode == AutodiscoverMode.disable: + if auto_discover_mode == AutodiscoverMode.ip_only or auto_discover_mode == AutodiscoverMode.off: return False if auto_discover_mode == AutodiscoverMode.light: From 18f917f5b0338adc7e21415e824e4feef6ed1511 Mon Sep 17 00:00:00 2001 From: Auto-format Bot Date: Thu, 18 Jul 2024 19:57:07 +0000 Subject: [PATCH 09/12] Automatically reformatting code with black and isort --- src/framegrab/grabber.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/framegrab/grabber.py b/src/framegrab/grabber.py index 62c2479..e079545 100644 --- a/src/framegrab/grabber.py +++ b/src/framegrab/grabber.py @@ -273,9 +273,7 @@ def create_grabber(config: dict, autogenerate_name: bool = True, warmup_delay: f return grabber @staticmethod - def autodiscover( - warmup_delay: float = 1.0, rtsp_discover_mode: AutodiscoverMode = AutodiscoverMode.off - ) -> dict: + def autodiscover(warmup_delay: float = 1.0, rtsp_discover_mode: AutodiscoverMode = AutodiscoverMode.off) -> dict: """Autodiscovers cameras and returns a dictionary of FrameGrabber objects warmup_delay (float, optional): The number of seconds to wait after creating the grabbers. USB From 681a4591f44dfcd9b8531bd21eed67e5895cac9f Mon Sep 17 00:00:00 2001 From: Harry Tung Date: Mon, 22 Jul 2024 10:15:35 -0700 Subject: [PATCH 10/12] Updated README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index cac9644..f27e4b8 100644 --- a/README.md +++ b/README.md @@ -174,7 +174,7 @@ The table below shows all available configurations and the cameras to which they In addition to the configurations in the table above, you can set any Basler camera property by including `options.basler.`. For example, it's common to set `options.basler.PixelFormat` to `RGB8`. ### Autodiscovery -Autodiscovery automatically connects to all cameras that are plugged into your machine or discoverable on the network, including `generic_usb`, `realsense`, `basler`, and ONVIF supported `RTSP` cameras. Default configurations will be loaded for each camera. Note that discovery of RTSP cameras will be disabled by default but can be enabled by setting `rtsp_discover_mode`. Refer to [RTSP Discovery](#rtsp-discovery) section for different options. +Autodiscovery automatically connects to all cameras that are plugged into your machine or discoverable on the network, including `generic_usb`, `realsense`, `basler`, and ONVIF supported `rtsp` cameras. Default configurations will be loaded for each camera. Note that discovery of RTSP cameras will be disabled by default but can be enabled by setting `rtsp_discover_mode`. Refer to [RTSP Discovery](#rtsp-discovery) section for different options. Autodiscovery is great for simple applications where you don't need to set any special options on your cameras. It's also a convenient method for finding the serial numbers of your cameras (if the serial number isn't printed on the camera). ```python From dacd38292fc1182ac447123ec4b39c7653cbe05f Mon Sep 17 00:00:00 2001 From: Harry Tung Date: Mon, 22 Jul 2024 10:15:57 -0700 Subject: [PATCH 11/12] Fixed docstring error --- src/framegrab/grabber.py | 1 - 1 file changed, 1 deletion(-) diff --git a/src/framegrab/grabber.py b/src/framegrab/grabber.py index e079545..574aa32 100644 --- a/src/framegrab/grabber.py +++ b/src/framegrab/grabber.py @@ -289,7 +289,6 @@ def autodiscover(warmup_delay: float = 1.0, rtsp_discover_mode: AutodiscoverMode light: Only try first two usernames and passwords ("admin:admin" and no username/password). complete_fast: Try the entire DEFAULT_CREDENTIALS without delays in between. complete_slow: Try the entire DEFAULT_CREDENTIALS with a delay of 1 seconds in between. - Defaults to ip_only. Defaults to off. """ autodiscoverable_input_types = ( From d68f9facd98def8b6efd4f748eea4a0760b6c835 Mon Sep 17 00:00:00 2001 From: Harry Tung Date: Mon, 22 Jul 2024 10:16:57 -0700 Subject: [PATCH 12/12] Changed CLI option name to use hyphens --- src/framegrab/cli/autodiscover.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/framegrab/cli/autodiscover.py b/src/framegrab/cli/autodiscover.py index 557d300..b81a2a5 100644 --- a/src/framegrab/cli/autodiscover.py +++ b/src/framegrab/cli/autodiscover.py @@ -21,12 +21,12 @@ show_default=True, ) @click.option( - "--rtsp_discover_mode", + "--rtsp-discover-mode", type=click.Choice(PREVIEW_RTSP_COMMAND_CHOICES, case_sensitive=False), default="off", show_default=True, ) -def autodiscover(preview: str, rtsp_discover_mode: str = "disable"): +def autodiscover(preview: str, rtsp_discover_mode: str = "off"): """Automatically discover cameras connected to the current host (e.g. USB).""" # Print message to stderr click.echo("Discovering cameras...", err=True)