Skip to content

Commit

Permalink
Minor Refactoring and Fixes #195 from sca075/2024.07_dev
Browse files Browse the repository at this point in the history
Some minimal refactoring.
  • Loading branch information
sca075 committed Jun 29, 2024
2 parents 82ffd7b + 5f15f73 commit 0929631
Show file tree
Hide file tree
Showing 9 changed files with 66 additions and 52 deletions.
4 changes: 1 addition & 3 deletions custom_components/mqtt_vacuum_camera/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
CONF_VACUUM_IDENTIFIERS,
DOMAIN,
)

from .utils.users_data import (
async_get_translations_vacuum_id,
async_rename_room_description,
Expand Down Expand Up @@ -230,7 +229,6 @@ async def async_migrate_entry(hass, config_entry: config_entries.ConfigEntry):
async def async_setup_entry(
hass: core.HomeAssistant, entry: config_entries.ConfigEntry
) -> bool:

"""Set up platform from a ConfigEntry."""
hass.data.setdefault(DOMAIN, {})
hass_data = dict(entry.data)
Expand Down Expand Up @@ -301,7 +299,7 @@ def find_vacuum_files(directory) -> list[str] or None:
# noinspection PyCallingNonCallable
async def async_setup(hass: core.HomeAssistant, config: dict) -> bool:
"""Set up the Valetudo Camera Custom component from yaml configuration."""

async def handle_homeassistant_stop(event):
"""Handle Home Assistant stop event."""
_LOGGER.info("Home Assistant is stopping. Writing down the rooms data.")
Expand Down
2 changes: 1 addition & 1 deletion custom_components/mqtt_vacuum_camera/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@
"iot_class": "local_polling",
"issue_tracker": "https://github.com/sca075/mqtt_vacuum_camera/issues",
"requirements": ["pillow==10.3.0", "numpy"],
"version": "2024.07.0b2"
"version": "2024.07.0"
}
5 changes: 2 additions & 3 deletions custom_components/mqtt_vacuum_camera/repairs.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@

from __future__ import annotations

import voluptuous as vol

from homeassistant import data_entry_flow
from homeassistant.components.repairs import RepairsFlow
from homeassistant.core import HomeAssistant
import voluptuous as vol


class Issue1RepairFlow(RepairsFlow):
Expand All @@ -17,7 +16,7 @@ async def async_step_init(
) -> data_entry_flow.FlowResult:
"""Handle the first step of a fix flow."""

return await (self.async_step_confirm())
return await self.async_step_confirm()

async def async_step_confirm(
self, user_input: dict[str, str] | None = None
Expand Down
7 changes: 1 addition & 6 deletions custom_components/mqtt_vacuum_camera/utils/drawable.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,7 @@
from PIL import ImageDraw, ImageFont
import numpy as np

from custom_components.mqtt_vacuum_camera.types import (
Color,
NumpyArray,
PilPNG,
Point,
)
from custom_components.mqtt_vacuum_camera.types import Color, NumpyArray, PilPNG, Point

# import re

Expand Down
2 changes: 1 addition & 1 deletion custom_components/mqtt_vacuum_camera/utils/status_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
import json
import logging

from custom_components.mqtt_vacuum_camera.types import JsonType, PilPNG
from custom_components.mqtt_vacuum_camera.const import DOMAIN
from custom_components.mqtt_vacuum_camera.types import JsonType, PilPNG

_LOGGER: logging.Logger = logging.getLogger(__name__)
_LOGGER.propagate = True
Expand Down
4 changes: 1 addition & 3 deletions custom_components/mqtt_vacuum_camera/utils/users_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -302,9 +302,7 @@ async def async_rename_room_description(
# Get the languages to modify
language = await async_load_languages(storage_path)
_LOGGER.info(f"Languages to modify: {language}")
edit_path = hass.config.path(
f"custom_components/mqtt_vacuum_camera/translations"
)
edit_path = hass.config.path(f"custom_components/mqtt_vacuum_camera/translations")
_LOGGER.info(f"Editing the translations file for language: {language}")
data_list = await async_load_translations_json(hass, language)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,7 @@
from isal import igzip, isal_zlib

from custom_components.mqtt_vacuum_camera.common import async_write_file_to_disk
from custom_components.mqtt_vacuum_camera.valetudo.rand256.rrparser import (
RRMapParser,
)
from custom_components.mqtt_vacuum_camera.valetudo.rand256.rrparser import RRMapParser

_LOGGER = logging.getLogger(__name__)
_QOS = 0
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
"""
Image Utils Class for Valetudo Hypfer Image Handling.
This class is used to simplify the ImageHandler class.
Version: 2024.06.1
Version: 2024.07.0
"""

from __future__ import annotations

import logging

import numpy as np
from numpy import rot90

from custom_components.mqtt_vacuum_camera.types import NumpyArray
from custom_components.mqtt_vacuum_camera.types import Color, NumpyArray

_LOGGER = logging.getLogger(__name__)


class TrimError(Exception):
"""Exception raised for errors in the trim process."""

def __init__(self, message, image):
super().__init__(message)
self.image = image


class ImageUtils:
"""Image Utils Class for Valetudo Hypfer Image Handler."""

Expand Down Expand Up @@ -52,6 +61,24 @@ async def async_check_if_zoom_is_on(
]
return trimmed

async def async_image_margins(
self, image_array: NumpyArray, detect_colour: Color
) -> tuple[int, int, int, int]:
"""Crop the image based on the auto crop area."""
"""async_auto_trim_and_zoom_image"""

nonzero_coords = np.column_stack(np.where(image_array != list(detect_colour)))
# Calculate the trim box based on the first and last occurrences
min_y, min_x, _ = NumpyArray.min(nonzero_coords, axis=0)
max_y, max_x, _ = NumpyArray.max(nonzero_coords, axis=0)
del nonzero_coords
_LOGGER.debug(
f"{self.file_name}: Found trims max and min values (y,x) "
f"({int(max_y)}, {int(max_x)}) ({int(min_y)},{int(min_x)})..."
)

return min_y, min_x, max_x, max_y

async def async_rotate_the_image(
self, trimmed: NumpyArray, rotate: int
) -> NumpyArray:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Image Handler Class.
It returns the PIL PNG image frame relative to the Map Data extrapolated from the vacuum json.
It also returns calibration, rooms data to the card and other images information to the camera.
Version: 2024.06.2
Version: 2024.07.0
"""

from __future__ import annotations
Expand All @@ -11,7 +11,6 @@
import logging

from PIL import Image, ImageOps
import numpy as np

from custom_components.mqtt_vacuum_camera.types import (
CalibrationPoints,
Expand All @@ -27,6 +26,7 @@
from custom_components.mqtt_vacuum_camera.utils.img_data import ImageData
from custom_components.mqtt_vacuum_camera.valetudo.hypfer.handler_utils import (
ImageUtils as ImUtils,
TrimError,
)
from custom_components.mqtt_vacuum_camera.valetudo.hypfer.image_draw import (
ImageDraw as ImDraw,
Expand Down Expand Up @@ -78,6 +78,20 @@ def __init__(self, shared_data):
self.imd = ImDraw(self)
self.imu = ImUtils(self)

def check_trim(
self, trimmed_height, trimmed_width, margin_size, image_array, file_name, rotate
):
"""
Check if the trimming is okay.
"""
if trimmed_height <= margin_size or trimmed_width <= margin_size:
self.crop_area = [0, 0, image_array.shape[1], image_array.shape[0]]
self.img_size = (image_array.shape[1], image_array.shape[0])
raise TrimError(
f"Trimming failed at rotation {rotate}. Reverting to original image.",
image_array,
)

async def async_auto_trim_and_zoom_image(
self,
image_array: NumpyArray,
Expand All @@ -92,21 +106,8 @@ async def async_auto_trim_and_zoom_image(
try:
if not self.auto_crop:
# Find the coordinates of the first occurrence of a non-background color
nonzero_coords = np.column_stack(
np.where(image_array != list(detect_colour))
)
# Calculate the trim box based on the first and last occurrences
min_y, min_x, _ = np.min(nonzero_coords, axis=0)
max_y, max_x, _ = np.max(nonzero_coords, axis=0)
del nonzero_coords
_LOGGER.debug(
"{}: Found trims max and min values (y,x) ({}, {}) ({},{})...".format(
self.file_name,
int(max_y),
int(max_x),
int(min_y),
int(min_x),
)
min_y, min_x, max_x, max_y = await self.imu.async_image_margins(
image_array, detect_colour
)
# Calculate and store the trims coordinates with margins
self.trim_left = int(min_x) + self.offset_left - margin_size
Expand All @@ -122,20 +123,17 @@ async def async_auto_trim_and_zoom_image(
self.shared.image_ref_width = trimmed_width

# Test if the trims are okay or not
if trimmed_height <= margin_size or trimmed_width <= margin_size:
_LOGGER.debug(
f"{self.file_name}: Background colour not detected at rotation {rotate}."
try:
self.check_trim(
trimmed_height,
trimmed_width,
margin_size,
image_array,
self.file_name,
rotate,
)
pos_0 = 0
self.crop_area = [
pos_0,
pos_0,
image_array.shape[1],
image_array.shape[0],
]
self.img_size = (image_array.shape[1], image_array.shape[0])
del trimmed_width, trimmed_height
return image_array
except TrimError as e:
return e.image

# Store Crop area of the original image_array we will use from the next frame.
self.auto_crop = [
Expand All @@ -144,6 +142,7 @@ async def async_auto_trim_and_zoom_image(
self.trim_right,
self.trim_down,
]

# If it is needed to zoom the image.
trimmed = await self.imu.async_check_if_zoom_is_on(
image_array, margin_size, zoom
Expand Down

0 comments on commit 0929631

Please sign in to comment.