config = { "ssh": { "user": "timelapse", "host": "10.0.0.69", "path": "~/" }, # Interval in seconds at which images are taken "interval": 5, # Amount of images allowed in buffer. If the device were to lose connection they would be kept in buffer until connected again. Max size depends on ram available "buffer_size": 200 } import datetime import logging import subprocess import threading import time # Images are appended to this list before being uploaded, we store them in a variable to reduce disk writes image_buffer = [] def main(): logging.basicConfig(level=logging.DEBUG, format='[%(asctime)s] %(levelname)s: %(message)s', datefmt='%Y-%m-%d %H:%M:%S') logging.info("Started") t_image_handler = threading.Thread(target=image_handler) t_image_handler.start() t_image_uploader = threading.Thread(target=image_uploader) t_image_uploader.start() while True: logging.debug(f"[Buffer entries: {len(image_buffer)}] [Active threads: {threading.active_count()}]") if len(image_buffer) >= config["buffer_size"]: logging.error("Image buffer limit exceeded!!! Connection lost?") else: subprocess.Popen("termux-camera-photo -c 0 image_buffer_pipe", shell=True) time.sleep(config["interval"]) # Appends image recieved from fifo into image_buffer def image_handler(): while True: # Wait for data to arrive with open("image_buffer_pipe", "rb") as binary_file: binary_file = binary_file.read() # For each file we recieve one that is empty, idk why but we skip it if not binary_file: continue image_buffer.append( [ datetime.datetime.now(), binary_file ] ) # Uploads image to remote server then removes image from image_buffer def image_uploader(): while True: time.sleep(config["interval"]) while image_buffer: # WARNING: I HAVE NO IDEA WHAT I'M DOING # Here we pipe the image binary data into ssh and run a remote command. In this case, the remote command is 'cat >filename' which will copy stdin into the 'filename' file proc = subprocess.run( f"ssh '{config['ssh']['user']}@{config['ssh']['host']}' 'cat >{config['ssh']['path']}{image_buffer[0][0].strftime('%Y%m%d_%H%M%S_%f')}.jpg'", stdout=subprocess.PIPE, input=image_buffer[0][1], encoding=None, shell=True ) if proc.returncode == 0: image_buffer.pop(0) else: logging.error(f"Command 'SSH' returned non-zero exit status {proc.returncode}") break if __name__ == "__main__": main()