From 5e3e8d274bb45f51d74f49f96a816dff62c48892 Mon Sep 17 00:00:00 2001 From: Calin Crisan Date: Sat, 12 Oct 2013 21:23:28 +0300 Subject: [PATCH] implemented media files cleanup --- doc/todo.txt | 4 +-- motioneye.py | 16 ++++++++++- settings.py | 3 ++ src/cleanup.py | 72 +++++++++++++++++++++++++++++++++++++++++++++++ src/config.py | 6 ++-- src/handlers.py | 2 +- static/js/main.js | 2 -- 7 files changed, 96 insertions(+), 9 deletions(-) create mode 100644 src/cleanup.py diff --git a/doc/todo.txt b/doc/todo.txt index ccb284c..a127156 100644 --- a/doc/todo.txt +++ b/doc/todo.txt @@ -1,4 +1,6 @@ +-> implement file preserving + -> style scroll bars -> hint text next to section titles -> clickable hints @@ -10,12 +12,10 @@ -> add a previewer for snapshots -> add a motioneye.svg icon --> implement file preserving -> add other options applicable only to special devices (rpi): wifi settings, notifications -> group @config rules to top -> browser compatibility test -> requirements test --> add a motion running status indicator (and maybe a start/stop button) -> other todos diff --git a/motioneye.py b/motioneye.py index 88570b8..aaea8ff 100755 --- a/motioneye.py +++ b/motioneye.py @@ -134,14 +134,28 @@ def _start_motion(): logging.info('motion started') ioloop = tornado.ioloop.IOLoop.instance() - ioloop.add_timeout(datetime.timedelta(seconds=10), checker) + ioloop.add_timeout(datetime.timedelta(seconds=settings.MOTION_CHECK_INTERVAL), checker) checker() +def _start_cleanup(): + import cleanup + + def do_cleanup(): + cleanup.cleanup_images() + cleanup.cleanup_movies() + + ioloop = tornado.ioloop.IOLoop.instance() + ioloop.add_timeout(datetime.timedelta(seconds=settings.CLEANUP_INTERVAL), do_cleanup) + + do_cleanup() + + if __name__ == '__main__': _configure_settings() _configure_signals() _configure_logging() _start_motion() + _start_cleanup() _start_server() diff --git a/settings.py b/settings.py index 6eeb272..3131e6c 100644 --- a/settings.py +++ b/settings.py @@ -18,3 +18,6 @@ STATIC_URL = '/static/' LISTEN = '0.0.0.0' PORT = 8765 + +MOTION_CHECK_INTERVAL = 10 +CLEANUP_INTERVAL = 10 diff --git a/src/cleanup.py b/src/cleanup.py new file mode 100644 index 0000000..ed6d25e --- /dev/null +++ b/src/cleanup.py @@ -0,0 +1,72 @@ + +import datetime +import logging +import os + +import config + + +def _remove_older_files(dir, moment): + for name in os.listdir(dir): + full_path = os.path.join(dir, name) + if not os.path.isfile(full_path): + continue + + file_moment = datetime.datetime.fromtimestamp(os.path.getmtime(file)) + if file_moment < moment: + logging.debug('removing file %(path)s...' % { + 'path': full_path}) + + #os.remove(full_path) + + +def cleanup_images(): + logging.debug('cleaning up images...') + + for camera_id in config.get_camera_ids(): + camera_config = config.get_camera(camera_id) + if camera_config.get('@proto') != 'v4l2': + continue + + preserve_images = camera_config.get('@preserve_images') + if preserve_images == 0: + return # preserve forever + + preserve_moment = datetime.datetime.now() - datetime.timedelta(days=preserve_images) + + target_dir = camera_config.get('target_dir') + snapshot_filename = camera_config.get('snapshot_filename') + jpeg_filename = camera_config.get('snapshot_jpeg') + + if snapshot_filename: + snapshot_path = os.path.join(target_dir, snapshot_filename) + snapshot_path = os.path.dirname(snapshot_path) + _remove_older_files(dir, preserve_moment) + + if jpeg_filename: + snapshot_path = os.path.join(target_dir, jpeg_filename) + snapshot_path = os.path.dirname(snapshot_path) + _remove_older_files(dir, preserve_moment) + + +def cleanup_movies(): + logging.debug('cleaning up movies...') + + for camera_id in config.get_camera_ids(): + camera_config = config.get_camera(camera_id) + if camera_config.get('@proto') != 'v4l2': + continue + + preserve_movies = camera_config.get('@preserve_movies') + if preserve_movies == 0: + return # preserve forever + + preserve_moment = datetime.datetime.now() - datetime.timedelta(days=preserve_movies) + + target_dir = camera_config.get('target_dir') + movie_filename = camera_config.get('movie_filename') + + if movie_filename: + snapshot_path = os.path.join(target_dir, movie_filename) + snapshot_path = os.path.dirname(snapshot_path) + _remove_older_files(dir, preserve_moment) diff --git a/src/config.py b/src/config.py index d1db8e2..3fdbaed 100644 --- a/src/config.py +++ b/src/config.py @@ -22,7 +22,7 @@ _camera_ids_cache = None def get_main(as_lines=False): global _main_config_cache - if not as_lines and _main_config_cache: + if not as_lines and _main_config_cache is not None: return _main_config_cache config_file_path = os.path.join(settings.PROJECT_PATH, _MAIN_CONFIG_FILE_PATH) @@ -119,7 +119,7 @@ def set_main(data): def get_camera_ids(): global _camera_ids_cache - if _camera_ids_cache: + if _camera_ids_cache is not None: return _camera_ids_cache config_path = settings.CONF_PATH @@ -166,7 +166,7 @@ def has_enabled_cameras(): def get_camera(camera_id, as_lines=False): global _camera_config_cache - if not as_lines and _camera_config_cache and camera_id in _camera_config_cache: + if not as_lines and _camera_config_cache is not None and camera_id in _camera_config_cache: return _camera_config_cache[camera_id] camera_config_path = _CAMERA_CONFIG_FILE_PATH % {'id': camera_id} diff --git a/src/handlers.py b/src/handlers.py index 04c959f..6980c86 100644 --- a/src/handlers.py +++ b/src/handlers.py @@ -757,7 +757,7 @@ class ConfigHandler(BaseHandler): class SnapshotHandler(BaseHandler): - #@asynchronous TODO don't forget about me + @asynchronous def get(self, camera_id, op, filename=None): if camera_id is not None: camera_id = int(camera_id) diff --git a/static/js/main.js b/static/js/main.js index 4de18ce..6fd6d42 100644 --- a/static/js/main.js +++ b/static/js/main.js @@ -160,9 +160,7 @@ function initUI() { /* text validators */ makeTextValidator($('#adminUsernameEntry'), true); - makeTextValidator($('#adminPasswordEntry'), true); makeTextValidator($('#normalUsernameEntry'), true); - makeTextValidator($('#normalPasswordEntry'), true); makeTextValidator($('#deviceNameEntry'), true); makeTextValidator($('#networkServerEntry'), true); makeTextValidator($('#networkShareNameEntry'), true); -- 2.39.5