Skip to content

Instantly share code, notes, and snippets.

@evanfoster
Created February 12, 2018 04:22
Show Gist options
  • Save evanfoster/5f335fa2166f976d93e8608490ad3c02 to your computer and use it in GitHub Desktop.
Save evanfoster/5f335fa2166f976d93e8608490ad3c02 to your computer and use it in GitHub Desktop.
Camera switching script for /u/akavMAC
#!/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