diff --git a/custom_components/moonraker/camera.py b/custom_components/moonraker/camera.py index 47b493f..44684bb 100755 --- a/custom_components/moonraker/camera.py +++ b/custom_components/moonraker/camera.py @@ -1,4 +1,5 @@ """Support for Moonraker camera.""" + from __future__ import annotations import logging @@ -15,12 +16,15 @@ CONF_URL, CONF_OPTION_CAMERA_STREAM, CONF_OPTION_CAMERA_SNAPSHOT, + CONF_OPTION_CAMERA_PORT, + CONF_OPTION_THUMBNAIL_PORT, DOMAIN, METHODS, PRINTSTATES, ) _LOGGER = logging.getLogger(__name__) +DEFAULT_PORT = 80 hardcoded_camera = { "name": "webcam", @@ -97,10 +101,18 @@ def __init__(self, config_entry, coordinator, camera, camera_id) -> None: self._attr_device_info = DeviceInfo( identifiers={(DOMAIN, config_entry.entry_id)} ) + if ( + config_entry.options.get(CONF_OPTION_CAMERA_PORT) is not None + and config_entry.options.get(CONF_OPTION_CAMERA_PORT) != "" + ): + self.port = config_entry.options.get(CONF_OPTION_CAMERA_PORT) + else: + self.port = DEFAULT_PORT + if camera["stream_url"].startswith("http"): self.url = "" else: - self.url = f"http://{config_entry.data.get(CONF_URL)}" + self.url = f"http://{config_entry.data.get(CONF_URL)}:{self.port}" _LOGGER.info(f"Connecting to camera: {self.url}{camera['stream_url']}") @@ -133,6 +145,14 @@ def __init__(self, config_entry, coordinator, session) -> None: self._current_pic = None self._current_path = "" + if ( + config_entry.options.get(CONF_OPTION_THUMBNAIL_PORT) is not None + and config_entry.options.get(CONF_OPTION_THUMBNAIL_PORT) != "" + ): + self.port = config_entry.options.get(CONF_OPTION_THUMBNAIL_PORT) + else: + self.port = DEFAULT_PORT + async def async_camera_image( self, width: int | None = None, height: int | None = None ) -> bytes | None: @@ -163,10 +183,10 @@ async def async_camera_image( new_path = new_path.replace(" ", "%20") _LOGGER.debug( - f"Fetching new thumbnail: http://{self.url}/server/files/gcodes/{new_path}" + f"Fetching new thumbnail: http://{self.url}:{self.port}/server/files/gcodes/{new_path}" ) response = await self._session.get( - f"http://{self.url}/server/files/gcodes/{new_path}" + f"http://{self.url}:{self.port}/server/files/gcodes/{new_path}" ) self._current_path = new_path diff --git a/custom_components/moonraker/config_flow.py b/custom_components/moonraker/config_flow.py index ec29a5a..a1486ef 100755 --- a/custom_components/moonraker/config_flow.py +++ b/custom_components/moonraker/config_flow.py @@ -22,6 +22,8 @@ CONF_OPTION_POLLING_RATE, CONF_OPTION_CAMERA_STREAM, CONF_OPTION_CAMERA_SNAPSHOT, + CONF_OPTION_CAMERA_PORT, + CONF_OPTION_THUMBNAIL_PORT, DOMAIN, TIMEOUT, ) @@ -187,6 +189,18 @@ async def async_step_init( CONF_OPTION_CAMERA_SNAPSHOT, "" ), ): str, + vol.Optional( + CONF_OPTION_CAMERA_PORT, + default=self.config_entry.options.get( + CONF_OPTION_CAMERA_PORT, "" + ), + ): str, + vol.Optional( + CONF_OPTION_THUMBNAIL_PORT, + default=self.config_entry.options.get( + CONF_OPTION_THUMBNAIL_PORT, "" + ), + ): str, } ), ) diff --git a/custom_components/moonraker/const.py b/custom_components/moonraker/const.py index d4daa81..5d508c2 100644 --- a/custom_components/moonraker/const.py +++ b/custom_components/moonraker/const.py @@ -28,6 +28,8 @@ CONF_OPTION_CAMERA_STREAM = "camera_stream_url" CONF_OPTION_CAMERA_SNAPSHOT = "camera_snapshot_url" CONF_OPTION_POLLING_RATE = "polling_rate" +CONF_OPTION_CAMERA_PORT = "camera_port" +CONF_OPTION_THUMBNAIL_PORT = "thumbnail_port" # API dict keys HOSTNAME = "hostname" diff --git a/custom_components/moonraker/translations/en.json b/custom_components/moonraker/translations/en.json index cfdb641..f30bcba 100644 --- a/custom_components/moonraker/translations/en.json +++ b/custom_components/moonraker/translations/en.json @@ -26,7 +26,9 @@ "data": { "polling_rate": "Integration polling rate (s)", "camera_stream_url": "Camera Stream URL", - "camera_snapshot_url": "Camera Snapshot URL" + "camera_snapshot_url": "Camera Snapshot URL", + "camera_port": "Camera Port", + "thumbnail_port": "Thumbnail Port" }, "title": "Configuration" } diff --git a/tests/test_camera.py b/tests/test_camera.py index cf569be..0339813 100755 --- a/tests/test_camera.py +++ b/tests/test_camera.py @@ -36,7 +36,9 @@ async def test_camera_services(hass, caplog): entry = entity_registry.async_get("camera.mainsail_webcam") assert entry is not None - assert "Connecting to camera: http://1.2.3.4/webcam/?action=stream" in caplog.text + assert ( + "Connecting to camera: http://1.2.3.4:80/webcam/?action=stream" in caplog.text + ) async def test_camera_services_full_path(hass, get_camera_info, caplog):