2023-07-14 04:00:37 +00:00
import json , requests
2023-07-14 15:21:10 +00:00
from flask import Flask , request , session , render_template , redirect , url_for , Response , send_file
2023-07-14 04:00:37 +00:00
from flask_session import Session
2023-07-25 14:32:47 +00:00
import pandas as pd
import numpy as np
from matplotlib . figure import Figure
import matplotlib . dates as mdates
import base64
2023-07-24 21:10:38 +00:00
from tqdm import tqdm
2023-07-14 15:21:10 +00:00
from io import BytesIO
2023-07-14 04:00:37 +00:00
import logging
logger = logging . getLogger ( )
2023-07-20 05:05:29 +00:00
from EagleEyev3 import *
from settings import config
logging . info ( f " Using EagleEyev3 version { EagleEyev3 . __version__ } " )
2023-07-14 04:00:37 +00:00
app = Flask ( __name__ )
SESSION_TYPE = ' filesystem '
app . config . from_object ( __name__ )
Session ( app )
2023-07-28 04:57:17 +00:00
# check if it could pull in a config object from settings.py
if config :
# start checking for keys in config object and set sensible defaults
if ' days_of_history ' in config :
DAYS_OF_HISTORY = config [ ' days_of_history ' ]
else :
# fallback to a sane default
DAYS_OF_HISTORY = 1
else :
if ' log_level ' in config :
logger . setLevel ( config [ ' log_level ' ] )
else :
logging . setLevel ( config [ ' INFO ' ] )
2023-07-28 16:55:08 +00:00
@app.route ( ' /landing ' )
def landing ( ) :
# sometimes you just want to get to the landing page and want to avoid the index redirect logic
if ' een ' in session :
een = session [ ' een ' ]
else :
een = EagleEyev3 ( config )
session [ ' een ' ] = een
base_url = " https://auth.eagleeyenetworks.com/oauth2/authorize "
path_url = f " ?client_id= { een . client_id } &response_type=code&scope=vms.all&redirect_uri= { een . redirect_uri } "
values = { " login_link " : f " { base_url } { path_url } " }
return render_template ( ' cover.html ' , template_values = values )
2023-07-28 04:57:17 +00:00
2023-07-14 04:00:37 +00:00
@app.route ( ' / ' )
def index ( ) :
if ' een ' in session :
een = session [ ' een ' ]
else :
2023-07-20 05:05:29 +00:00
een = EagleEyev3 ( config )
2023-07-14 04:00:37 +00:00
session [ ' een ' ] = een
# using current_user as a proxy for an established valid session
if een . access_token == None :
base_url = " https://auth.eagleeyenetworks.com/oauth2/authorize "
path_url = f " ?client_id= { een . client_id } &response_type=code&scope=vms.all&redirect_uri= { een . redirect_uri } "
2023-07-28 03:32:56 +00:00
values = { " login_link " : f " { base_url } { path_url } " }
return render_template ( ' cover.html ' , template_values = values )
2023-07-14 04:00:37 +00:00
# call this to check if session is actually valid
check = een . get_current_user ( )
if ' success ' not in check or check [ ' success ' ] == False :
base_url = " https://auth.eagleeyenetworks.com/oauth2/authorize "
path_url = f " ?client_id= { een . client_id } &response_type=code&scope=vms.all&redirect_uri= { een . redirect_uri } "
2023-07-28 03:32:56 +00:00
values = { " login_link " : f " { base_url } { path_url } " }
return render_template ( ' cover.html ' , template_values = values )
2023-07-14 04:00:37 +00:00
else :
2023-07-20 05:05:29 +00:00
logging . info ( f " { check [ ' success ' ] } - check get_current_user { een . current_user [ ' email ' ] } { een . access_token } " )
2023-07-14 04:00:37 +00:00
2023-07-14 06:11:14 +00:00
een . get_list_of_cameras ( )
2023-07-14 04:00:37 +00:00
values = {
2023-07-14 06:11:14 +00:00
" current_user " : een . current_user ,
" cameras " : een . cameras
2023-07-14 04:00:37 +00:00
}
return render_template ( ' index.html ' , template_values = values )
@app.route ( ' /login_callback ' )
def login_callback ( ) :
# This is getting the ?code= querystring value from the HTTP request.
code = request . args . get ( ' code ' )
if ' een ' in session :
een = session [ ' een ' ]
else :
2023-07-20 05:05:29 +00:00
een = EagleEyev3 ( config )
2023-07-14 04:00:37 +00:00
if ( code ) :
# use the include code parameter to complete login process
oauth_object = een . login_tokens ( code )
2023-07-14 06:11:14 +00:00
2023-07-14 04:00:37 +00:00
return redirect ( url_for ( ' index ' ) )
@app.route ( ' /logout ' )
def logout ( ) :
if ' een ' in session :
een = session [ ' een ' ]
een . logout ( )
2023-07-26 19:21:23 +00:00
session . pop ( ' een ' )
2023-07-14 18:02:26 +00:00
2023-07-14 04:00:37 +00:00
return redirect ( url_for ( ' index ' ) )
2023-07-14 06:11:14 +00:00
@app.route ( ' /cameras ' )
def cameras ( ) :
if ' een ' in session :
een = session [ ' een ' ]
else :
2023-07-20 05:05:29 +00:00
een = EagleEyev3 ( config )
2023-07-14 06:11:14 +00:00
een . get_list_of_cameras ( )
values = {
" current_user " : een . current_user ,
" cameras " : een . cameras
}
return render_template ( ' cameras_partial.html ' , template_values = values )
2023-07-14 15:21:10 +00:00
2023-07-26 13:34:33 +00:00
@app.route ( ' /camera/<esn>/preview_image ' )
def camera__preivew_image ( esn = None ) :
2023-07-14 15:21:10 +00:00
if ' een ' in session :
een = session [ ' een ' ]
else :
2023-07-20 05:05:29 +00:00
een = EagleEyev3 ( config )
2023-07-14 15:21:10 +00:00
camera = een . get_camera_by_id ( esn )
res = camera . get_live_preview ( )
if res :
return send_file ( BytesIO ( res . content ) , mimetype = ' image/jpeg ' )
else :
2023-07-14 15:48:14 +00:00
return send_file ( ' static/placeholder.png ' )
2023-07-14 15:21:10 +00:00
2023-07-28 16:55:08 +00:00
2023-07-26 13:34:33 +00:00
@app.route ( ' /camera/<esn>/preview ' )
def camera_live_preivew ( esn = None ) :
if ' een ' in session :
een = session [ ' een ' ]
else :
een = EagleEyev3 ( config )
camera = een . get_camera_by_id ( esn )
values = {
" current_user " : een . current_user ,
" camera " : camera ,
" events " : camera . events [ ' status ' ]
}
return render_template ( ' camera_preview.html ' , template_values = values )
2023-08-07 20:43:23 +00:00
@app.route ( " /camera/<esn>/events/<int:days> " )
2023-07-26 13:34:33 +00:00
@app.route ( ' /camera/<esn>/events ' )
2023-08-07 20:43:23 +00:00
def camera_detail ( esn = None , days = DAYS_OF_HISTORY ) :
2023-07-14 06:11:14 +00:00
if ' een ' in session :
een = session [ ' een ' ]
else :
2023-07-20 05:05:29 +00:00
een = EagleEyev3 ( config )
2023-07-14 06:11:14 +00:00
camera = een . get_camera_by_id ( esn )
2023-07-24 21:10:38 +00:00
now = een . time_now ( )
2023-08-08 14:39:48 +00:00
# because of API limitation, can only query 24 hours max
for i in tqdm ( range ( 0 , days ) ) :
camera . get_list_of_events ( end_timestamp = een . time_before ( ts = now , hours = 24 * i ) , \
start_timestamp = een . time_before ( ts = now , hours = 24 * ( i + 1 ) ) )
2023-07-14 06:11:14 +00:00
values = {
" current_user " : een . current_user ,
" camera " : camera ,
2023-07-14 13:26:06 +00:00
" events " : camera . events [ ' status ' ]
2023-07-14 06:11:14 +00:00
}
2023-07-26 13:34:33 +00:00
return render_template ( ' camera_events_partial.html ' , template_values = values )
2023-07-14 06:11:14 +00:00
2023-07-28 16:55:08 +00:00
2023-07-24 21:10:38 +00:00
@app.route ( ' /camera/<esn>/status_plot ' )
def camera_status_plot ( esn = None ) :
if ' een ' in session :
een = session [ ' een ' ]
else :
een = EagleEyev3 ( config )
2023-07-14 06:11:14 +00:00
2023-07-24 21:10:38 +00:00
cam = een . get_camera_by_id ( esn )
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 ' ] )
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 ' )
data = data . drop ( [ ' startTimestamp ' ] , axis = 1 )
2023-07-25 14:32:47 +00:00
# Generate the figure **without using pyplot**.
fig = Figure ( figsize = ( 6 , 5 ) , dpi = 160 )
ax = fig . subplots ( )
2023-07-24 21:10:38 +00:00
2023-07-25 14:32:47 +00:00
ax . step ( data . index , data [ ' status ' ] , lw = 2 , color = ' blue ' )
ax . set_title ( cam . name )
2023-07-24 21:10:38 +00:00
# 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 )
2023-07-25 14:32:47 +00:00
2023-07-24 21:10:38 +00:00
for label in ax . get_xticklabels ( which = ' major ' ) :
label . set ( rotation = 30 , horizontalalignment = ' right ' )
# Save it to a temporary buffer.
buf = BytesIO ( )
2023-07-28 16:41:05 +00:00
fig . savefig ( buf , format = " png " , transparent = True )
2023-07-24 21:10:38 +00:00
# Embed the result in the html output.
data = base64 . b64encode ( buf . getbuffer ( ) ) . decode ( " ascii " )
2023-08-07 18:55:58 +00:00
return f " <h3>Graph of Status Events <i class= ' bi bi-bar-chart ' ></i></h3><div class= ' col-md-12 ' ><img src= ' data:image/png;base64, { data } ' style= ' max-width:100% ' /></div> "
2023-07-14 06:11:14 +00:00
2023-07-14 15:21:10 +00:00
2023-07-28 16:55:08 +00:00
2023-07-14 04:00:37 +00:00
if __name__ == ' __main__ ' :
app . run ( host = een . server_host , port = een . server_port )