super un-efficient way to mangle data for graph

redesign
Mark Cotton 2023-07-24 15:10:38 -06:00
parent 8eb3a45e2e
commit f4676c2257
5 changed files with 77 additions and 6 deletions

64
app.py
View File

@ -3,6 +3,8 @@ import json, requests
from flask import Flask, request, session, render_template, redirect, url_for, Response, send_file from flask import Flask, request, session, render_template, redirect, url_for, Response, send_file
from flask_session import Session from flask_session import Session
from tqdm import tqdm
from io import BytesIO from io import BytesIO
import logging import logging
@ -138,8 +140,11 @@ def camera_detail(esn=None):
een = EagleEyev3(config) een = EagleEyev3(config)
camera = een.get_camera_by_id(esn) camera = een.get_camera_by_id(esn)
camera.get_list_of_events(end_timestamp=een.time_before(ts=een.time_now(), hours=0), \ now = een.time_now()
start_timestamp=een.time_before(ts=een.time_now(), hours=6) )
for i in tqdm(range(0,4)):
camera.get_list_of_events(end_timestamp=een.time_before(ts=now, hours=6*i), \
start_timestamp=een.time_before(ts=now, hours=6*(i+1)))
values = { values = {
"current_user": een.current_user, "current_user": een.current_user,
@ -149,7 +154,62 @@ def camera_detail(esn=None):
return render_template('camera_detail_partial.html', template_values=values) return render_template('camera_detail_partial.html', template_values=values)
@app.route('/camera/<esn>/status_plot')
def camera_status_plot(esn=None):
if 'een' in session:
een = session['een']
else:
een = EagleEyev3(config)
cam = een.get_camera_by_id(esn)
import pandas as pd
import numpy as np
from matplotlib.figure import Figure
import matplotlib.dates as mdates
import base64
atm_df = pd.DataFrame(cam.events['status'][::-1], columns=['id', 'startTimestamp', 'actorId', 'data'])
atm_df['ts'] = pd.to_datetime(atm_df.startTimestamp)
atm_df['status_desc'] = atm_df['data'].apply(lambda x: x[0]['newStatus']['connectionStatus'])
atm_df['status'] = atm_df['status_desc'].replace(to_replace=['online', 'offline', 'error', 'deviceOffline', 'deviceOnline', 'off', 'bridgeOffline'], value=[1,0,0,0,0,0,0])
imp = atm_df.set_index(['ts'])
# Generate the figure **without using pyplot**.
fig = Figure(figsize=(16, 12), dpi=80)
ax = fig.subplots()
imp['startTimestamp'] = pd.to_datetime(imp['startTimestamp'])
imp = imp.drop(['id', 'actorId', 'data', 'status_desc'], axis=1)
data = imp.resample('S').bfill()
data['status'] = data['status'].astype('int64')
print(len(data))
print(data.info())
print(data)
data = data.drop(['startTimestamp'], axis=1)
print(data)
ax.step(data.index, data['status'], lw=5, color='blue')
# ax.fill_between(data['startTimestamp'], data['status'])
ax.axhline(1, color='green', lw=2, alpha=0.3)
ax.axhline(0, color='red', lw=2, alpha=0.3)
# ax.set_title('Manual DateFormatter', loc='left', y=0.85, x=0.02, ontsize='medium')
# Text in the x-axis will be displayed in 'YYYY-mm' format.
# ax.xaxis.set_major_formatter(mdates.DateFormatter('%Y-%b'))
# Rotates and right-aligns the x labels so they don't crowd each other.
for label in ax.get_xticklabels(which='major'):
label.set(rotation=30, horizontalalignment='right')
# Save it to a temporary buffer.
buf = BytesIO()
fig.savefig(buf, format="png")
# Embed the result in the html output.
data = base64.b64encode(buf.getbuffer()).decode("ascii")
return f"<div class='col-md-12'><img src='data:image/png;base64,{data}' width=100%/></div>"

View File

@ -15,3 +15,5 @@ gunicorn==20.1.0
cachelib==0.10.2 cachelib==0.10.2
Flask-Session==0.5.0 Flask-Session==0.5.0
EagleEyev3>=0.0.4 EagleEyev3>=0.0.4
tqdm

View File

@ -11,14 +11,20 @@
<ul> <ul>
{% if template_values['events'] %} {% if template_values['events'] %}
{% for event in template_values['events'] %} {% for event in template_values['events'] %}
<li>{{ event['data'][0]['newStatus']['connectionStatus'] }} <br> <small>{{ event['startTimestamp'] }}</small></li> <li>
{{ event['data'][0]['newStatus']['connectionStatus'] }}
<br> <small>{{ event['endTimestamp'] }}</small>
<br> <small>{{ event['startTimestamp'] }}</small>
</li>
{% endfor %} {% endfor %}
{% else %} {% else %}
<li>No events in the last six hours</li> <li>No events in the last six hours</li>
{% endif %} {% endif %}
</ul> </ul>
<div> <div>
<!-- <button hx-get="/camera/{{ template_values['camera'].id }}/events" hx-trigger="click" hx-target="#event_list">refresh</button> --> <button hx-get="/camera/{{ template_values['camera'].id }}/status_plot" hx-trigger="click" hx-target="#camera_status_plot">
load plot
</button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -19,7 +19,7 @@
<h3>Offline</h3> <h3>Offline</h3>
<ul> <ul>
{% for camera in template_values['cameras'] %} {% for camera in template_values['cameras'] %}
{% if camera.is_offline() %} {% if camera.is_offline() and camera.bridge_id %}
<li hx-get="/camera/{{ camera.id }}" hx-trigger="click" hx-target="#camera_detail"> {{ camera.name }}</li> <li hx-get="/camera/{{ camera.id }}" hx-trigger="click" hx-target="#camera_detail"> {{ camera.name }}</li>
{% endif %} {% endif %}
{% endfor %} {% endfor %}

View File

@ -28,6 +28,9 @@
{% include 'cameras_partial.html' %} {% include 'cameras_partial.html' %}
</div> </div>
<div class="row" id="camera_status_plot">
</div>
</div> </div>
{% endblock %} {% endblock %}