strix

A simple web UI for motion
git clone https://www.brianlane.com/git/strix
Log | Files | Refs | LICENSE

commit 59b1dab522d543f21060034a374f1044ee41fa70
parent 934b891da6608da11ce6af6d7ad14f51268b3951
Author: Brian C. Lane <bcl@brianlane.com>
Date:   Sat,  4 Jun 2022 17:16:46 -0700

api: Add reading the cameras from the motion config

This requires adding 'camera_name' to the thread-X.conf files, and it
also gets the stream_port which it uses to sort the cameras into the
order to be displayed.

Diffstat:
Msrc/strix/__init__.py | 15++++++++++++---
Msrc/strix/api.py | 6+++---
Msrc/strix/ui/index.html | 12+++++++-----
3 files changed, 22 insertions(+), 11 deletions(-)

diff --git a/src/strix/__init__.py b/src/strix/__init__.py @@ -41,6 +41,7 @@ def check_motion_config(config_path): errors = [] base_target_dir = "" base_queue_dir = "" + cameras = [] found_pf = False cfg = motion.config.MotionConfig(config_path) @@ -73,6 +74,12 @@ def check_motion_config(config_path): elif base_target_dir != tm.group(1): errors += ["All of the base paths in target_dir MUST match."] + # Gather the info about the cameras and ports + camera_name = c.get("camera_name", "") + stream_port = c.get("stream_port", 8080) + if camera_name: + cameras.append((camera_name, stream_port)) + if not base_target_dir: errors += ["Could not find a target_dir setting. The last directory must be /CameraX"] if not base_queue_dir: @@ -82,7 +89,9 @@ def check_motion_config(config_path): if not found_pf: errors += ["picture_filename MUST be set to %s" % picture_filename] - return (base_target_dir, errors) + # Cameras are sorted by their stream_port + cameras = sorted(cameras, key=lambda c: c[1]) + return (base_target_dir, cameras, errors) def run(): @@ -90,7 +99,7 @@ def run(): opts = parser.parse_args() try: - (base_dir, errors) = check_motion_config(opts.config) + (base_dir, cameras, errors) = check_motion_config(opts.config) except Exception as e: errors = [str(e)] @@ -141,7 +150,7 @@ def run(): api_quit = mp.Event() api_thread = mp.Process(name="api-thread", target=api.run_api, - args=(logger_queue, base_dir, opts.host, opts.port, opts.debug)) + args=(logger_queue, base_dir, cameras, opts.host, opts.port, opts.debug)) api_thread.start() running_threads += [(api_thread, api_quit)] diff --git a/src/strix/api.py b/src/strix/api.py @@ -33,9 +33,9 @@ TIME_FORMAT = "%Y-%m-%d %H:%M:%S" def timestr_to_dt(rfc_str): return datetime.strptime(rfc_str, TIME_FORMAT) -def run_api(logging_queue, base_dir, host, port, debug): +def run_api(logging_queue, base_dir, cameras, host, port, debug): log = logger.log(logging_queue) - log.info("Starting API", base_dir=base_dir, host=host, port=port, debug=debug) + log.info("Starting API", base_dir=base_dir, cameras=cameras, host=host, port=port, debug=debug) EventCache.logger(log) @route('/') @@ -49,7 +49,7 @@ def run_api(logging_queue, base_dir, host, port, debug): @route('/api/cameras/list') def serve_cameras_list() -> Response: - return {"cameras": sorted([d for d in os.listdir(base_dir) if d != "queue"])} + return {"cameras": cameras} @route('/api/events/<cameras>') def serve_events(cameras): diff --git a/src/strix/ui/index.html b/src/strix/ui/index.html @@ -78,10 +78,7 @@ function update_events() { }); } -function setup_page() { - // Camera information will eventually be filled in by an api call - // And then the page will be populated - cameras = [["Camera1", 8081], ["Camera2", 8082], ["Camera3", 8083], ["Camera5", 8085], ["Camera4", 8084]]; +function setup_page(cameras) { event_offsets = new Map(); // Setup the camera HTML @@ -123,7 +120,12 @@ function setup_page() { setInterval(update_events, 30 * 1000); } -setup_page(); +// First thing to do is get the list of cameras, then setup the page. +fetch("/api/cameras/list") + .then(resp => resp.json()) + .then(data => { + setup_page(data.cameras); + }); </script> </body> </html>