stopi2/dslr_helper.py

163 lines
6.2 KiB
Python
Raw Normal View History

2025-02-02 15:45:05 +01:00
#!/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
# <https://www.gnu.org/licenses/>.
import logging
import locale
import os
# ~ import subprocess
import sys
import gphoto2 as gp
camera_current_settings = {
2025-02-15 10:08:13 +01:00
'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
2025-02-02 15:45:05 +01:00
}
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
2025-02-15 10:08:13 +01:00
# 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):
2025-02-02 15:45:05 +01:00
# find the $setting config item
try:
2025-02-15 10:08:13 +01:00
# Get widget with name $setting
2025-02-02 15:45:05 +01:00
cur_setting = gp.check_result(gp.gp_widget_get_child_by_name(config, setting))
2025-02-15 10:08:13 +01:00
# 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))
2025-02-02 15:45:05 +01:00
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
2025-02-15 10:08:13 +01:00
2025-02-02 15:45:05 +01:00
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())