valetudo-map-parser 0.1.9b32__tar.gz → 0.1.9b34__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (21) hide show
  1. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/PKG-INFO +1 -1
  2. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/config/auto_crop.py +9 -3
  3. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/config/shared.py +11 -3
  4. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/config/types.py +40 -32
  5. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/config/utils.py +6 -2
  6. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/hypfer_handler.py +3 -2
  7. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/rand25_handler.py +3 -0
  8. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/pyproject.toml +1 -1
  9. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/LICENSE +0 -0
  10. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/NOTICE.txt +0 -0
  11. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/README.md +0 -0
  12. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/__init__.py +0 -0
  13. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/config/__init__.py +0 -0
  14. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/config/colors.py +0 -0
  15. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/config/colors_man.py +0 -0
  16. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/config/drawable.py +0 -0
  17. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/config/rand25_parser.py +0 -0
  18. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/hypfer_draw.py +0 -0
  19. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/map_data.py +0 -0
  20. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/py.typed +0 -0
  21. {valetudo_map_parser-0.1.9b32 → valetudo_map_parser-0.1.9b34}/SCR/valetudo_map_parser/reimg_draw.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: valetudo-map-parser
3
- Version: 0.1.9b32
3
+ Version: 0.1.9b34
4
4
  Summary: A Python library to parse Valetudo map data returning a PIL Image object.
5
5
  License: Apache-2.0
6
6
  Author: Sandro Cantarella
@@ -90,6 +90,7 @@ class AutoCrop:
90
90
 
91
91
  async def _async_auto_crop_data(self, tdata: TrimsData): # , tdata=None
92
92
  """Load the auto crop data from the Camera config."""
93
+ _LOGGER.debug("Auto Crop data: %s, %s", str(tdata), str(self.auto_crop))
93
94
  if not self.auto_crop:
94
95
  trims_data = TrimCropData.from_dict(dict(tdata.to_dict())).to_list()
95
96
  (
@@ -98,9 +99,12 @@ class AutoCrop:
98
99
  self.trim_right,
99
100
  self.trim_down,
100
101
  ) = trims_data
101
- self._calculate_trimmed_dimensions()
102
+ _LOGGER.debug("Auto Crop trims data: %s", trims_data)
103
+ if trims_data != [0, 0, 0, 0]:
104
+ self._calculate_trimmed_dimensions()
105
+ else:
106
+ trims_data = None
102
107
  return trims_data
103
- _LOGGER.debug("No Crop data found in the Camera config.")
104
108
  return None
105
109
 
106
110
  def auto_crop_offset(self):
@@ -113,7 +117,9 @@ class AutoCrop:
113
117
 
114
118
  async def _init_auto_crop(self):
115
119
  """Initialize the auto crop data."""
116
- if not self.auto_crop and self.handler.shared.vacuum_state == "docked":
120
+ _LOGGER.debug("Auto Crop Init data: %s", str(self.auto_crop))
121
+ _LOGGER.debug("Auto Crop Init trims data: %s", self.handler.shared.trims.to_dict())
122
+ if not self.auto_crop: # and self.handler.shared.vacuum_state == "docked":
117
123
  self.auto_crop = await self._async_auto_crop_data(self.handler.shared.trims)
118
124
  if self.auto_crop:
119
125
  self.auto_crop_offset()
@@ -123,6 +123,10 @@ class CameraShared:
123
123
  """Get the rooms colors."""
124
124
  return self.rooms_colors
125
125
 
126
+ def reset_trims(self) -> dict:
127
+ """Reset the trims."""
128
+ return self.trims.clear()
129
+
126
130
  async def batch_update(self, **kwargs):
127
131
  """Batch update multiple attributes."""
128
132
  for key, value in kwargs.items():
@@ -172,6 +176,7 @@ class CameraSharedManager:
172
176
  self._lock = asyncio.Lock()
173
177
  self.file_name = file_name
174
178
  self.device_info = device_info
179
+ self.update_shared_data(device_info)
175
180
 
176
181
  # Automatically initialize shared data for the instance
177
182
  # self._init_shared_data(device_info)
@@ -227,9 +232,12 @@ class CameraSharedManager:
227
232
  instance.enable_snapshots = device_info.get(
228
233
  CONF_SNAPSHOTS_ENABLE, DEFAULT_VALUES["enable_www_snapshots"]
229
234
  )
230
- instance.trims.from_dict(
231
- device_info.get("trims_data", DEFAULT_VALUES["trims_data"])
232
- )
235
+ # Ensure trims are updated correctly
236
+ trim_data = device_info.get("trims_data", DEFAULT_VALUES["trims_data"])
237
+ _LOGGER.debug("Updating shared trims with: %s", trim_data)
238
+ instance.trims = TrimsData.from_dict(trim_data)
239
+
240
+ _LOGGER.debug("Shared trims successfully updated: %s", instance.trims.to_dict())
233
241
 
234
242
  except TypeError as ex:
235
243
  _LOGGER.error("Shared data can't be initialized due to a TypeError! %s", ex)
@@ -7,7 +7,7 @@ import asyncio
7
7
  import json
8
8
  import logging
9
9
  from dataclasses import asdict, dataclass
10
- from typing import Any, Dict, Tuple, Union
10
+ from typing import Any, Dict, Tuple, Union, Optional
11
11
 
12
12
  import numpy as np
13
13
  from PIL import Image
@@ -74,43 +74,43 @@ class TrimCropData:
74
74
  )
75
75
 
76
76
 
77
- # pylint: disable=no-member
78
77
  class RoomStore:
79
- """Store the room data for the vacuum."""
78
+ """Singleton RoomStore to store room data per vacuum."""
80
79
 
81
- _instance = None
82
- _lock = asyncio.Lock()
80
+ _instances: Dict[str, "RoomStore"] = {} # Stores instances by vacuum ID
81
+ _lock = asyncio.Lock() # Ensures thread-safe access
83
82
 
84
- def __init__(self):
85
- self.vacuums_data = {}
83
+ def __new__(cls, vacuum_id: str, rooms_data: Optional[dict] = None) -> "RoomStore":
84
+ """Create a new instance or return an existing one."""
85
+ if vacuum_id not in cls._instances:
86
+ instance = super().__new__(cls)
87
+ instance.vacuum_id = vacuum_id
88
+ instance.vacuums_data = rooms_data or {} # Store room data
89
+ cls._instances[vacuum_id] = instance # Store the instance
90
+ return cls._instances[vacuum_id]
86
91
 
87
- def __new__(cls):
88
- if cls._instance is None:
89
- cls._instance = super(RoomStore, cls).__new__(cls)
90
- cls._instance.vacuums_data = {}
91
- return cls._instance
92
+ def __init__(self, vacuum_id: str, rooms_data: Optional[dict] = None):
93
+ """Initialize the instance."""
94
+ self.vacuum_id = vacuum_id
95
+ self.vacuums_data = rooms_data or {}
92
96
 
93
- async def async_set_rooms_data(self, vacuum_id: str, rooms_data: dict) -> None:
94
- """Set the room data for the vacuum."""
95
- async with self._lock:
96
- self.vacuums_data[vacuum_id] = rooms_data
97
+ def get_rooms(self) -> dict:
98
+ """Return the stored rooms data."""
99
+ return self.vacuums_data
100
+
101
+ def set_rooms(self, rooms_data: dict) -> None:
102
+ """Update the rooms data."""
103
+ self.vacuums_data = rooms_data
104
+
105
+ def get_rooms_count(self) -> int:
106
+ """Return the number of rooms stored for this vacuum."""
107
+ return len(self.vacuums_data)
108
+
109
+ @classmethod
110
+ def get_all_instances(cls) -> Dict[str, "RoomStore"]:
111
+ """Return all active instances (for debugging)."""
112
+ return cls._instances
97
113
 
98
- async def async_get_rooms_data(self, vacuum_id: str) -> dict:
99
- """Get the room data for a vacuum."""
100
- async with self._lock:
101
- data = self.vacuums_data.get(vacuum_id, {})
102
- if isinstance(data, str):
103
- json_data = json.loads(data)
104
- return json_data
105
- return data
106
-
107
- async def async_get_rooms_count(self, vacuum_id: str) -> int:
108
- """Count the number of rooms for a vacuum."""
109
- async with self._lock:
110
- count = len(self.vacuums_data.get(vacuum_id, {}))
111
- if count == 0:
112
- return DEFAULT_ROOMS
113
- return count
114
114
 
115
115
 
116
116
  # pylint: disable=no-member
@@ -624,3 +624,11 @@ class TrimsData:
624
624
  def to_dict(self) -> dict:
625
625
  """Convert TrimData to a dictionary."""
626
626
  return asdict(self)
627
+
628
+ def clear(self)-> dict:
629
+ """Clear all the trims."""
630
+ self.trim_left = 0
631
+ self.trim_up = 0
632
+ self.trim_right = 0
633
+ self.trim_down = 0
634
+ return asdict(self)
@@ -58,7 +58,7 @@ class BaseHandler:
58
58
  self.crop_img_size = [0, 0]
59
59
  self.offset_x = 0
60
60
  self.offset_y = 0
61
- self.crop_area = [0, 0, 0, 0]
61
+ self.crop_area = None
62
62
  self.zooming = False
63
63
  self.async_resize_images = async_resize_image
64
64
 
@@ -495,7 +495,10 @@ async def async_resize_image(params: ResizeParams):
495
495
  hsf,
496
496
  )
497
497
  return params.pil_img # Return original image if invalid
498
-
498
+ if params.width == 0:
499
+ params.width = params.pil_img.width
500
+ if params.height == 0:
501
+ params.height = params.pil_img.height
499
502
  new_aspect_ratio = wsf / hsf
500
503
  if params.width / params.height > new_aspect_ratio:
501
504
  new_width = int(params.pil_img.height * new_aspect_ratio)
@@ -505,6 +508,7 @@ async def async_resize_image(params: ResizeParams):
505
508
  new_height = int(params.pil_img.width / new_aspect_ratio)
506
509
 
507
510
  _LOGGER.debug("Resizing image to aspect ratio: %s, %s", wsf, hsf)
511
+ _LOGGER.debug("New image size: %s x %s", new_width, new_height)
508
512
 
509
513
  if (params.crop_size is not None) and (params.offset_func is not None):
510
514
  offset = OffsetParams(wsf, hsf, new_width, new_height, params.is_rand)
@@ -15,7 +15,7 @@ from PIL import Image
15
15
  from .config.auto_crop import AutoCrop
16
16
  from .config.drawable import Drawable
17
17
  from .config.shared import CameraShared
18
- from .config.types import COLORS, CalibrationPoints, Colors, RoomsProperties
18
+ from .config.types import COLORS, CalibrationPoints, Colors, RoomsProperties, RoomStore
19
19
  from .config.utils import BaseHandler, prepare_resize_params
20
20
  from .hypfer_draw import ImageDraw as ImDraw
21
21
  from .map_data import ImageData
@@ -83,7 +83,8 @@ class HypferMapImageHandler(BaseHandler, AutoCrop):
83
83
  "y": ((y_min + y_max) // 2),
84
84
  }
85
85
  if room_properties:
86
- _LOGGER.debug("%s: Rooms data extracted!", self.file_name)
86
+ rooms = RoomStore(self.file_name, room_properties)
87
+ _LOGGER.debug("%s: Rooms data extracted! %s", self.file_name, rooms.get_rooms())
87
88
  else:
88
89
  _LOGGER.debug("%s: Rooms data not available!", self.file_name)
89
90
  self.rooms_pos = None
@@ -27,6 +27,7 @@ from .config.types import (
27
27
  from .config.utils import BaseHandler, prepare_resize_params
28
28
  from .map_data import RandImageData
29
29
  from .reimg_draw import ImageDraw
30
+ from .config.types import RoomStore
30
31
 
31
32
 
32
33
  _LOGGER = logging.getLogger(__name__)
@@ -120,6 +121,8 @@ class ReImageHandler(BaseHandler, AutoCrop):
120
121
  _LOGGER.debug(
121
122
  "%s: Rooms and Zones data not available!", self.file_name
122
123
  )
124
+ rooms = RoomStore(self.file_name, room_properties)
125
+ _LOGGER.debug("Rooms Data: %s", rooms.get_rooms())
123
126
  return room_properties, zone_properties, point_properties
124
127
  except RuntimeError as e:
125
128
  _LOGGER.debug(
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "valetudo-map-parser"
3
- version = "0.1.9.b32"
3
+ version = "0.1.9.b34"
4
4
  description = "A Python library to parse Valetudo map data returning a PIL Image object."
5
5
  authors = ["Sandro Cantarella <gsca075@gmail.com>"]
6
6
  license = "Apache-2.0"