diff --git a/component/timelapse.py b/component/timelapse.py index f25138a..0c3e9b2 100644 --- a/component/timelapse.py +++ b/component/timelapse.py @@ -70,6 +70,7 @@ def __init__(self, confighelper: ConfigHelper) -> None: 'enabled': True, 'mode': "layermacro", 'camera': "", + 'gphoto2_camera_model': "", 'snapshoturl': "http://localhost:8080/?action=snapshot", 'stream_delay_compensation': 0.05, 'gcode_verbose': False, @@ -464,25 +465,48 @@ async def newframe(self) -> None: # make sure webcamconfig is uptodate before grabbing a new frame await self.getWebcamConfig() - options = "" - if self.wget_skip_cert: - options += "--no-check-certificate " - self.framecount += 1 framefile = "frame" + str(self.framecount).zfill(6) + ".jpg" - cmd = "wget " + options + self.config['snapshoturl'] \ - + " -O " + self.temp_dir + framefile self.lastframefile = framefile - logging.debug(f"cmd: {cmd}") - - shell_cmd: SCMDComp = self.server.lookup_component('shell_command') - scmd = shell_cmd.build_shell_command(cmd, None) - try: - cmdstatus = await scmd.run(timeout=2., verbose=False) - except Exception: - logging.exception(f"Error running cmd '{cmd}'") result = {'action': 'newframe'} + cmdstatus = False + + # Route to appropriate camera handler + if self.config['gphoto2_camera_model'] != "": + framepath = os.path.join(self.temp_dir, framefile) + # Build gphoto2 command + # --camera selects which camera to use needs model from gphoto2 --auto-detect + # --capture-image-and-download folder/file captures and downloads in one operation + cmd = f"gphoto2 --camera '{self.config['gphoto2_camera_model']}' --capture-image-and-download --filename '{framepath}'" + logging.debug(f"Executing gphoto2 command: {cmd}") + + shell_cmd: SCMDComp = self.server.lookup_component('shell_command') + scmd = shell_cmd.build_shell_command(cmd, None) + + try: + cmdstatus = await scmd.run(timeout=5., verbose=False) + except Exception: + logging.exception(f"Error executing gphoto2 command: {cmd}") + + else: + # Default webcam capture via wget + options = "" + if self.wget_skip_cert: + options += "--no-check-certificate " + + cmd = "wget " + options + self.config['snapshoturl'] \ + + " -O " + self.temp_dir + framefile + logging.debug(f"cmd: {cmd}") + + shell_cmd: SCMDComp = self.server.lookup_component('shell_command') + scmd = shell_cmd.build_shell_command(cmd, None) + try: + cmdstatus = await scmd.run(timeout=2., verbose=False) + except Exception: + logging.exception(f"Error running cmd '{cmd}'") + + # Process result if cmdstatus: result.update({ 'frame': str(self.framecount), diff --git a/docs/configuration.md b/docs/configuration.md index 0ead318..f33fe28 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -240,6 +240,7 @@ does. #previewimage: True #saveframes: False #wget_skip_cert_check: False +#gphoto2_camera_model: Nikon DSC D40 (PTP mode) ``` @@ -267,4 +268,44 @@ To get that change at every klipper start: [delayed_gcode _INIT_TIMELAPSE_CHECK_TIME] initial_duration: 1 gcode: SET_GCODE_VARIABLE MACRO=TIMELAPSE_TAKE_FRAME VARIABLE=check_time VALUE=0.5 -``` \ No newline at end of file +``` +# gphoto2 Configuration + +## Connect Your Camera + +1. Connect camera via USB +2. Enable PTP/USB mode on camera (varies by model) +3. Verify detection: + +```bash +gphoto2 --auto-detect +``` + +You should see your camera listed: + +```bash +Model Port +---------------------------------------------------------- +Nikon DSC D40 (PTP mode) usb:003,004 +``` + +## Update Configuration + +Add a dummy webcam and give it a stream and snapshot URL that is not in use. +Select that Camara in the timelaps menue. +Set the Stream Delay Compensation to the amount of time it takes to focus and take a picture (setting it to manual focus decreases the time taken) + +Edit `moonraker.conf`: + +```ini +[timelapse] +gphoto2_camera_model = Nikon DSC D40 (PTP mode) +``` + +## Camera "Device busy" + +```bash +# Kill any process using camera +killall gvfs-gphoto2-volume-monitor +killall gphoto2 +``` \ No newline at end of file diff --git a/docs/installation.md b/docs/installation.md index 1731216..767d366 100644 --- a/docs/installation.md +++ b/docs/installation.md @@ -51,3 +51,19 @@ managed_services: klipper moonraker Please see [configuration.md](configuration.md) for details on how to configure the timelapse component. + + +# Install gphoto2 if an External camara is to be used like a Nikon D40 + +```bash +# Debian/Ubuntu/Raspbian +sudo apt-get update +sudo apt-get install gphoto2 +``` + +## Support for gphoto2 + +For issues: +1. Check `moonraker.log` for errors +2. Test gphoto2 manually: `gphoto2 --camera '{Model}' --capture-image-and-download --filename '/tmp/test_Image000001.jpg'` +3. Verify camera compatibility at: http://gphoto.org/proj/libgphoto2/support.php \ No newline at end of file