Skip to content

Commit

Permalink
Retry on failed fetch, fixed duration could be set to 0
Browse files Browse the repository at this point in the history
  • Loading branch information
valentinfrlch committed Oct 21, 2024
1 parent 72ced20 commit dc39f64
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 15 deletions.
16 changes: 15 additions & 1 deletion custom_components/llmvision/media_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ async def resize_image(self, target_width, image_path=None, image_data=None, img
img = await self.hass.loop.run_in_executor(None, Image.open, image_path)
with img:
# Check if the image is a GIF and convert if necessary
_LOGGER.debug(f"Image format: {img.format}")
img = self._convert_to_rgb(img)
# calculate new height based on aspect ratio
width, height = img.size
Expand Down Expand Up @@ -134,6 +133,7 @@ async def record(self, image_entities, duration, max_frames, target_width, inclu
import asyncio

interval = 1 if duration < 3 else 2 if duration < 10 else 4 if duration < 30 else 6 if duration < 60 else 10
duration += 1 # add 1 second in case the first fetch fails
camera_frames = {}

# Record on a separate thread for each camera
Expand All @@ -144,10 +144,15 @@ async def record_camera(image_entity, camera_number):
previous_frame = None
while time.time() - start < duration:
base_url = get_url(self.hass)
# fetched every cycle to ensure latest access token
frame_url = base_url + \
self.hass.states.get(image_entity).attributes.get(
'entity_picture')
frame_data = await self.client._fetch(frame_url)

# Skip frame when fetch failed
if not frame_data:
continue

img = Image.open(io.BytesIO(frame_data))
current_frame_gray = np.array(img.convert('L'))
Expand Down Expand Up @@ -212,6 +217,10 @@ async def add_images(self, image_entities, image_paths, target_width, include_fi
self.hass.states.get(image_entity).attributes.get(
'entity_picture')
image_data = await self.client._fetch(image_url)

# Skip frame when fetch failed
if not image_data:
continue

# If entity snapshot requested, use entity name as 'filename'
self.client.add_frame(
Expand Down Expand Up @@ -256,6 +265,11 @@ async def add_videos(self, video_paths, event_ids, max_frames, target_width, inc
base_url = get_url(self.hass)
frigate_url = base_url + "/api/frigate/notifications/" + event_id + "/clip.mp4"
clip_data = await self.client._fetch(frigate_url)

# Skip frame when fetch failed
if not clip_data:
continue

# create tmp dir to store video clips
os.makedirs(tmp_clips_dir, exist_ok=True)
_LOGGER.info(f"Created {tmp_clips_dir}")
Expand Down
35 changes: 22 additions & 13 deletions custom_components/llmvision/request_handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -415,20 +415,29 @@ async def _post(self, url, headers, data):
_LOGGER.info(f"Response data: {response_data}")
return response_data

async def _fetch(self, url):
async def _fetch(self, url, max_retries=1, retry_delay=1):
import asyncio
"""Fetch image from url and return image data"""
_LOGGER.info(f"Fetching {url}")
try:
response = await self.session.get(url)
except Exception as e:
raise ServiceValidationError(f"Fetch failed: {e}")

if response.status != 200:
raise ServiceValidationError(
f"Fetch failed with status code {response.status}")

data = await response.read()
return data
retries = 0
while retries < max_retries:
_LOGGER.info(
f"Fetching {url} (attempt {retries + 1}/{max_retries})")
try:
response = await self.session.get(url)
if response.status != 200:
_LOGGER.warning(f"Couldn't fetch frame (status code: {response.status})")
retries += 1
await asyncio.sleep(retry_delay)
continue
data = await response.read()
return data
except Exception as e:
_LOGGER.error(f"Fetch failed: {e}")
retries += 1
await asyncio.sleep(retry_delay)

_LOGGER.error(f"Failed to fetch {url} after {max_retries} retries")
return None

def _validate_call(self, provider, api_key, base64_images, ip_address=None, port=None):
"""Validate the service call data"""
Expand Down
2 changes: 1 addition & 1 deletion custom_components/llmvision/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ stream_analyzer:
default: 5
selector:
number:
min: 0
min: 1
max: 60
max_frames:
name: Max Frames
Expand Down

0 comments on commit dc39f64

Please sign in to comment.