# ==============================================================================
# FindFace configuration file
# ==============================================================================
#
# This config file is written in Python's syntax and interpreted at FindFace
# service startup. You have to restart the service in order to apply changes.
#
# If you have any questions or suggestions, please contact us at support@ntechlab.com


# ==============================================================================
# GENERAL SETTINGS
# ==============================================================================
CIBR = False

# USE_X_FORWARDED_HOST = True
# SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'https')

# enables debug options
DEBUG = False

# media files directory
MEDIA_ROOT = "/var/lib/findface-security/uploads"

# fast temporary storage for event files (fullframe, thumbnail)
FAST_MEDIA_ROOT = None

# static files directory
STATIC_ROOT = "/var/lib/findface-security/static"

# language code
LANGUAGE_CODE = 'en-us'

# time zone in tz format e.g.'Africa/Abidjan'
# DANGER - WARNING! Etc/GMT+3 means UTC-3
TIME_ZONE = 'UTC'

# Database is used to store cameras, camera groups, watchlists and so on.
# Only PostgreSQL is supported.
DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'DISABLE_SERVER_SIDE_CURSORS': True,
        'NAME': 'ffsecurity', 'HOST': 'pgbouncer', 'PORT': 6432, 'USER': 'ntech', 'PASSWORD': 'f9RFmizHMMmsgo6hucXjrmGf1miT2qKP'
    }
}

# Signature key for session encryption
# Use pwgen -sncy 50 1|tr "'" "." to generate your own unique key
SECRET_KEY = '2dc52a7079ebe87b7430185be8340398'

# ==============================================================================
# FINDFACE SETTINGS
# ==============================================================================

# SERVICE_EXTERNAL_ADDRESS is prioritized for webhooks.
# EXTERNAL_ADDRESS is used instead if SERVICE_EXTERNAL_ADDRESS is not provided.
# You must provide either SERVICE_EXTERNAL_ADDRESS or EXTERNAL_ADDRESS in order
# to be able to work with webhooks.
SERVICE_EXTERNAL_ADDRESS = 'http://172.17.47.211'

# EXTERNAL_ADDRESS is used to access created objects via external links.
EXTERNAL_ADDRESS = 'http://172.17.47.211'

# Specify VIDEO_ARCHIVE_SOURCE_URL to get access to uploaded videos
# if not specified then EXTERNAL_ADDRESS is used
VIDEO_ARCHIVE_SOURCE_URL = ''

# - Base settings -

FFSECURITY = {
    'ENABLE_TELEGRAM': False,
    # auth config
    # available options: face, password, face_and_password, face_or_password
    'AUTH_TYPE': 'face_or_password',
    # 180 days by default
    'MAXIMUM_SESSION_LENGTH': 15552000,
    # maximum amount of simultaneous active tokens
    'MAXIMUM_ALLOWED_TOKENS': 100,
    # findface-video-worker authorization token
    'VIDEO_DETECTOR_TOKEN': '53770e022d5e1982f2d78a84fcf41497',
    # optional objects to detect
    'ENABLE_FACES': True,
    'ENABLE_CARS': True,
    'ENABLE_BODIES': True,
    # base face matching confidence threshold
    'FACE_CONFIDENCE_THRESHOLD': 0.702,  # FAR = 1.00E-08 # model: [nectarine_l_320]
    # base body matching confidence threshold
    'BODY_CONFIDENCE_THRESHOLD': 0.65,  # model: [durga]
    # base car matching confidence threshold
    'CAR_CONFIDENCE_THRESHOLD': 0.65,  # model: [bottas]
    # episodes specific matching threshold that is used to join faces in an episode
    'FACE_EPISODES_THRESHOLD': 0.663,  # FAR = 1.00E-06  # model: [nectarine_l_320]
    'BODY_EPISODES_THRESHOLD': 0.75,  # model: [durga]
    'CAR_EPISODES_THRESHOLD': 0.61,  # model: [bottas]
    # minimum confidence for license plate number, country and region identification
    'MIN_CAR_LICENSE_PLATE_CONFIDENCE': 0.01,  # model: [carattr.license_plate.v11]
    # NOTE. quality settings below do not apply to new events,
    # change video manager job's `filter_min_quality` (camera setting) to filter events
    # minimum face quality sufficient to add it to a card and use object in counter
    'MINIMUM_FACE_QUALITY': 0.42,  # model: [faceattr.quality.v5]
    # minimum body quality sufficient to add it to a card and use object in counter
    'MINIMUM_BODY_QUALITY': 0.6,  # model: [pedattr.quality.v0]
    # minimum car quality sufficient to add it to a card and use object in counter
    # p.s. set this parameter equals to `0.73` for more accurate results
    'MINIMUM_CAR_QUALITY': 0.6,  # model: [carattr.quality.v1]
    # car matching options
    'CAR_MATCHING': {
        'events': {
            'alternative_matching': False,
            'alternative_matching_filters': {
                'color': {'enabled': False, 'min_confidence': 0.1},
                'body': {'enabled': True, 'min_confidence': 0.1},
                'make': {'enabled': True, 'min_confidence': 0.1},
                'model': {'enabled': True, 'min_confidence': 0.1},
                'special_vehicle_type': {'enabled': True, 'min_confidence': 0.1},
                'category': {'enabled': False, 'min_confidence': 0.1},
                'weight_type': {'enabled': False, 'min_confidence': 0.1},
            },
        },
        'episodes': {
            'track': True,
            'alternative_matching': False,
            'alternative_matching_filters': {
                'emben': {'enabled': True},  # uses CAR_EPISODES_THRESHOLD
                'color': {'enabled': False, 'min_confidence': 0.1},
                'body': {'enabled': True, 'min_confidence': 0.1},
                'make': {'enabled': True, 'min_confidence': 0.1},
                'model': {'enabled': True, 'min_confidence': 0.1},
                'special_vehicle_type': {'enabled': True, 'min_confidence': 0.1},
                'category': {'enabled': False, 'min_confidence': 0.1},
                'weight_type': {'enabled': False, 'min_confidence': 0.1},
            },
        },
    },
    'ALLOW_CAR_EPISODES_WITHOUT_LICENSE_PLATE': False,
    # use additional features for extra confidence when matching body by emben
    'EXTRA_BODY_MATCHING': {
        'bottom_color': {'enabled': False, 'min_confidence': 0},
        'top_color': {'enabled': False, 'min_confidence': 0},
        'headwear': {'enabled': False, 'min_confidence': 0},
        'detailed_upper_clothes': {'enabled': False, 'min_confidence': 0},
        'upper_clothes': {'enabled': False, 'min_confidence': 0},
        'lower_clothes': {'enabled': False, 'min_confidence': 0},
        'helmet_type': {'enabled': False, 'min_confidence': 0},
        'vest_type': {'enabled': False, 'min_confidence': 0},
        'age_group': {'enabled': False, 'min_confidence': 0},
        'gender': {'enabled': False, 'min_confidence': 0},
    },
    # do not save unmatched events (GDPR support)
    'IGNORE_UNMATCHED': False,
    # blur all unmatched objects on the full frame of the matched event (GDPR support)
    'BLUR_UNMATCHED_OBJECTS': False,
    # full frame jpeg quality when `BLUR_UNMATCHED_OBJECTS` is enabled
    'BLURRED_FULLFRAME_JPEG_QUALITY': 85,
    # rrule (recurrence rule) for scheduling cleanup service
    'CLEANUP_SCHEDULE': 'RRULE:FREQ=DAILY;BYHOUR=1;BYMINUTE=17',
    # matched face events older than EVENTS_MAX_MATCHED_AGE seconds will be automatically
    # deleted (every night at 1:17 am by default)
    'FACE_EVENTS_MAX_MATCHED_AGE': 30*24*60*60,
    # same as above but for unmatched face events (in seconds)
    'FACE_EVENTS_MAX_UNMATCHED_AGE': 30*24*60*60,
    # same as EVENTS_MAX_MATCHED_AGE but for matched full frame face images only (thumbnails won't be deleted)
    # (in seconds)
    'FACE_EVENTS_MAX_FULLFRAME_MATCHED_AGE': 30*24*60*60,
    # same as above but for unmatched full frame face images only (thumbnails won't be deleted) (in seconds)
    'FACE_EVENTS_MAX_FULLFRAME_UNMATCHED_AGE': 30*24*60*60,
    # same as above but for car events (in seconds)
    'CAR_EVENTS_MAX_MATCHED_AGE': 30*24*60*60,
    'CAR_EVENTS_MAX_UNMATCHED_AGE': 30*24*60*60,
    'CAR_EVENTS_MAX_FULLFRAME_MATCHED_AGE': 30*24*60*60,
    'CAR_EVENTS_MAX_FULLFRAME_UNMATCHED_AGE': 30*24*60*60,
    # same as above but for body events (in seconds)
    'BODY_EVENTS_MAX_MATCHED_AGE': 30*24*60*60,
    'BODY_EVENTS_MAX_UNMATCHED_AGE': 30*24*60*60,
    'BODY_EVENTS_MAX_FULLFRAME_MATCHED_AGE': 30*24*60*60,
    'BODY_EVENTS_MAX_FULLFRAME_UNMATCHED_AGE': 30*24*60*60,
    # same as above but for counter records (in seconds)
    'COUNTER_RECORDS_MAX_AGE': 30*24*60*60,
    # same as above but for cluster events (if no cluster events left in cluster, it is deleted too) (in seconds)
    'FACE_CLUSTER_EVENTS_MAX_AGE': 180*24*60*60,
    'BODY_CLUSTER_EVENTS_MAX_AGE': 180*24*60*60,
    'CAR_CLUSTER_EVENTS_MAX_AGE': 180*24*60*60,
    # same as above but keep best cluster event (in seconds)
    'FACE_CLUSTER_EVENTS_KEEP_BEST_MAX_AGE': 90*24*60*60,
    'BODY_CLUSTER_EVENTS_KEEP_BEST_MAX_AGE': 90*24*60*60,
    'CAR_CLUSTER_EVENTS_KEEP_BEST_MAX_AGE': 90*24*60*60,
    # same as above but for audit logs (in seconds)
    'AUDIT_LOGS_MAX_AGE': 0,
    # available are: face, body, car
    'CREATE_EPISODE_FROM_OBJECT_TYPES': ['face', 'body', 'car'],
    # when closing episode, delete all events except the best episode event
    'EPISODE_KEEP_ONLY_BEST_EVENT': False,
    # delete episode events after delay in seconds
    'EPISODE_DELETE_EVENTS_DELAY': 60,
    # NTLS licence server url
    'NTLS_HTTP_URL': 'http://findface-ntls:3185',
    'IDENTITY_PROVIDER_URL': 'http://findface-multi-identity-provider:8002',
    # findface-video-worker face posting address,
    # it must be set to either EXTERNAL_ADDRESS (by default)
    # or findface-facerouter url (in some specific cases)
    'ROUTER_URL': 'http://findface-multi-ui',
    # send serialized cards, card-lists, camera and camera groups in webhooks
    'VERBOSE_WEBHOOKS': True,
    # jpeg quality used when saving thumbnails
    'THUMBNAIL_JPEG_QUALITY': 75,
    # multiply bbox diagonal to this coefficient for thumbnails
    'THUMBNAIL_SCALE': {
        'face': 1.2,
        'body': 1,
        'car': 1,
    },
    # FFServer services urls
    'VIDEO_MANAGER_ADDRESS': 'http://findface-video-manager:18810',
    'SF_API_ADDRESS': 'http://findface-sf-api:18411',
    'DEDUPLICATOR_ADDRESS': 'http://findface-deduplicator:18310',
    'LIVENESS_API_ADDRESS': 'http://findface-liveness-api:18301',
    'VIDEO_STORAGE_ADDRESS': 'http://findface-video-storage:18611',
    # do not change video-streamer ip:port (external-vms only)
    'VIDEO_STREAMER_ADDRESS': 'http://findface-video-streamer-cpu:9000',
    # upload video archives to this path, it differs from media root
    'VIDEO_ARCHIVE_UPLOAD_PATH': '/var/lib/findface-security/uploads/videos/',
    # additional events features
    # make sure that corresponding extractors are licensed
    # and enabled at findface-extraction-api config file
    # available features: age, beard, emotions, gender, glasses, headpose, medmask, eyes_attrs
    'FACE_EVENTS_FEATURES': ['eyes_attrs', 'gender', 'emotions', 'age', 'medmask', 'glasses', 'beard', 'headpose'],
    # available features: age_gender, bags, clothes, color, protective_equipment, fall, handface, phoneuse
    'BODY_EVENTS_FEATURES': ['color', 'bags', 'clothes', 'age_gender', 'handface', 'protective_equipment', 'phoneuse', 'fall'],
    # available features: category, description, license_plate, orientation, special_vehicle_type, weight_type
    # Make sure to read following caution before adding `special_vehicle_type` and weight_type features
    # in case its' added in findface-extraction-api.yaml (car_special_vehicle_types11) and (car_weight_types7):
    # 1) `weight_type` neural network was trained Russian Federation's transport only
    # 2) `special_vehicle_type` neural network works more efficient on russians` special vehicle
    # 3) `special_vehicle_type` neural network is not quite sufficient for car sharing
    'CAR_EVENTS_FEATURES': ['category', 'weight_type', 'license_plate', 'orientation', 'special_vehicle_type', 'description'],
    'CAR_SPECIAL_VEHICLE_TYPE_EXTRACTOR': 'car_special_types12',
    'FACE_GLASSES_EXTRACTOR': 'face_glasses4',
    # null features depending on `category` and `weight_type` of a vehicle
    'CAR_EVENTS_FEATURES_TO_NULL': {
        'category': {
            # features, that will be nulled for all categories
            'default': ['make', 'body', 'model', 'color'],
            'unknown': ['make', 'body', 'model', 'color'],
            # categories with other behavior
            'B': [],
        },
        'weight_type': {
            # features, that will be nulled for all weight types
            'default': ['make', 'body', 'model', 'color'],
            # weight types with other behavior
            'B_light': [],
            'B_heavy': [],
        },
    },
    # feature specific confidence thresholds
    'LIVENESS_THRESHOLD': 0.885,  # model: [faceattr.liveness_pacs.v3]
    'BEARD_THRESHOLD': 0.7,  # model: [beard]
    'BAG_HAND_THRESHOLD': 0.605,  # model: [bags.v0]
    'BAG_BACK_THRESHOLD': 0.642,  # model: [bags.v0]
    'BAG_GROUND_THRESHOLD': 0.1,  # model: [bags.v0]
    'FALL_THRESHOLD': 0.72,  # FAR = 0.001 # model: [pedattr.fall.v1]
    'HANDFACE_SMOKING_THRESHOLD': 0.7,  # model: [pedattr.handface.v1]
    'HANDFACE_PHONE_USE_THRESHOLD': 0.469,  # model: [pedattr.handface.v1]
    'HANDFACE_PHONE_CALL_THRESHOLD': 0.495,  # model: [pedattr.handface.v1]
    'HANDFACE_PHOTO_THRESHOLD': 0.5,  # model: [pedattr.phoneuse.v0]
    # if top2 emotion confidence greater than this value, top2 emotion return instead of top1
    'EMOTIONS_THRESHOLD': 0.25,  # model: [emotions.v1]
    # If the confidence of a car attribute recognition is below the threshold specified in this setting,
    # the recognized value will be lost, and FindFace Multi will display 'unknown' instead of it.
    'CAR_DESCRIPTION_THRESHOLD': {
        'make': 0.5,
        'model': 0.5,
        'body': 0.5,
        'color': 0.5,
    },  # model: [carattr.description.v1]
    'SPECIAL_VEHICLE_TYPE_THRESHOLD': 0.5,  # model: [special_types12.v0]
    'CAR_CATEGORY_THRESHOLD': 0.75,  # model: [carattr.categories.v1]
    'CAR_WEIGHT_TYPE_THRESHOLD': 0.5,  # model: [weight-types7.v0]
    'CAR_ORIENTATION_THRESHOLD': 0.8,  # model  [orientation.v0]
    # counters full frame saving options:
    # `always` - save always
    # `detect` - save only if faces, silhouettes or cars have been detected
    # `never` - never save full frames
    'COUNTERS_SAVE_FULLFRAME': 'always',
    'COUNTERS_FULLFRAME_JPEG_QUALITY': 75,
    'COUNTERS_THUMBNAIL_JPEG_QUALITY': 75,
    # required percentage of bbox intersection with ROI
    'COUNTERS_ROI_INTERSECTION_THRESHOLD': 0.75,
    'COUNTERS_MAX_SLEEP_ON_START': 10,  # in seconds
    'COUNTERS_SCREENSHOT_TIMEOUT': 15,  # in seconds
    'COUNTERS_DETECTION_TASK_TIMEOUT': 15,  # in seconds
    # global limit devided equally among general workers
    'COUNTERS_MAX_CONCURRENT_SCREENSHOT_FETCHES': 100,
    # screenshot handler timeout
    'SCREENSHOT_HANDLER_TIMEOUT': 60,
    # max camera frames_dropped percent
    'MAX_CAMERA_DROPPED_FRAMES': {'yellow': 0.1, 'red': 0.3},
    # max camera objects failed percent
    'MAX_CAMERA_FAILED_OBJECTS': {'yellow': 0.1, 'red': 0.3},
    # Counter health status config:
    # max percent of camera records with errors
    'MAX_COUNTER_ERROR_RECORDS': {'yellow': 0, 'red': 0.7},
    # -- Clusters configuration --
    'ENABLE_NIGHT_CLUSTERIZATION': False,
    'ENABLE_REALTIME_CLUSTERIZATION': False,
    # rrule (recurrence rule) for scheduling "night" clusterization
    'CLUSTERIZATION_SCHEDULE': 'RRULE:FREQ=DAILY;INTERVAL=1;WKST=MO;BYHOUR=0;BYMINUTE=0',
    # clusterize only selected objects types (for realtime and nightly clusterization)
    # available are: face, body, car
    'CLUSTERIZE_OBJECT_TYPES': [],
    # use no more than N the best quality events to calculate centroid and cluster features (None to disable)
    'CENTROID_MAX_SIZE': 20,
    # save cluster events without emben and images (only keep thumbnail for the best event)
    'LONG_LIVING_CLUSTER_EVENTS': False,
    # skip clusterization if unpinned cluster events count is greater than this value
    'CLUSTERIZATION_MAX_CLUSTER_EVENTS': None,
    # cluster event to cluster matching confidence threshold
    'FACE_CLUSTER_CONFIDENCE_THRESHOLD': 0.702,  # FAR = 1.00E-08 # model: [nectarine_l_320]
    'BODY_CLUSTER_CONFIDENCE_THRESHOLD': 0.65,  # model: [durga]
    # minimum required event quality for cluster creation
    'FACE_CLUSTER_EVENT_MIN_QUALITY': 0.42,  # model: [faceattr.quality.v5]
    'BODY_CLUSTER_EVENT_MIN_QUALITY': 0.6,  # model: [pedattr.quality.v0]
    'CAR_CLUSTER_EVENT_MIN_QUALITY': 0.6,  # model: [carattr.quality.v1]
    # discard cluster event if `max_centroids` similar centroids found with confidence greater than `confidence`
    'FACE_CLUSTER_MAX_N_SIMILAR': {'enabled': False, 'max_centroids': 5, 'confidence': 0.702},  # FAR = 1.00E-08 # model: [nectarine_l_320]
    'BODY_CLUSTER_MAX_N_SIMILAR': {'enabled': False, 'max_centroids': 5, 'confidence': 0.65},
    # minimum required object size in pixels for cluster creation
    'FACE_CLUSTER_EVENT_MIN_SIZE': 50,
    'BODY_CLUSTER_EVENT_MIN_SIZE': 50,
    'CAR_CLUSTER_EVENT_MIN_SIZE': 50,
    # minimum required number events in episode for cluster creation
    'FACE_CLUSTER_EVENT_MIN_EPISODE_EVENTS': 1,
    'BODY_CLUSTER_EVENT_MIN_EPISODE_EVENTS': 1,
    'CAR_CLUSTER_EVENT_MIN_EPISODE_EVENTS': 1,
    # age feature threshold for cluster creation
    'FACE_CLUSTER_EVENT_MIN_AGE_THRESHOLD': 16,
    # headpose feature thresholds for cluster creation (in º)
    'FACE_CLUSTER_EVENT_HEADPOSE_THRESHOLDS_ENABLE': False,
    'FACE_CLUSTER_EVENT_YAW_ANGLE_LOWEST_THRESHOLD': -30,
    'FACE_CLUSTER_EVENT_YAW_ANGLE_HIGHEST_THRESHOLD': 30,
    'FACE_CLUSTER_EVENT_PITCH_ANGLE_LOWEST_THRESHOLD': -60,
    'FACE_CLUSTER_EVENT_PITCH_ANGLE_HIGHEST_THRESHOLD': 60,
    # coefficient of dependence of the clustering threshold on the cluster event's quality
    'FACE_CLUSTER_SOFT_CLUSTERIZATION_COEFFICIENT': 0.1,
    'BODY_CLUSTER_SOFT_CLUSTERIZATION_COEFFICIENT': 0.1,
    # match with clusters when no card objects matches found
    'MATCH_CLUSTERS': False,
    # pinned clusters keep their id and events after reclusterization
    'CLUSTERS_AUTO_PIN_HEURISTICS': {
        'face': {
            # pin clusters with `value` minimum cluster events
            'min_events': {'enabled': True, 'value': 10},
            # cluster's centroid similarity confidence is less than
            'max_centroid_similarity_threshold': {'enabled': True, 'value': 0.545},  # FAR = 0.075 # nectarine_l_320
            # minimum average event's quality
            'min_average_events_quality': {'enabled': True, 'value': 0.42},
        },
        'body': {},
        'car': {},
    },
    # always pin clusters with matched events (not affected by heuristics above)
    'PIN_MATCHED_CLUSTERS': False,
    # maximum concurrent video manager jobs for video archives processing
    'MAX_VIDEO_ARCHIVE_JOBS': 3,
    # reports image saving options
    'REPORT_THUMBNAIL_JPEG_QUALITY': 75,
    'REPORT_THUMBNAIL_MAX_HEIGHT': 100,
    'REPORT_FULLFRAME_JPEG_QUALITY': 75,
    'REPORT_FULLFRAME_MAX_HEIGHT': 250,
    # authorization token for POST /events/{face, car, body}/add
    'EVENTS_CREATION_API_TOKEN': '53770e022d5e1982f2d78a84fcf41497',
    'EVENTS_CREATION_API_SERIALIZE_EVENTS': False,
    # save audit logs
    'ENABLE_AUDIT_LOGS': True,
    # -- Startup tests --
    # required services availability test
    'SERVICES_AVAILABILITY_TEST': True,
    # -- Onvif --
    # auth credentials for ffsecurity_onvif plugin
    # ONVIF_CREDENTIALS: [
    #     {
    #         "hostnames": ["192.168.1.64", "2a00:1370:8117:ab87:a614:37ff:fe49:2683"],
    #         "username": "admin",
    #         "password": "admin123"
    #     }
    # ],
    'ONVIF_CREDENTIALS': [],
    # list of all hostnames that will be ignored during Onvif service discovery
    # ONVIF_IGNORE_LIST: ["192.168.1.217"],
    'ONVIF_IGNORE_LIST': [],
    # ONVIF Client timeout
    'ONVIF_CLIENT_TIMEOUT': 15,
    # -- Optional parameters --
    # Regular expression to filter files uploaded to card-attachments. All files are allowed by default.
    # For example, to allow only files with png extension - specify r'.*.png$' or r'.*(.png|.jpg)$'
    # to allow png and jpg extensions. You can specify any valid Python regular expression.
    'CARD_ATTACHMENTS_FILENAME_REGEXP': None,
    # maximum event age in seconds than could be added to an episode.
    'FACE_EPISODE_SEARCH_INTERVAL': 60,
    'BODY_EPISODE_SEARCH_INTERVAL': 60,
    'CAR_EPISODE_SEARCH_INTERVAL': 60,
    # maximum episode duration (episode is closed after)
    'EPISODE_MAX_DURATION': 300,
    # if no new event added to an episode during this timeout, episode will be closed.
    'EPISODE_EVENT_TIMEOUT': 30,
    # maximum created thumbnail width
    'THUMBNAIL_MAX_WIDTH': 320,
    # unacknowledged events notification interval
    'UNACKNOWLEDGED_NOTIFY_INTERVAL': 1,
    # number of events concurrently processed in each worker
    'VIDEO_PROCESSING_BATCH_SIZE': 2,
    # failed process tries before dropping event and interrupting video processing
    # high value might DDOS extraction-api
    'VIDEO_MAX_EVENT_PROCESS_TRIES': 1,
    # -- Overprotect media --
    # Set to True to run all media requests (photos, attachments) through the django application for acl checks.
    # Enabling this setting slightly increases security but has severe negative effects on performance.
    # You will also have to mark /uploads/ location as 'internal' in nginx config
    'OVERPROTECT_MEDIA': False,
    # send ws-messages when internal models change
    'WS_BINDINGS': {
        'ENABLED': False,
        'SERIALIZE_MODELS': False,
        'MODELS': [
            # 'user',
            # 'group',
            # 'humancard',
            # 'carcard',
            # 'watchlist',
            # 'cameragroup',
            # 'camera',
            # 'runtimesetting',
            # 'videoarchive',
            # 'webhook',
            # 'counter',
            # 'faceobject',
            # 'bodyobject',
            # 'carobject',
        ],
    },
    # save full detector params from video worker request
    'SAVE_DETECTOR_PARAMS': False,
    'VMS_CLEANUP_SETTINGS': {
        'CLEANUP_BETWEEN_TRACKS': True,
        'CLEANUP_ARCHIVE': True,
        'ARCHIVE_CLEANUP_AGE': 30,  # days
        'BETWEEN_TRACKS_CLEANUP_START_AGE': 0,  # days
        'KEEP_EVENT_TYPES': ['face', 'body', 'car'],
        # Add `safe_time_interval` in seconds to each `track` subject to delete
        # Prevents deletion of essential data.
        # Should be lower than CLEANUP_THRESHOLD
        'KEEP_EVENT_BEFORE_AFTER': 10,  # minimal allowed value
        # Threshold between `intervals` in seconds.
        # If duration between `tracks` < `CLEANUP_THRESHOLD`
        # interval between tracks will not be added to deletion tasks
        'CLEANUP_THRESHOLD': 360,  # minimal allowed value
    },
    # rrule (recurrence rule) for scheduling `vms_cleanup` service. disabled_frequencies=['SECONDLY', 'MINUTELY']
    'VMS_CLEANUP_SERVICE_SCHEDULE': 'RRULE:FREQ=HOURLY;INTERVAL=3;WKST=MO',
    # -- External VMS integration settings --
    # cleanup settings
    'EXTERNAL_VMS_EVENTS_MAX_AGE': 0,
    'EXTERNAL_VMS_SEND_EVENTS_STATUS_MAX_AGE': 0,
    'EXTERNAL_VMS': {
        'ENABLED': False,
        'PLUGIN_ADDRESS': 'http://127.0.0.1:18333',
        'TOKEN': 'VmsPluginToken PLUGIN_TOKEN',
        'EVENT_SENDER': {
            'ENABLED': False,
            'ALLOWED_TYPES': ['face'],
            'SENDER_TASKS': 1,
            'MAX_SEND_ATTEMPTS': 1,
            'MIN_EVENT_SEND_TIMEOUT': 0.1,
            'MAX_EVENT_SEND_TIMEOUT': 100,
            'RESPONSE_TIMEOUT': 10,
        },
    },
    # enable line crossing correction by proximity
    'LINE_CROSSING_CORRECTION': False,
    # line crossing correction by proximity (in percents of frame height), always uses to prevent backward_line_crossing
    'LINE_CROSSING_CORRECTION_DIST': 1,
    # Installer uses only
    'MIGRATE_LIVENESS': True,

    'VIDEO_MANAGER_TIMEOUT': 10,
    'VIDEO_MANAGER_MAX_RETRIES': 3,
    'VIDEO_STORAGE_TIMEOUT': 10,
    'VIDEO_STORAGE_MAX_RETRIES': 3,
    'SF_API_TIMEOUT': 40,
    'SF_API_MAX_RETRIES': 3,
    'LIVENESS_API_TIMEOUT': 10,
    'LIVENESS_API_MAX_RETRIES': 3,
    'DEDUPLICATOR_TIMEOUT': 10,
    'DEDUPLICATOR_MAX_RETRIES': 3,
    'IDENTITY_PROVIDER_TIMEOUT': 10,
    'IDENTITY_PROVIDER_MAX_RETRIES': 3,

    'GEOCODING': {
        'SERVICE_NAME': 'NOMINATIM',
        'NOMINATIM': {
            'ADDRESS': 'https://nominatim.openstreetmap.org',
        }
    },
    'ANNEX_URL': 'http://findface-multi-ui/service_alarmer/alarms/',
    'CBS': {
        'ENABLED': False,
        'URL': 'http://127.0.0.1/match_persons',
        'LIMIT': 2,
        'SSL': False,
        'TIMEOUT': 5
    },
    # -- Custom model fields --
    # Edit CUSTOM_FIELDS -> `human_card` section to customize human card fields.
    # Edit CUSTOM_FIELDS -> `car_card` section to customize car card fields.
    # Edit CUSTOM_FIELDS -> `face_object` section to customize face object fields.
    # Edit CUSTOM_FIELDS -> `car_object` section to customize car object fields.
    # Edit CUSTOM_FIELDS -> `body_object` section to customize body object fields.
    # Edit CUSTOM_FIELDS -> `camera_meta` section to customize camera fields.
    # Below is an example with every field type possible.
    # 'CUSTOM_FIELDS': {
    #     'human_card': {
    #         'options': {
    #             'list': {
    #                 'name': True
    #             }
    #         },
    #         'items': [
    #             {
    #                 'name': 'personid',
    #                 'default': '',
    #                 'label': 'PersonID',
    #                 'display': ['list', 'form'],
    #                 'description': 'Sigur person ID',
    #                 'editable': False
    #             },
    #             {
    #                 'name': 'firstname',
    #                 'default': '',
    #                 'label': 'First Name',
    #                 'display': ['list', 'form'],
    #                 'description': 'Sigur first name',
    #                 'editable': False
    #             },
    #             {
    #                 'name': 'lastname',
    #                 'default': '',
    #                 'label': 'Last Name',
    #                 'display': ['list', 'form'],
    #                 'description': 'Sigur last name',
    #                 'editable': False
    #             },
    #             {
    #                 'name': 'version',
    #                 'default': '',
    #                 'label': 'Version',
    #                 'display': ['list', 'form'],
    #                 'description': 'Sigur photo version',
    #                 'editable': False
    #             },
    #             {
    #                 'name': 'division_name',
    #                 'default': '',
    #                 'label': 'Perco division name',
    #                 'display': ['list', 'form'],
    #                 'description': 'Perco division name',
    #                 'editable': False
    #             },
    #             {
    #                 'name': 'division_id',
    #                 'default': '',
    #                 'label': 'Perco division ID',
    #                 'display': ['list', 'form'],
    #                 'description': 'Perco division ID',
    #                 'editable': False
    #             }
    #         ],
    #         'filters': [
    #             {
    #                 'name': 'personid',
    #                 'label': 'Sigur person ID filter',
    #                 'field': 'personid'
    #             },
    #             {
    #                 'name': 'division_id',
    #                 'label': 'Perco division ID filter',
    #                 'field': 'division_id'
    #             },
    #             {
    #                 'name': 'division_name',
    #                 'label': 'Perco division name filter',
    #                 'field': 'division_name'
    #             }
    #         ]
    #     },
    #     'car_card': {}, # same fields are available
    #     'camera_meta': {
    #         'items': [
    #             {
    #                 'name': 'bit_camera_id',
    #                 'default': None,
    #                 'label': 'BIT camera id',
    #                 'display': ['list', 'form'],
    #                 'description': 'Camera id in BIT system',
    #             },
    #             {
    #                 'name': 'bit_send_events',
    #                 'default': False,
    #                 'label': 'Send events to BIT',
    #                 'display': ['list', 'form'],
    #                 'description': 'Either send events to BIT or not',
    #             }
    #         ],
    #         'filters': [
    #             {
    #                 'name': 'bit_camera_id',
    #                 'label': 'BIT camera id',
    #                 'field': 'bit_camera_id'
    #             },
    #             {
    #                 'name': 'bit_send_events',
    #                 'label': 'Send events to BIT',
    #                 'field': 'bit_send_events',
    #                 'parse_json': True
    #             }
    #         ]
    #     },
    #     'face_object': {
    #         'items': [
    #             {
    #                 "field_name": "tag_name_1",
    #                 "type": "string",
    #                 "default": "change_me"
    #             },
    #             {
    #                 "field_name": "tag_name_2",
    #                 "type": "uint",
    #                 "default": 123
    #             },
    #             {
    #                 "field_name": "tag_name_3",
    #                 "type": "bool",
    #                 "default": True
    #             },
    #         ]
    #     }
    # },
}

# -- Authorization configuration dictionary --

FFSECURITY_AUTH_CONFIG = {
    'FACE_AUTH_CONFIDENCE': 0.702,  # FAR = 1.00E-08 # model: [nectarine_l_320]
    # 3 settings below are for front-end only
    # session renew works only with face or face_or_password authorization type
    'NEED_SESSION_RENEW': False,
    'RENEW_SESSION_INTERVAL': 0,
    'MAXIMUM_RENEW_ATTEMPTS': 2,
}

# ==============================================================================
# FINDFACE SERVER CONFIG
# ==============================================================================
# consult support before changing these settings.

IPC_BACKEND_TYPE = 'nats'
IPC_CONFIG = {
    'nats': {
        'servers': ['nats://nats:4222'],
    }
}

PERSISTENT_BROKER_TYPE = 'nats-jetstream'
PERSISTENT_BROKER_CONFIG = {
    'nats-jetstream': {
        'servers': ['nats://nats-jetstream:4222'],
    }
}

ETCD_CONFIG = {
    'host': 'etcd',
    'port': 2379,
}

# per worker thread pool size.
ASGI_THREADS = 32

UVICORN_SETTINGS = {
    # worker processes count,
    # 'auto' sets it to logical cpu count
    'workers': 'auto',
    'host': '0.0.0.0',
    'port': 8002,
    # websocket worker processes count,
    # 'auto' sets it to logical cpu count
    'ws-workers': 'auto',
    'ws-host': '0.0.0.0',
    'ws-port': 8003,
    # django worker processes count,
    # 'auto' sets it to logical cpu count
    'django-workers': 0,
    'django-host': '0.0.0.0',
    'django-port': 8004,
    # sharding options,
    # do not change if you do not know exactly what you are doing
    'first-worker-id': 0,  # first worker id for this server
    'total-workers': 'auto',  # total workers of this type from all servers
    'first-ws-worker-id': 0,
    'total-ws-workers': 'auto',
    'first-django-worker-id': 0,
    'total-django-workers': 'auto',
}

# disable unused services to increase
# overall system performance in some cases.
SERVICES = {
    "ffsecurity": {
        "episodes": True,
        "webhooks": True,
        "vms_cleanup": False,
    }
}

# -- Other settings --

# The number of threads in the night clusterization.
# Not recommended values are greater than the number of cores in the processor.
# Consult with support before changing this value.
NUMPY_OMP_NUM_THREADS = 'auto'

# ==============================================================================
# EXTERNAL STORAGE CONFIG
# ==============================================================================
# available STORAGE_TYPE are: `AWS`, `LOCAL`
# AS for `LOCAL` use s3 compatible storage service. For example minio
EXTERNAL_STORAGE_CONFIG = {
    'STORAGE_TYPE': None,
    'STORAGE_BUCKET_NAME': 'ffsec.storage',
    'ACCESS_KEY_ID': 'access-key',
    'SECRET_ACCESS_KEY': 'secret-key',
    'REGION_NAME': 'eu-west-3',
    'LOCAL_S3_SETTINGS': {
        'CONNECTION_ADDRESS': 'localhost:9003',
    },
}

# ==============================================================================
# PROMETHEUS METRICS CONFIG
# ==============================================================================
PROMETHEUS_METRICS = {
    'enabled': False,
    'push_gateway_job': 'pushgateway',
    'push_gateway_url': 'http://127.0.0.1:9091',
    'runtime_metrics': {
        'enabled': True,
        'collect_interval': 5,
    },
    'push_interval': 5,
}

# ==============================================================================
# PLUGINS
# ==============================================================================
# Uncomment lines below to enable plugins. Please consult documentation for
# plugin specific settings.


# ============== Puppeteer ===============
# INSTALLED_APPS.append('ffsecurity_puppeteer')

# PUPPETEER_CONFIG = {
#     'UNSAVED_RESULTS_DELETION_TIMEOUT': 3600,        # maximum lifetime of search results not saved involuntarily
#     'REMOTE_MONITORING_SYNC_INTERVAL': 600,          # monitoring data synchronization interval, seconds
#     'REMOTE_MONITORING_EVENTS_MAX_AGE': 30*24*60*60, # monitoring events older than this number of seconds will be
#                                                      # automatically deleted (every night at 1:17 am by default)
#     'ENABLE_WATCH_LISTS_MONITORING': False,
#     'DAILY_SEARCH_PUSH_HOUR': 2,                     # daily search cards synchronization hour
#     'DAILY_SEARCH_PULL_HOUR': 6,                     # hour in which results of daily search will be obtained
#     'DAILY_SEARCH_EVENTS_MAX_AGE': 0,                # daily search events older than this number of seconds will be
#                                                      # automatically deleted (every night at 1:17 am by default)
#     'DAILY_SEARCH_EVENTS_FULLFRAME_MAX_AGE': 30*24*60*60,  # daily search events fullframes
#                                                      # older than this number of seconds will be
#                                                      # automatically deleted (every night at 1:17 am by default)
#     'puppets': [
#         {
#             'id': 'first_puppet',                    # puppet ID
#             'url': 'http://1.1.1.1:8010/',           # puppet URL
#             'token': 'first_puppet_token',           # use pwgen -s 64 1 (should match the token in puppet)
#             'facen_model': 'mango_320'           # face model in puppet
#         },
#         {
#             'id': 'second_puppet',
#             'url': 'http://1.1.1.1:8010/',
#             'token': 'second_puppet_token',
#
#              # if remote installation has a different face model than the one used in this installation -
#              # you need to specify its name and ExtractionAPI URL where the corresponding face model is specified
#              # other settings like detector, normalizer and other should be set as puppeteer's ExtractionAPI
#              # contact support for details
#             'facen_model': 'grapefruit_480',
#             'extractor': 'http://127.0.0.1:18667',
#         },
#     ]
# }
#
# ================= Vns ==================
# A plugin for using FindFace as a puppeteer server
# increasing CONCURRENCY might speedup remote monitoring
# INSTALLED_APPS.append('ffsecurity_vns')

# VNS_CONFIG = {
#     'USERS': {
#         'user1': 'token1',
#         'user2': 'token2'
#     },
#     'MONITORING_THRESHOLD': 0.75,
#     'DAILY': {
#         'ENABLED': False,
#         'THRESHOLD': 0.75,
#         'SEARCH_LIMIT': 100,
#         'START_TIME': "00:00:00"
#     },
#     'CONCURRENCY': 5,
# }

# ================= BIT ==================
# A plugin for using FindFace with BIT
# INSTALLED_APPS.append('ffsecurity_bit')

# BIT_CONFIG = {
#     'URL_ENDPOINT': '',
#     'TOKEN': '',
#     'CONFIDENCE_THRESHOLD': 0.79,
#     'SEND_ATTEMPTS': 5,
#     'SESSION_TIMEOUT': 10,
#     'RESEND_DELAY': 0.1,
#     'MODEL_NAME': '',
# }

CONSOLE_LOG = True
