diff --git a/src/ambianic/webapp/flaskr.py b/src/ambianic/webapp/flaskr.py index 2f9b957e..86f8d6a9 100755 --- a/src/ambianic/webapp/flaskr.py +++ b/src/ambianic/webapp/flaskr.py @@ -5,6 +5,7 @@ from flask import Flask, request, jsonify from flask_cors import CORS from flask.logging import default_handler +from flask import g import flask from requests import get from werkzeug.serving import make_server @@ -21,11 +22,14 @@ class FlaskJob(ManagedService): def __init__(self, config): self.config = config + data_dir = config.get('data_dir', './data') self.srv = None - app = create_app() + app = create_app(data_dir=data_dir) self.srv = make_server('0.0.0.0', 8778, app) ctx = app.app_context() ctx.push() + with app.app_context(): + flask.current_app.data_dir = data_dir self.flask_stopped = True log.debug('Flask process created') @@ -90,7 +94,7 @@ def stop(self): log.info('Flask server job stopped.') -def create_app(): +def create_app(data_dir=None): log.debug('Creating Flask app...') # if Ambianic is in INFO or DEBUG mode, pass that info on to Flask @@ -130,6 +134,18 @@ def health_check(): def view_pipelines(): return flask.render_template('pipelines.html') + @app.route('/api/timeline', methods=['GET']) + def get_timeline(): + response_object = {'status': 'success'} + req_page = request.args.get('page', default=1, type=int) + nonlocal data_dir + resp = samples.get_timeline(page=req_page, data_dir=data_dir) + response_object['timeline'] = resp + log.debug('Returning %d timeline events', len(resp)) + # log.debug('Returning samples: %s ', response_object) + resp = jsonify(response_object) + return resp + @app.route('/api/samples', methods=['GET', 'POST']) def get_samples(): response_object = {'status': 'success'} diff --git a/src/ambianic/webapp/server/samples.py b/src/ambianic/webapp/server/samples.py index bc9cf1c1..7dabdf7c 100644 --- a/src/ambianic/webapp/server/samples.py +++ b/src/ambianic/webapp/server/samples.py @@ -5,6 +5,7 @@ from pathlib import Path import os import json +import yaml log = logging.getLogger() @@ -110,6 +111,62 @@ def get_samples(before_datetime=None, page=1): return samples +def get_timeline(before_datetime=None, page=1, data_dir=None): + """Get stored pipeline timeline events. + + :Parameters: + ---------- + before_datetime : date time in ISO 8601 compatible format, + YYYY-MM-DDTHH:MM:SS. For example '2002-12-25 00:00:00-06:39'. + It uses python's standard function datetime.fromisoformat(). + If not provided, the function will start with the most recent available + sample. + page : positive integer + Paginates samples in batches of 5. Defaults to page=1. + + :Returns: + ------- + list: json + Returns a list of previously saved pipeline events. + + """ + parsed_datetime = None + assert isinstance(page, int) + assert page > 0 + page_size = 5 + if before_datetime: + try: + parsed_datetime = datetime.fromisoformat(before_datetime) + log.debug('Fetching samples saved before %s', + parsed_datetime) + except ValueError as e: + log.warning('Unable to parse before_datetime parameter: %s. ' + ' Error: %s', before_datetime, str(e)) + page_start_position = (page-1)*page_size + page_end_position = page_start_position + page_size + if not parsed_datetime: + log.debug('Fetching most recent saved samples') + log.debug('Fetching samples page %d. Page size %d. ' + 'Sample index range [%d:%d]. ', + page, page_size, page_start_position, page_end_position) + p = Path(data_dir) / 'timeline-event-log.yaml' + log.debug('Timeline path: %s', p.resolve()) + with p.open() as pf: + timeline_events = yaml.safe_load(pf) + log.debug('Fetched timeline file with %d events: ', len(timeline_events)) + # files = sorted(files, key=os.path.getmtime, reverse=True) + # for json_file in files[page_start_position:page_end_position]: + # if + # with open(json_file) as f: + # sample = json.load(f) + # sample['id'] = uuid.uuid4().hex + # sample['file'] = str(json_file) + # samples.append(sample) + # lines = map(str, files) + # log.debug('File names follow:\n %s', "\n".join(lines)) + return timeline_events + + def add_sample(new_sample=None): assert new_sample log.debug('add_sample new_sample 0 %s', new_sample) diff --git a/tests/pipeline/avsource/test_avsource.py b/tests/pipeline/avsource/test_avsource.py index 1a969326..027a62ca 100644 --- a/tests/pipeline/avsource/test_avsource.py +++ b/tests/pipeline/avsource/test_avsource.py @@ -148,8 +148,8 @@ def sample_callback(image=None, inference_result=None, **kwargs): print('detections: {det}'.format(det=detections)) print('len(detections): {len}'.format(len=len(detections))) if detections: - category, confidence, _ = detections[0] - if category == 'person' and confidence > 0.9: + label, confidence, _ = detections[0] + if label == 'person' and confidence > 0.9: # skip video image samples until we reach a person detection # with high level of confidence detection_received.set() @@ -168,8 +168,8 @@ def sample_callback(image=None, inference_result=None, **kwargs): assert sample_image.size[1] == 720 assert detections assert len(detections) == 1 - category, confidence, (x0, y0, x1, y1) = detections[0] - assert category == 'person' + label, confidence, (x0, y0, x1, y1) = detections[0] + assert label == 'person' assert confidence > 0.9 assert x0 > 0 and x0 < x1 assert y0 > 0 and y0 < y1 @@ -243,8 +243,8 @@ def sample_callback(image=None, inference_result=None, **kwargs): print('detections: {det}'.format(det=detections)) print('len(detections): {len}'.format(len=len(detections))) if detections: - category, confidence, _ = detections[0] - if category == 'person' and confidence > 0.9: + label, confidence, _ = detections[0] + if label == 'person' and confidence > 0.9: # skip video image samples until we reach a person detection # with high level of confidence detection_received.set() @@ -263,8 +263,8 @@ def sample_callback(image=None, inference_result=None, **kwargs): assert sample_image.size[1] == 720 assert detections assert len(detections) == 1 - category, confidence, (x0, y0, x1, y1) = detections[0] - assert category == 'person' + label, confidence, (x0, y0, x1, y1) = detections[0] + assert label == 'person' assert confidence > 0.9 assert x0 > 0 and x0 < x1 assert y0 > 0 and y0 < y1 @@ -297,8 +297,8 @@ def sample_callback(image=None, inference_result=None, **kwargs): print('detections: {det}'.format(det=detections)) print('len(detections): {len}'.format(len=len(detections))) if detections: - category, confidence, _ = detections[0] - if category == 'person' and confidence > 0.9: + label, confidence, _ = detections[0] + if label == 'person' and confidence > 0.9: # skip video image samples until we reach a person detection # with high level of confidence detection_received.set() @@ -317,8 +317,8 @@ def sample_callback(image=None, inference_result=None, **kwargs): assert sample_image.size[1] == 720 assert detections assert len(detections) == 1 - category, confidence, (x0, y0, x1, y1) = detections[0] - assert category == 'person' + label, confidence, (x0, y0, x1, y1) = detections[0] + assert label == 'person' assert confidence > 0.9 assert x0 > 0 and x0 < x1 assert y0 > 0 and y0 < y1 @@ -417,8 +417,8 @@ def sample_callback(image=None, inference_result=None, **kwargs): print('detections: {det}'.format(det=detections)) print('len(detections): {len}'.format(len=len(detections))) if detections: - category, confidence, _ = detections[0] - if category == 'person' and confidence > 0.9: + label, confidence, _ = detections[0] + if label == 'person' and confidence > 0.9: # skip video image samples until we reach a person detection # with high level of confidence detection_received.set() @@ -437,8 +437,8 @@ def sample_callback(image=None, inference_result=None, **kwargs): assert sample_image.size[1] == 720 assert detections assert len(detections) == 1 - category, confidence, (x0, y0, x1, y1) = detections[0] - assert category == 'person' + label, confidence, (x0, y0, x1, y1) = detections[0] + assert label == 'person' assert confidence > 0.9 assert x0 > 0 and x0 < x1 assert y0 > 0 and y0 < y1 @@ -518,8 +518,8 @@ def sample_callback(image=None, inference_result=None, **kwargs): print('detections: {det}'.format(det=detections)) print('len(detections): {len}'.format(len=len(detections))) if detections: - category, confidence, _ = detections[0] - if category == 'person' and confidence > 0.9: + label, confidence, _ = detections[0] + if label == 'person' and confidence > 0.9: # skip video image samples until we reach a person detection # with high level of confidence detection_received.set() @@ -538,8 +538,8 @@ def sample_callback(image=None, inference_result=None, **kwargs): assert sample_image.size[1] == 720 assert detections assert len(detections) == 1 - category, confidence, (x0, y0, x1, y1) = detections[0] - assert category == 'person' + label, confidence, (x0, y0, x1, y1) = detections[0] + assert label == 'person' assert confidence > 0.9 assert x0 > 0 and x0 < x1 assert y0 > 0 and y0 < y1 @@ -634,8 +634,8 @@ def sample_callback(image=None, inference_result=None, **kwargs): print('detections: {det}'.format(det=detections)) print('len(detections): {len}'.format(len=len(detections))) if detections: - category, confidence, _ = detections[0] - if category == 'person' and confidence > 0.9: + label, confidence, _ = detections[0] + if label == 'person' and confidence > 0.9: # skip video image samples until we reach a person detection # with high level of confidence detection_received.set() @@ -654,8 +654,8 @@ def sample_callback(image=None, inference_result=None, **kwargs): assert sample_image.size[1] == 720 assert detections assert len(detections) == 1 - category, confidence, (x0, y0, x1, y1) = detections[0] - assert category == 'person' + label, confidence, (x0, y0, x1, y1) = detections[0] + assert label == 'person' assert confidence > 0.9 assert x0 > 0 and x0 < x1 assert y0 > 0 and y0 < y1