mirror of
				https://github.com/blakeblackshear/frigate.git
				synced 2025-10-27 10:52:11 +01:00 
			
		
		
		
	Add error handling for unsupported label uploading to frigate+ (#9775)
This commit is contained in:
		
							parent
							
								
									91cdf64602
								
							
						
					
					
						commit
						86341c3172
					
				@ -275,6 +275,13 @@ def send_to_plus(id):
 | 
				
			|||||||
                box,
 | 
					                box,
 | 
				
			||||||
                event.label,
 | 
					                event.label,
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					        except ValueError:
 | 
				
			||||||
 | 
					            message = "Error uploading annotation, unsupported label provided."
 | 
				
			||||||
 | 
					            logger.error(message)
 | 
				
			||||||
 | 
					            return make_response(
 | 
				
			||||||
 | 
					                jsonify({"success": False, "message": message}),
 | 
				
			||||||
 | 
					                400,
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
        except Exception as ex:
 | 
					        except Exception as ex:
 | 
				
			||||||
            logger.exception(ex)
 | 
					            logger.exception(ex)
 | 
				
			||||||
            return make_response(
 | 
					            return make_response(
 | 
				
			||||||
@ -346,6 +353,13 @@ def false_positive(id):
 | 
				
			|||||||
            event.model_type,
 | 
					            event.model_type,
 | 
				
			||||||
            event.detector_type,
 | 
					            event.detector_type,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					    except ValueError:
 | 
				
			||||||
 | 
					        message = "Error uploading false positive, unsupported label provided."
 | 
				
			||||||
 | 
					        logger.error(message)
 | 
				
			||||||
 | 
					        return make_response(
 | 
				
			||||||
 | 
					            jsonify({"success": False, "message": message}),
 | 
				
			||||||
 | 
					            400,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
    except Exception as ex:
 | 
					    except Exception as ex:
 | 
				
			||||||
        logger.exception(ex)
 | 
					        logger.exception(ex)
 | 
				
			||||||
        return make_response(
 | 
					        return make_response(
 | 
				
			||||||
 | 
				
			|||||||
@ -171,6 +171,17 @@ class PlusApi:
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not r.ok:
 | 
					        if not r.ok:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                error_response = r.json()
 | 
				
			||||||
 | 
					                errors = error_response.get("errors", [])
 | 
				
			||||||
 | 
					                for error in errors:
 | 
				
			||||||
 | 
					                    if (
 | 
				
			||||||
 | 
					                        error.get("param") == "label"
 | 
				
			||||||
 | 
					                        and error.get("type") == "invalid_enum_value"
 | 
				
			||||||
 | 
					                    ):
 | 
				
			||||||
 | 
					                        raise ValueError(f"Unsupported label value provided: {label}")
 | 
				
			||||||
 | 
					            except ValueError as e:
 | 
				
			||||||
 | 
					                raise e
 | 
				
			||||||
            raise Exception(r.text)
 | 
					            raise Exception(r.text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def add_annotation(
 | 
					    def add_annotation(
 | 
				
			||||||
@ -193,6 +204,17 @@ class PlusApi:
 | 
				
			|||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not r.ok:
 | 
					        if not r.ok:
 | 
				
			||||||
 | 
					            try:
 | 
				
			||||||
 | 
					                error_response = r.json()
 | 
				
			||||||
 | 
					                errors = error_response.get("errors", [])
 | 
				
			||||||
 | 
					                for error in errors:
 | 
				
			||||||
 | 
					                    if (
 | 
				
			||||||
 | 
					                        error.get("param") == "label"
 | 
				
			||||||
 | 
					                        and error.get("type") == "invalid_enum_value"
 | 
				
			||||||
 | 
					                    ):
 | 
				
			||||||
 | 
					                        raise ValueError(f"Unsupported label value provided: {label}")
 | 
				
			||||||
 | 
					            except ValueError as e:
 | 
				
			||||||
 | 
					                raise e
 | 
				
			||||||
            raise Exception(r.text)
 | 
					            raise Exception(r.text)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_model_download_url(
 | 
					    def get_model_download_url(
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ import Link from '../components/Link';
 | 
				
			|||||||
import { useApiHost } from '../api';
 | 
					import { useApiHost } from '../api';
 | 
				
			||||||
import useSWR from 'swr';
 | 
					import useSWR from 'swr';
 | 
				
			||||||
import useSWRInfinite from 'swr/infinite';
 | 
					import useSWRInfinite from 'swr/infinite';
 | 
				
			||||||
import axios from 'axios';
 | 
					import axios, { AxiosError } from 'axios';
 | 
				
			||||||
import { useState, useRef, useCallback, useMemo } from 'preact/hooks';
 | 
					import { useState, useRef, useCallback, useMemo } from 'preact/hooks';
 | 
				
			||||||
import VideoPlayer from '../components/VideoPlayer';
 | 
					import VideoPlayer from '../components/VideoPlayer';
 | 
				
			||||||
import { StarRecording } from '../icons/StarRecording';
 | 
					import { StarRecording } from '../icons/StarRecording';
 | 
				
			||||||
@ -79,6 +79,7 @@ export default function Events({ path, ...props }) {
 | 
				
			|||||||
    validBox: null,
 | 
					    validBox: null,
 | 
				
			||||||
  });
 | 
					  });
 | 
				
			||||||
  const [uploading, setUploading] = useState([]);
 | 
					  const [uploading, setUploading] = useState([]);
 | 
				
			||||||
 | 
					  const [uploadErrors, setUploadErrors] = useState([]);
 | 
				
			||||||
  const [viewEvent, setViewEvent] = useState(props.event);
 | 
					  const [viewEvent, setViewEvent] = useState(props.event);
 | 
				
			||||||
  const [eventOverlay, setEventOverlay] = useState();
 | 
					  const [eventOverlay, setEventOverlay] = useState();
 | 
				
			||||||
  const [eventDetailType, setEventDetailType] = useState('clip');
 | 
					  const [eventDetailType, setEventDetailType] = useState('clip');
 | 
				
			||||||
@ -328,27 +329,40 @@ export default function Events({ path, ...props }) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    setUploading((prev) => [...prev, id]);
 | 
					    setUploading((prev) => [...prev, id]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const response = false_positive
 | 
					    try {
 | 
				
			||||||
      ? await axios.put(`events/${id}/false_positive`)
 | 
					      const response = false_positive
 | 
				
			||||||
      : await axios.post(`events/${id}/plus`, validBox ? { include_annotation: 1 } : {});
 | 
					        ? await axios.put(`events/${id}/false_positive`)
 | 
				
			||||||
 | 
					        : await axios.post(`events/${id}/plus`, validBox ? { include_annotation: 1 } : {});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (response.status === 200) {
 | 
					      if (response.status === 200) {
 | 
				
			||||||
      mutate(
 | 
					        mutate(
 | 
				
			||||||
        (pages) =>
 | 
					          (pages) =>
 | 
				
			||||||
          pages.map((page) =>
 | 
					            pages.map((page) =>
 | 
				
			||||||
            page.map((event) => {
 | 
					              page.map((event) => {
 | 
				
			||||||
              if (event.id === id) {
 | 
					                if (event.id === id) {
 | 
				
			||||||
                return { ...event, plus_id: response.data.plus_id };
 | 
					                  return { ...event, plus_id: response.data.plus_id };
 | 
				
			||||||
              }
 | 
					                }
 | 
				
			||||||
              return event;
 | 
					                return event;
 | 
				
			||||||
            })
 | 
					              })
 | 
				
			||||||
          ),
 | 
					            ),
 | 
				
			||||||
        false
 | 
					          false
 | 
				
			||||||
      );
 | 
					        );
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      if (
 | 
				
			||||||
 | 
					        e instanceof AxiosError &&
 | 
				
			||||||
 | 
					        (e.response.data.message === 'Error uploading annotation, unsupported label provided.' ||
 | 
				
			||||||
 | 
					          e.response.data.message === 'Error uploading false positive, unsupported label provided.')
 | 
				
			||||||
 | 
					      ) {
 | 
				
			||||||
 | 
					        setUploadErrors((prev) => [...prev, { id, isUnsupported: true }]);
 | 
				
			||||||
 | 
					        return;
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      setUploadErrors((prev) => [...prev, { id }]);
 | 
				
			||||||
 | 
					      throw e;
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					      setUploading((prev) => prev.filter((i) => i !== id));
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    setUploading((prev) => prev.filter((i) => i !== id));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (state.showDownloadMenu && downloadEvent.id === id) {
 | 
					    if (state.showDownloadMenu && downloadEvent.id === id) {
 | 
				
			||||||
      setState({ ...state, showDownloadMenu: false });
 | 
					      setState({ ...state, showDownloadMenu: false });
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@ -681,6 +695,7 @@ export default function Events({ path, ...props }) {
 | 
				
			|||||||
                    viewEvent={viewEvent}
 | 
					                    viewEvent={viewEvent}
 | 
				
			||||||
                    setViewEvent={setViewEvent}
 | 
					                    setViewEvent={setViewEvent}
 | 
				
			||||||
                    uploading={uploading}
 | 
					                    uploading={uploading}
 | 
				
			||||||
 | 
					                    uploadErrors={uploadErrors}
 | 
				
			||||||
                    handleEventDetailTabChange={handleEventDetailTabChange}
 | 
					                    handleEventDetailTabChange={handleEventDetailTabChange}
 | 
				
			||||||
                    onEventFrameSelected={onEventFrameSelected}
 | 
					                    onEventFrameSelected={onEventFrameSelected}
 | 
				
			||||||
                    onDelete={onDelete}
 | 
					                    onDelete={onDelete}
 | 
				
			||||||
@ -721,6 +736,7 @@ export default function Events({ path, ...props }) {
 | 
				
			|||||||
                  lastEvent={lastEvent}
 | 
					                  lastEvent={lastEvent}
 | 
				
			||||||
                  lastEventRef={lastEventRef}
 | 
					                  lastEventRef={lastEventRef}
 | 
				
			||||||
                  uploading={uploading}
 | 
					                  uploading={uploading}
 | 
				
			||||||
 | 
					                  uploadErrors={uploadErrors}
 | 
				
			||||||
                  handleEventDetailTabChange={handleEventDetailTabChange}
 | 
					                  handleEventDetailTabChange={handleEventDetailTabChange}
 | 
				
			||||||
                  onEventFrameSelected={onEventFrameSelected}
 | 
					                  onEventFrameSelected={onEventFrameSelected}
 | 
				
			||||||
                  onDelete={onDelete}
 | 
					                  onDelete={onDelete}
 | 
				
			||||||
@ -760,6 +776,7 @@ function Event({
 | 
				
			|||||||
  lastEvent,
 | 
					  lastEvent,
 | 
				
			||||||
  lastEventRef,
 | 
					  lastEventRef,
 | 
				
			||||||
  uploading,
 | 
					  uploading,
 | 
				
			||||||
 | 
					  uploadErrors,
 | 
				
			||||||
  handleEventDetailTabChange,
 | 
					  handleEventDetailTabChange,
 | 
				
			||||||
  onEventFrameSelected,
 | 
					  onEventFrameSelected,
 | 
				
			||||||
  onDelete,
 | 
					  onDelete,
 | 
				
			||||||
@ -769,6 +786,19 @@ function Event({
 | 
				
			|||||||
  onSave,
 | 
					  onSave,
 | 
				
			||||||
  showSubmitToPlus,
 | 
					  showSubmitToPlus,
 | 
				
			||||||
}) {
 | 
					}) {
 | 
				
			||||||
 | 
					  const getUploadButtonState = (eventId) => {
 | 
				
			||||||
 | 
					    const isUploading = uploading.includes(eventId);
 | 
				
			||||||
 | 
					    const hasUploadError = uploadErrors.find((event) => event.id === eventId);
 | 
				
			||||||
 | 
					    if (hasUploadError) {
 | 
				
			||||||
 | 
					      if (hasUploadError.isUnsupported) {
 | 
				
			||||||
 | 
					        return { isDisabled: true, label: 'Unsupported label' };
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					      return { isDisabled: isUploading, label: 'Upload error' };
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    const label = isUploading ? 'Uploading...' : 'Send to Frigate+';
 | 
				
			||||||
 | 
					    return { isDisabled: isUploading, label };
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
  const apiHost = useApiHost();
 | 
					  const apiHost = useApiHost();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return (
 | 
					  return (
 | 
				
			||||||
@ -849,10 +879,10 @@ function Event({
 | 
				
			|||||||
                ) : (
 | 
					                ) : (
 | 
				
			||||||
                  <Button
 | 
					                  <Button
 | 
				
			||||||
                    color="gray"
 | 
					                    color="gray"
 | 
				
			||||||
                    disabled={uploading.includes(event.id)}
 | 
					                    disabled={getUploadButtonState(event.id).isDisabled}
 | 
				
			||||||
                    onClick={(e) => showSubmitToPlus(event.id, event.label, event?.data?.box || event.box, e)}
 | 
					                    onClick={(e) => showSubmitToPlus(event.id, event.label, event?.data?.box || event.box, e)}
 | 
				
			||||||
                  >
 | 
					                  >
 | 
				
			||||||
                    {uploading.includes(event.id) ? 'Uploading...' : 'Send to Frigate+'}
 | 
					                    {getUploadButtonState(event.id).label}
 | 
				
			||||||
                  </Button>
 | 
					                  </Button>
 | 
				
			||||||
                )}
 | 
					                )}
 | 
				
			||||||
              </Fragment>
 | 
					              </Fragment>
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user