#!/usr/bin/env python # python-gphoto2 - Python interface to libgphoto2 # http://github.com/jim-easterbrook/python-gphoto2 # Copyright (C) 2015-22 Jim Easterbrook jim@jim-easterbrook.me.uk # # This file is part of python-gphoto2. # # python-gphoto2 is free software: you can redistribute it and/or modify # it under the terms of the GNU Lesser General Public License as # published by the Free Software Foundation, either version 3 of the # License, or (at your option) any later version. # # python-gphoto2 is distributed in the hope that it will be useful, but # WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # # You should have received a copy of the GNU Lesser General Public # License along with python-gphoto2. If not, see # . import logging import locale import os # ~ import subprocess import sys import gphoto2 as gp camera_current_settings = { 'capturemode' : dict(min=0, max=4, default=0, value=3), # 0: single,1: burst,2:Timer,3:2S Remote,4:Quick remote 'imagesize' : dict(min=0, max=2, default=0, value=2), # 0:L, 1:M, 2: S (1936x1296) 'whitebalance' : dict(min=0, max=7, default=0, value=1), # 0 Automatic 1 Daylight 2 Fluorescent 3 Tungsten 4 Flash 5 Cloudy 6 Shade 7 Preset 'capturetarget' : dict(min=0, max=1, default=0, value=0), # Internal memory # ~ 'nocfcardrelease' : dict(min=0, max=1, default=0, value=0), # Allow capture without sd card # ~ 'recordingmedia' : dict(min=0, max=1, default=0, value=1), # Write to RAM } def initialize_camera(): camera = gp.check_result(gp.gp_camera_new()) try: gp.check_result(gp.gp_camera_init(camera)) # get configuration tree current_camera_config = gp.check_result(gp.gp_camera_get_config(camera)) except: camera.exit() camera = None current_camera_config = None return camera, current_camera_config # TODO: find how to use gp.CameraWidget.get_range() and check parameter value is in range before applying. def apply_gphoto_setting(config, setting, new_value, inc=False): # find the $setting config item try: # Get widget with name $setting cur_setting = gp.check_result(gp.gp_widget_get_child_by_name(config, setting)) # Get a list of available choices choices = list(gp.check_result(gp.gp_widget_get_choices(cur_setting))) # Build dict with name/value equivalence choices_dict = {choices.index(i):i for i in list(choices)} # Increment mode : current value is increased or looped if inc: # Get current setting value new_value = gp.check_result(gp.gp_widget_get_value(cur_setting)) # Check current value + 1 is in range if new_value in range(0, len(choices)): # Apply or loop value accordingly pass # If new_value exists in list, apply if new_value['value'] in choices_dict: cur_setting_choice = gp.check_result(gp.gp_widget_get_choice(cur_setting, new_value['value'])) # set config value gp.check_result(gp.gp_widget_set_value(cur_setting, cur_setting_choice)) except: print("Configuration error while setting {} to {}".format(setting, new_value)) def apply_dslr_settings(camera_settings): camera, config = initialize_camera() # iterate over the settings dictionary for setting in camera_settings: apply_gphoto_setting(config, setting, camera_settings[setting]) # validate config status = gp.check_result(gp.gp_camera_set_config(camera, config)) # close camera camera.exit() return status def check_status_value(config, value, optimal_value=None): cur_check = gp.check_result(gp.gp_widget_get_child_by_name(config, value)) cur_check_value = gp.check_result(gp.gp_widget_get_value(cur_check)) if optimal_value is not None: cur_check_choice = gp.check_result(gp.gp_widget_get_choice(cur_check, optimal_value[value])) return [cur_check_value, cur_check_choice] else: return cur_check_value # ~ def check_status(camera, config): # ~ for value in camera_status: # ~ cur_check_value, cur_check_choice = check_status_value(config, value, camera_status) # ~ if cur_check_value == cur_check_choice: # ~ return True # ~ else: # ~ # Some values are not optimal # ~ return False def find_file_ext(gp_name:str, full_path:str): # extract dir path dirname = os.path.dirname(full_path) # extract filename from path new_name = os.path.basename(full_path) # if the path does'nt contain file name, return camera's FS filename if not full_path.endswith(('.jpg', '.JPG', '.raw')): return gp_name suffix = gp_name.split('.')[-1] prefix = new_name.split('.')[:-1] prefix.insert(len(prefix), suffix) print(suffix) print(prefix) return os.path.join(dirname, '.'.join(prefix)) def capture_and_download(target:str='/tmp'): camera, current_camera_config = initialize_camera() # Check battery level battery_level = int(check_status_value(current_camera_config, 'batterylevel')[:-1]) if battery_level < 10: print("Battery level is too low, shutter disabled.") return False file_path = camera.capture(gp.GP_CAPTURE_IMAGE) print('Camera file path: {0}/{1}'.format(file_path.folder, file_path.name)) print(target) target = find_file_ext(file_path.name, target) print('Copying image to', target) try: camera_file = camera.file_get( file_path.folder, file_path.name, gp.GP_FILE_TYPE_NORMAL) except: print("Camera error. Check Battery and try restarting the camera.") return False try: camera_file.save(target) except: print('File access error.') return False camera.exit() return True def main(): apply_dslr_settings(camera_current_settings) if __name__ == "__main__": logging.basicConfig( format='%(levelname)s: %(name)s: %(message)s', level=logging.ERROR) callback_obj = gp.check_result(gp.use_python_logging()) sys.exit(main())