Beacon_Webapp.py

Run the beacon reciver and start a webserver at http://localhost:5000 for viewing Valid URL parameters for http://localhost/live_database include, offset, limit, and orderby. The orderby field requires a column name (case sensitive).

import sqlite3
from flask import Flask, request
import os
import Beacon_Receiver
import options_file as options
import traceback

# ---------- Setup Database --------------------

conn = sqlite3.connect(os.path.join(options.beacon_files_dir, 'Beacons.db'))
cursor = conn.cursor()

# ---------- Setup WebApp --------------------

app = Flask(__name__)


@app.route('/')
def homepage():
    html = '''
      <h1>Prox 1 Beacons</h1>
      <a href="/live_database">View Live Database</a><br>
      <a href="/Most_Recent_Beacon">Most Recent Beacon</a><br>
      
      <h2>How To</h2>
      <p>Enable Auto Refresh: /live_database?auto_refresh=True</p>
      <p>Enforce Limit: /live_database?limit=100</p>
      <p>Enable Auto Refresh and Enforce Limit: /live_database?limit=100&auto_refresh=True</p>
      '''
    return html


@app.route('/live_database')
def live_database():
  try:
    limit = ''
    offset = ''
    orderby = ''
    if request.args.get('limit'): 
      limit = ' LIMIT ' + str(int(request.args.get('limit')))
    if request.args.get('offset'): 
      offset = ' OFFSET ' + str(int(request.args.get('offset')))
    if request.args.get('orderby'): 
      orderby = request.args.get('orderby')
    html = '''<html><head> <style style="text/css">
        .hoverTable{
        width:100%; 
        border-collapse:collapse; 
      }
      .hoverTable td{ 
        padding:7px; border:#4e95f4 1px solid;
      }
      /* Define the default color for all the table rows */
      .hoverTable tr{
        background: #b8d1f3;
      }
      /* Define the hover highlight color for the table row */
        .hoverTable tr:hover {
              background-color: #ffff99;
        }
    </style> </head>'''
    query = ''
    if not orderby:
      query = "SELECT * FROM Beacons ORDER BY time_received DESC"
    else:
      query = "SELECT * FROM Beacons ORDER BY " + orderby + " DESC"
    print "Query", query
    query += limit + offset
    for entry in cursor.execute(query):
      html += '<tr><td><a href="/beacon_details/'+str(entry[0]).replace('/','_')+'">'+str(entry[0])+'</a>'
      html+= ''.join(['<td>'+str(e)+'</td>' for e in entry[1:]]) + '</tr>'
    html += '</table>'
    titles = ''.join(['<th><a href="/chart?variable='+str(e)+'">'+str(e)+'</a></th>' for e in list(map(lambda x: x[0], cursor.description))])
    html =  '<table  class="hoverTable"><tr>'+ titles + '</tr>' + html
    if request.args.get('auto_refresh'): html += '<meta http-equiv="refresh" content="5">'
    html += '</html>'
    return html
  except Exception as e:
    traceback.print_exc()
  
@app.route('/chart')
def chart():
    var = request.args.get('variable')
    xVar = request.args.get('x')
    if xVar == None:
      xVar = "time_received"
    if var == None:
        return '<h1>Error. Visit page with format /chart?variable=<variable name></h1>'
    try:
        entries = list(cursor.execute("SELECT " + xVar + ", " + var + " FROM Beacons"))
    except:
        return '<h1>Error. Unable to find variable "' + var + '."</h1>'
    if isinstance(entries[0][1], unicode):
        return '<h1>Error. Cannot graph variable "' + var + '."</h1>'

    html = '''
  <!DOCTYPE html>
  <html>
    <head>
      <title>Beacon Chart</title>
      <!-- amCharts javascript sources -->
      <script type="text/javascript" src="http://www.amcharts.com/lib/3/amcharts.js"></script>
      <script type="text/javascript" src="http://www.amcharts.com/lib/3/serial.js"></script>
      <!-- amCharts javascript code -->
      <script type="text/javascript">
        AmCharts.makeChart("chartdiv",
          {
            "type": "serial",
            "categoryField": "date",
            "dataDateFormat": "MM/DD/YY HH:NN:SS.QQQ",
            "categoryAxis": {
              "minPeriod": "fff",
              "parseDates": true
            },
            "chartCursor": {
              "categoryBalloonDateFormat": "MM/DD/YY HH:NN:SS.QQQ"
            },
            "chartScrollbar": {},
            "trendLines": [],
            "graphs": [
              {
                "balloonColor": "#000000",
                "bullet": "round",
                "bulletBorderColor": "#FFFFFF",
                "color": "#0000FF",
                "fillColors": "#0000FF",
                "id": "AmGraph-1",
                "lineColor": "#000000",
                "title": "'''
    html += var
    html += '''",
                "valueField": "column-1"
              }
            ],
            "guides": [],
            "valueAxes": [
              {
                "id": "ValueAxis-1",
                "title": ""
              }
            ],
            "allLabels": [],
            "balloon": {},
            "legend": {},
            "titles": [
              {
                "id": "Title-1",
                "size": 15,
                "text": "'''
    html += var + ' vs Time'
    html += '''"
              }
            ],
            "dataProvider": ['''
    for entry in entries:
        html += '''
    {
      "column-1": '''
        html += str(entry[1]) + ','
        html += '''
      "date": "'''
        html += str(entry[0])
        html += '''"
    },
    '''

    html += '''
            ]
          }
        );
      </script>
    </head>
    <body>
      <div id="chartdiv" style="width: 100%; height: 400px; background-color: #FFFFFF;" ></div>
    </body>
  </html>
  '''
    if request.args.get('auto_refresh'): html += '<meta http-equiv="refresh" content="5">'
    return html


@app.route('/Most_Recent_Beacon')
def most_recent_beacon():
    num_columns = 6
    entries = list(list(cursor.execute("SELECT * FROM Beacons ORDER BY time_received DESC LIMIT 1"))[0])
    titles = list(map(lambda x: x[0], cursor.description))
    html = '''
  <!DOCTYPE html>
  <html>
  <meta http-equiv="refresh" content="5">
  <body>
  <p style="font-size:130%" align="center"><b><u>Beacon #'''
    html += str(entries[1])
    html += '''</u></b></p>
  <p style="font-size:110%" align="center">Received on '''
    html += str(entries[0])
    html += '''</p>
  <table border="1" style="width:100%">
  '''
    while len(entries) > 0:
        row_entries = entries[:num_columns]
        entries[:num_columns] = []
        row_titles = titles[:num_columns]
        titles[:num_columns] = []
        html += '<tr>' + ''.join(
                ['<td><b><u>' + str(row_titles[i]) + '</b></u><br>' + str(row_entries[i]) + '</td>' for i in
                 range(len(row_entries))]) + '</tr>'
    html += '''
  </table>
  </body>
  </html>
  '''
    return html


@app.route('/beacon_details/<time_received>')
def beacon_details(time_received):
    time_received = time_received.replace('_', '/')
    num_columns = 6
    try:
        entries = list(list(cursor.execute("SELECT * FROM Beacons WHERE time_received = ?", (time_received,)))[0])
    except:
        return '<h1>Error</h1>'
    titles = list(map(lambda x: x[0], cursor.description))
    html = '''
  <!DOCTYPE html>
  <html><body>
  <p style="font-size:130%" align="center"><b><u>Beacon #'''
    html += str(entries[1])
    html += '''</u></b></p>
  <p style="font-size:110%" align="center">Received on '''
    html += str(entries[0])
    html += '''</p>
  <table border="1" style="width:100%">
  '''
    while len(entries) > 0:
        row_entries = entries[:num_columns]
        entries[:num_columns] = []
        row_titles = titles[:num_columns]
        titles[:num_columns] = []
        html += '<tr>' + ''.join(
                ['<td><b><u>' + str(row_titles[i]) + '</b></u><br>' + str(row_entries[i]) + '</td>' for i in
                 range(len(row_entries))]) + '</tr>'
    html += '''
  </table>
  </body>
  </html>
  '''
    return html


if __name__ == '__main__':
  Beacon_Receiver.listen()
  app.run(host="0.0.0.0", port=5000)