diff --git a/TODO.md b/TODO.md index 3e674bf..01400d6 100755 --- a/TODO.md +++ b/TODO.md @@ -34,11 +34,12 @@ These are the features actively planned for Predator and are likely to be added - [X] Test configuration updates. - [X] Test config file reconciliation behavior. - [X] Test config behavior from sub-directories. -- [X] Add dash-cam operation mode stamp. - +- [X] Add more dash-cam stamps. + - [X] Add dash-cam operation mode stamp. + - [X] Add custom relay status stamps through GPIO. +- [X] Add default config support for values that involve adding entries. ## Hypothetical Features in this section may be added in the future, but are not actively planned. -- [ ] Add custom relay status stamps through GPIO. diff --git a/assets/support/configdefault.json b/assets/support/configdefault.json index c3e75e4..3699b7d 100755 --- a/assets/support/configdefault.json +++ b/assets/support/configdefault.json @@ -227,9 +227,9 @@ "size": 0.8, "main": { "color": [ - 255, - 255, - 255 + 0, + 0, + 0 ], "unix_time": { "enabled": false @@ -258,6 +258,29 @@ "enabled": true } }, + "relay": { + "enabled": true, + "colors": { + "on": [ + 255, + 0, + 0 + ], + "off": [ + 0, + 0, + 0 + ] + }, + "triggers": { + "horn": { + "enabled": true, + "pin": 0, + "invert": false, + "text": "HORN" + } + } + }, "gps": { "color": [ 0, diff --git a/assets/support/configoutline.json b/assets/support/configoutline.json index 14d897a..971efb0 100755 --- a/assets/support/configoutline.json +++ b/assets/support/configoutline.json @@ -223,6 +223,14 @@ "enabled": "bool" } }, + "relay": { + "enabled": "bool", + "colors": { + "on": "list", + "off": "list" + }, + "triggers": "dict" + }, "gps": { "color": "list", "location": { diff --git a/config.py b/config.py index 26ad763..ef14353 100755 --- a/config.py +++ b/config.py @@ -316,33 +316,37 @@ def highest_different_index(config_active, config_default, index): # This functi return [] +ignore_indexes = [["realtime", "image", "camera", "devices"], ["dashcam", "stamps", "relay", "triggers"], ["dashcam", "capture", "video", "devices"]] # Configure values specified here will not be checked by the check_defaults_missing() and check_defaults_extra() functions. + # This function checks for values that exist in the default config that aren't present in the active config. def check_defaults_missing(config_defaults, config_active, index=[], missing_values=[]): - if (type(config_defaults) == dict): - for key, section in config_defaults.items(): - new_index = index.copy() - new_index.append(key) - config_active, missing_values = check_defaults_missing(section, config_active, new_index, missing_values) - else: - config_active_value = get_nested_value(index, config_active) - if (config_active_value == None): - index_to_set = highest_different_index(config_active, config_defaults, index) - default_value = get_nested_value(index_to_set, load_config(config_default_filepath)) - config_active = set_nested_value(index_to_set, config_active, default_value) - missing_values.append(index) + if (index not in ignore_indexes): # Only continue if the specified index is not ignored. + if (type(config_defaults) == dict): + for key, section in config_defaults.items(): + new_index = index.copy() + new_index.append(key) + config_active, missing_values = check_defaults_missing(section, config_active, new_index, missing_values) + else: + config_active_value = get_nested_value(index, config_active) + if (config_active_value == None): + index_to_set = highest_different_index(config_active, config_defaults, index) + default_value = get_nested_value(index_to_set, load_config(config_default_filepath)) + config_active = set_nested_value(index_to_set, config_active, default_value) + missing_values.append(index) return config_active, missing_values # This function checks for values that exist on the active config that aren't present in the default config. def check_defaults_extra(config_defaults, config_active, index=[], extra_values=[]): - if (type(config_active) == dict): - for key, section in config_active.items(): - new_index = index.copy() - new_index.append(key) - extra_values = check_defaults_extra(config_defaults, section, new_index) - else: - config_default_value = get_nested_value(index, config_defaults) - if (config_default_value == None): - extra_values.append(index) + if (index not in ignore_indexes): # Only continue if the specified index is not ignored. + if (type(config_active) == dict): + for key, section in config_active.items(): + new_index = index.copy() + new_index.append(key) + extra_values = check_defaults_extra(config_defaults, section, new_index) + else: + config_default_value = get_nested_value(index, config_defaults) + if (config_default_value == None): + extra_values.append(index) return extra_values # This function checks the active config file against the default config file, and attempts to reconcile any differences. Irreconcileable differences will cause Predator to exit, and a notice will be displayed. diff --git a/dashcam.py b/dashcam.py index af7b79d..2a7c539 100755 --- a/dashcam.py +++ b/dashcam.py @@ -53,6 +53,11 @@ import lighting # Import the lighting.py script. update_status_lighting = lighting.update_status_lighting # Load the status lighting update function from the lighting script. +for stamp in config["dashcam"]["stamps"]["relay"]["triggers"]: # Check to see if there are any GPIO relay stamps active. + if (config["dashcam"]["stamps"]["relay"]["triggers"][stamp]["enabled"] == True): # Check to see if at least one relay stamp is enabled. + from gpiozero import Button # Import GPIOZero + break # Exit the loop, since GPIOZero has already been imported. + if (config["dashcam"]["saving"]["looped_recording"]["mode"] == "manual"): # Only validate the manual history length if manual looped recording mode is enabled. @@ -244,6 +249,11 @@ def save_dashcam_segments(file1, file2=""): process_timing("end", "Dashcam/File Maintenance") +relay_triggers = {} +for stamp in config["dashcam"]["stamps"]["relay"]["triggers"]: + if (config["dashcam"]["stamps"]["relay"]["triggers"][stamp]["enabled"] == True): # Check to see if this relay stamp is enabled. + relay_trigger[stamp] = Button(int(config["dashcam"]["stamps"]["relay"]["triggers"][stamp]["pin"])) + def apply_dashcam_stamps(frame, device=""): global instant_framerate @@ -293,6 +303,21 @@ def apply_dashcam_stamps(frame, device=""): diagnostic_stamp = diagnostic_stamp + "PA" + if (config["dashcam"]["stamps"]["relay"]["enabled"] == True): # Check to see if relay stamp features are enabled before processing the relay stamp. + stamp_number = 0 + for stamp in config["dashcam"]["stamps"]["relay"]["triggers"]: + if (config["dashcam"]["stamps"]["relay"]["triggers"][stamp]["enabled"] == True): # Check to see if this relay stamp is enabled. + if (relay_trigger[stamp].is_pressed): # Check to see if the relay is triggered. + relay_stamp_color = config["dashcam"]["stamps"]["relay"]["color"]["on"] + else: + relay_stamp_color = config["dashcam"]["stamps"]["relay"]["color"]["off"] + relay_stamp = config["dashcam"]["stamps"]["relay"]["triggers"][stamp]["text"] # Set the relay stamp text to a blank placeholder. Elements will be added to this in the next steps. + (label_width, label_height), baseline = cv2.getTextSize(relay_stamp, 2, config["dashcam"]["stamps"]["size"], 1) + relay_stamp_position = [width - 10 - label_width, (30 * stamp_number) + round(30 * config["dashcam"]["stamps"]["size"])] # Determine where the diagnostic overlay stamp should be positioned in the video stream. + cv2.putText(frame, relay_stamp, (relay_stamp_position[0], relay_stamp_position[1]), 2, config["dashcam"]["stamps"]["size"], (relay_stamp_color[2], relay_stamp_color[1], relay_stamp_color[0])) # Add the relay overlay stamp to the video stream. + stamp_number += 1 + + gps_stamp_position = [10, 30] # Determine where the GPS overlay stamp should be positioned in the video stream. gps_stamp = "" # Set the GPS to a blank placeholder. Elements will be added to this in the next steps. if (config["general"]["gps"]["enabled"] == True): # Check to see if GPS features are enabled before processing the GPS stamp.