Skip to content

Commit

Permalink
Improving ObstacleImages View.
Browse files Browse the repository at this point in the history
- Reduced THRead from 3 to 1 for the image download.
- Added more logging to check the CameraMode.
- Added async immage load.
- Safe Fail link creation using vacuum api

Signed-off-by: [email protected] <[email protected]>
  • Loading branch information
sca075 committed Dec 6, 2024
1 parent 8b425ed commit a0f4e9e
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 13 deletions.
47 changes: 39 additions & 8 deletions custom_components/mqtt_vacuum_camera/camera.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"""
Camera
Version: v2024.12.0
Version: v2024.12.1
"""

from __future__ import annotations
Expand Down Expand Up @@ -248,8 +248,9 @@ async def handle_obstacle_view(self, event):

if self._shared.camera_mode == CameraModes.OBSTACLE_VIEW:
self._shared.camera_mode = CameraModes.MAP_VIEW
_LOGGER.debug(f"Camera Mode Change to {self._shared.camera_mode}")
self._should_poll = True
return
return await self.async_update()

if (
self._shared.obstacles_data
Expand All @@ -258,6 +259,7 @@ async def handle_obstacle_view(self, event):
_LOGGER.debug(f"Received event: {event.event_type}, Data: {event.data}")
if event.data.get("entity_id") == self.entity_id:
self._shared.camera_mode = CameraModes.OBSTACLE_DOWNLOAD
_LOGGER.debug(f"Camera Mode Change to {self._shared.camera_mode}")
self._should_poll = False # Turn off polling
coordinates = event.data.get("coordinates")
if coordinates:
Expand Down Expand Up @@ -288,11 +290,14 @@ async def handle_obstacle_view(self, event):
)
self._should_poll = True # Turn on polling
self._shared.camera_mode = CameraModes.MAP_VIEW
_LOGGER.debug(
f"Camera Mode Change to {self._shared.camera_mode}"
)
return None
if temp_image is not None:
try:
# Open the downloaded image with PIL
pil_img = Image.open(temp_image)
pil_img = await self.async_open_image(temp_image)

# Resize the image if resize_to is provided
pil_img.thumbnail((self._image_w, self._image_h))
Expand All @@ -304,15 +309,24 @@ async def handle_obstacle_view(self, event):
f"{self._file_name}: Error processing image: {e}"
)
self._shared.camera_mode = CameraModes.MAP_VIEW
_LOGGER.debug(
f"Camera Mode Change to {self._shared.camera_mode}"
)
self._should_poll = True # Turn on polling
return None

self.Image = await self.hass.async_create_task(
self.run_async_pil_to_bytes(pil_img)
)
self._shared.camera_mode = CameraModes.OBSTACLE_VIEW
_LOGGER.debug(
f"Camera Mode Change to {self._shared.camera_mode}"
)
else:
self._shared.camera_mode = CameraModes.MAP_VIEW
_LOGGER.debug(
f"Camera Mode Change to {self._shared.camera_mode}"
)
self._should_poll = True # Turn on polling
else:
_LOGGER.debug("No nearby obstacle found.")
Expand All @@ -326,9 +340,9 @@ async def handle_obstacle_view(self, event):
async def _async_find_nearest_obstacle(x, y, obstacles):
"""Find the nearest obstacle to the given coordinates."""
nearest_obstacle = None
min_distance = float("inf") # Start with a very large distance
min_distance = 500 # Start with a very large distance
_LOGGER.debug(
f"Finding the nearest {min_distance} obstacle to coordinates: {x}, {y}"
f"Finding in the nearest {min_distance} piyels obstacle to coordinates: {x}, {y}"
)

for obstacle in obstacles:
Expand All @@ -345,8 +359,23 @@ async def _async_find_nearest_obstacle(x, y, obstacles):

return nearest_obstacle

@staticmethod
async def download_image(url: str, storage_path: str, filename: str):
async def async_open_image(self, file_path) -> Image.Image:
"""
Asynchronously open an image file using a thread pool.
Args:
file_path (str): Path to the image file.
Returns:
Image.Image: Opened PIL image.
"""
executor = ThreadPoolExecutor(
max_workers=1, thread_name_prefix=f"{self._file_name}_camera"
)
loop = asyncio.get_running_loop()
pil_img = await loop.run_in_executor(executor, Image.open, file_path)
return pil_img

async def download_image(self, url: str, storage_path: str, filename: str):
"""
Asynchronously download an image using threading to avoid blocking.
Expand Down Expand Up @@ -384,7 +413,9 @@ async def blocking_download():
_LOGGER.error(f"Error downloading image: {e}")
return None

executor = ThreadPoolExecutor(max_workers=3) # Limit to 3 workers
executor = ThreadPoolExecutor(
max_workers=1, thread_name_prefix=f"{self._file_name}_camera"
) # Limit to 3 workers

# Run the blocking I/O in a thread
return await asyncio.get_running_loop().run_in_executor(
Expand Down
10 changes: 8 additions & 2 deletions custom_components/mqtt_vacuum_camera/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -219,14 +219,20 @@ def compose_obstacle_links(vacuum_host_ip: str, obstacles: list) -> list:
Compose JSON with obstacle details including the image link.
"""
obstacle_links = []
if not obstacles or not vacuum_host_ip:
_LOGGER.debug(
f"Obstacle links: no obstacles: "
f"{obstacles} and / or ip: {vacuum_host_ip} to link."
)
return None

for obstacle in obstacles:
# Extract obstacle details
label = obstacle.get("label", "")
points = obstacle.get("points", {})
image_id = obstacle.get("id", "None")

if label and points and image_id:
if label and points and image_id and vacuum_host_ip:
# Append formatted obstacle data
if image_id != "None":
# Compose the link
Expand All @@ -246,6 +252,6 @@ def compose_obstacle_links(vacuum_host_ip: str, obstacles: list) -> list:
}
)

_LOGGER.debug(f"Obstacle links: {obstacle_links}")
_LOGGER.debug(f"Obstacle links: linked data complete.")

return obstacle_links
Original file line number Diff line number Diff line change
Expand Up @@ -122,9 +122,14 @@ async def async_draw_obstacle(
obstacle_objects.append(obstacle_obj)

# Store obstacle data in shared data
self.img_h.shared.obstacles_data = compose_obstacle_links(
self.img_h.shared.vacuum_ips, obstacle_objects
)
if self.img_h.shared.vacuum_ips:
self.img_h.shared.obstacles_data = compose_obstacle_links(
self.img_h.shared.vacuum_ips, obstacle_objects
)
elif self.img_h.shared.vacuum_api:
self.img_h.shared.obstacles_data = compose_obstacle_links(
self.img_h.shared.vacuum_api.spit("http://")[1], obstacle_objects
)

# Draw obstacles on the map
if obstacle_objects:
Expand Down

0 comments on commit a0f4e9e

Please sign in to comment.