Created
February 12, 2018 04:22
-
-
Save evanfoster/5f335fa2166f976d93e8608490ad3c02 to your computer and use it in GitHub Desktop.
Camera switching script for /u/akavMAC
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# Remember to either chmod +x this file and call it like this: | |
# */15 * * * * /path/to/foo.py >/dev/null 2>&1 | |
# Or invoke with python3 like this: | |
# */15 * * * * python3 /path/to/foo.py >/dev/null 2>&1 | |
from subprocess import run | |
username = 'User' | |
password = 'Pass' | |
omxplayer_start_command = """screen -dmS ipc{} sh -c 'omxplayer --live --refresh --fps {} --win "{}" rtsp://{}:{}@{}/h264/ch1/sub/av_stream'""" | |
# The below could easily be in a JSON configuration file. Then you could just do this and have the script be super short | |
# import json | |
# with open('config_file_path') as file_descriptor: | |
# cameras = json.load(file_descriptor) | |
# As things are, I've baked the config into the script. | |
cameras = { | |
'1': { | |
'fps': '30', | |
'window_size': '0 0 1008 1050', | |
'ip_address': '192.168.1.50', | |
'status': { | |
'0': {'kill': ['1'], 'start': '7'}, | |
'1': {'kill': ['7', '4', '5'], 'start': '1'} | |
} | |
}, | |
'2': { | |
'fps': '15', | |
'window_size': '1008 0 1680 350', | |
'ip_address': '192.168.1.51', | |
'status': { | |
'0': {'kill': ['2'], 'start': '8'}, | |
'1': {'kill': ['8'], 'start': '2'} | |
} | |
}, | |
'3': { | |
'fps': '15', | |
'window_size': '1008 350 1680 700', | |
'ip_address': '192.168.1.52', | |
'status': { | |
'0': {'kill': ['3'], 'start': '9'}, | |
'1': {'kill': ['9'], 'start': '3'} | |
} | |
}, | |
'4': { | |
'fps': '15', | |
'window_size': '840 0 1680 350', | |
'ip_address': '192.168.1.53', | |
'status': { | |
'0': {'kill': [], 'start': None}, | |
'1': {'kill': [], 'start': '4'} | |
} | |
}, | |
'5': { | |
'fps': '15', | |
'window_size': '840 350 1680 700', | |
'ip_address': '192.168.1.54', | |
'status': { | |
'0': {'kill': [], 'start': None}, | |
'1': {'kill': [], 'start': '5'} | |
} | |
}, | |
'6': { | |
'fps': '15', | |
'window_size': '1008 700 1680 1050', | |
'ip_address': '192.168.1.55', | |
'status': { | |
'0': {'kill': ['6'], 'start': '10'}, | |
'1': {'kill': ['10'], 'start': '6'} | |
} | |
}, | |
'7': { | |
'fps': '15', | |
'window_size': '0 0 840 350', | |
'ip_address': '192.168.1.50', | |
}, | |
'8': { | |
'fps': '15', | |
'window_size': '0 350 840 700', | |
'ip_address': '192.168.1.51', | |
}, | |
'9': { | |
'fps': '15', | |
'window_size': '0 700 840 1050', | |
'ip_address': '192.168.1.52', | |
}, | |
'10': { | |
'fps': '15', | |
'window_size': '840 700 1680 1050', | |
'ip_address': '192.168.1.55', | |
} | |
} | |
# Whew! Alright. Your script actually has pretty complex logic. There might be ways to simplify that, but it's not | |
# really my place to do so if there are. | |
# Previously, you had the relationship between cameras codified in your if statements and what you did in them. | |
# I tend to prefer more declarative style config, so cameras 1-6 have a status key in them. | |
# If the grep for those camera's pids returns a 0 (which means grep found something) then I perform one set of actions, | |
# and if it's 1 (the other value grep will return, which means it couldn't find anything) then I'll perform a different | |
# set of actions. That way, there's only one piece of actual code, and the config dictates the relationships between | |
# all of the cameras, namely which ones to kill and which one to start. The kill key is a list since you kill multiple | |
# cameras if st1 is not running. | |
for camera_number in range(1, 7): | |
# For stupid techincal reasons, all of the integer keys in our dict above are strings. Namely, JSON doesn't like | |
# keys that aren't strings. In order to make it easy to turn this into something that reads from a JSON config file, | |
# I'm going to pretend that I'm already reading from one and cast our camera_number variable to a string. | |
camera_number = str(camera_number) | |
# Grep for a specific camera running. I dunno if the cut statements are necessary here, since we're just checking | |
# the return value now. I've left them out for simplicities sake. | |
# See that {} thingy there? That's how you do string interpolation in Python. In Bash you can just do this: | |
# ps -ef | grep omxplayer | grep ipc$some_variable | |
# Python doesn't do that. It's actually a much better design, but that means that you need to do the {} thingy and | |
# put .format at the end of your string. | |
result = run('''ps -ef | grep omxplayer | grep ipc{}'''.format(camera_number), shell=True) | |
# Again, casting this to a string because JSON is kinda dumb sometimes. YAML is way better but isn't in the stdlib. | |
camera_is_running = str(result.returncode) | |
# Pull out what to do with this specific camera based on whether is was running or not. | |
camera_info = cameras[camera_number]['status'][camera_is_running] | |
cameras_to_kill = camera_info['kill'] | |
camera_to_start = camera_info['start'] | |
for camera_to_kill in cameras_to_kill: | |
# Using the old method to kill cameras because I can't test against the actual environment. I'd recommend | |
# changing this to use pkill instead. | |
run('''kill $(ps aux | grep ipc{} | awk '{{print $2}}')'''.format(camera_to_kill), shell=True) | |
if camera_to_start is None: | |
# In the cases of cameras 4 and 5, you don't start anything if the camera is already running. | |
continue | |
camera = cameras[camera_to_start] | |
camera_fps, camera_window_size, camera_ip_address = camera['fps'], camera['window_size'], camera['ip_address'] | |
run(omxplayer_start_command.format( | |
camera_to_start, camera_fps, camera_window_size, username, password, camera_ip_address), shell=True) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment