123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- #!/usr/bin/env python3
- """
- Module Docstring
- """
- __author__ = "Nikola Kotur"
- __version__ = "0.1"
- __license__ = "MIT"
- import os
- import sys
- import argparse
- import threading
- import tempfile
- import subprocess
- from pprint import pprint as pp
- import pyudev
- from logzero import logger
- class USBDetector():
- ''' Monitor udev for detection of usb '''
-
- def __init__(self, handler, source_dir, dest_dir, ftp_args):
- ''' Initiate the object '''
- self.usb_plugged_in = handler
- self.source_dir = source_dir
- self.dest_dir = dest_dir
- self.ftp_args = ftp_args
- thread = threading.Thread(target=self._work)
- thread.daemon = True
- thread.start()
- thread.join()
- def _work(self):
- ''' Runs the actual loop to detect the events '''
- self.context = pyudev.Context()
- self.monitor = pyudev.Monitor.from_netlink(self.context)
- self.monitor.filter_by(subsystem='block')
- # this is module level logger, can be ignored
- logger.info("Starting to monitor for usb")
- self.monitor.start()
- for device in iter(self.monitor.poll, None):
- logger.debug("Got USB event: %s", device.action)
- if device.action == 'add' and device.device_type == 'partition':
- # some function to run on insertion of usb
- self.usb_plugged_in(device, self.source_dir, self.dest_dir, self.ftp_args)
- def execute(shell_command):
- shell_command = shell_command.split(' ')
- try:
- res = subprocess.check_output(shell_command, stderr=subprocess.PIPE)
- return res.decode('utf-8')
- except subprocess.CalledProcessError as e:
- print('exit code: {}'.format(e.returncode))
- print('stdout: {}'.format(e.output.decode(sys.getfilesystemencoding())))
- print('stderr: {}'.format(e.stderr.decode(sys.getfilesystemencoding())))
- return None
- def parse_video_files(usb_dir, base_dir, extension):
- files = {}
- for file in os.listdir(os.path.join(usb_dir, base_dir)):
- if file.endswith(extension):
- full_path = (os.path.join(usb_dir, base_dir, file))
- file_parts = file.split('_')
- part_date = file_parts[0]
- if part_date not in files:
- files[part_date] = []
- files[part_date].append(full_path)
- return files
- def join_video_files(dest, sources):
- with tempfile.TemporaryDirectory() as tmpdirname:
- list_file = os.path.join(tmpdirname, 'list')
- with open(list_file, 'w') as lfh:
- for source_line in sources:
- lfh.write("file '%s'\n" % source_line)
- ffmpeg_line = 'ffmpeg -safe 0 -f concat -i %s -c copy %s' % (list_file, dest)
- output = execute(ffmpeg_line)
- if output != None:
- logger.info('Removing source files')
- for s_file in sources:
- os.remove(s_file)
- return True
- return False
- def plugged_in(dev, source_dir, dest_dir, ftp):
- logger.info('Detected %s (%s)', dev.device_node, dev.device_type)
- with tempfile.TemporaryDirectory() as tmpdirname:
- logger.info('Mounting %s on %s', dev.device_node, tmpdirname)
- output = execute('mount %s %s' % (dev.device_node, tmpdirname))
- # Join files
- joined_files = []
- for file_group, files in parse_video_files(tmpdirname, source_dir, 'MP4').items():
- logger.info('Joining video group %s', file_group)
- outfile_name = '%s.mp4' % file_group
- outfile_path = os.path.join(dest_dir, outfile_name)
- if join_video_files(outfile_path, files):
- joined_files.append(outfile_path)
- logger.info('Umounting %s from %s', dev.device_node, tmpdirname)
- output = execute('umount %s' % (dev.device_node))
- # Beam files to FTP
- for up_file in joined_files:
- logger.info('Uploading %s to %s', up_file, ftp['host'])
- execute('ncftpput -u %s -p %s %s %s %s' % (ftp['user'], ftp['password'], ftp['host'], ftp['path'], up_file))
- logger.info('Done')
- def main(args):
- """ Main entry point of the app """
- ftp_args = {
- 'host': args.ftp_host,
- 'path': args.ftp_path,
- 'user': args.ftp_user,
- 'password': args.ftp_password,
- }
- usb_detect = USBDetector(plugged_in, args.source, args.destination, ftp_args)
- if __name__ == "__main__":
- """ This is executed when run from the command line """
- parser = argparse.ArgumentParser()
- # Optional argument flag which defaults to False
- parser.add_argument("-f", "--flag", action="store_true", default=False)
- # Directory options
- parser.add_argument("-s", "--source", help="source directory with dashcam videos", action="store", dest="source", default="DCIM/Movie")
- parser.add_argument("-d", "--destination", help="destination directory for joined dashcam videos", action="store", dest="destination", default="/var/dashcam")
- # FTP options
- parser.add_argument("--ftp-host", help="ftp host (server)", action="store", default="192.168.88.242")
- parser.add_argument("--ftp-path", help="ftp path", action="store", default="/dashcam")
- parser.add_argument("--ftp-user", help="ftp user", action="store", default="dashcam")
- parser.add_argument("--ftp-password", help="ftp user", action="store", default="")
- # Optional verbosity counter (eg. -v, -vv, -vvv, etc.)
- parser.add_argument(
- "-v",
- "--verbose",
- action="count",
- default=0,
- help="Verbosity (-v, -vv, etc)")
- # Specify output of "--version"
- parser.add_argument(
- "--version",
- action="version",
- version="%(prog)s (version {version})".format(version=__version__))
- args = parser.parse_args()
- main(args)
|