Project

General

Profile

« Previous | Next » 

Revision 98f4e4a6

Added by dsorber almost 12 years ago

Continued working on the web GUI, taking baby steps.

View differences:

software/bookmark_library/bmklib/web/base_controller.py
from genshi.template import TemplateLoader
BASE_PATH = '/home/dsorber/Documents/phalanx-repo/software/bookmark_library/web'
DB_PATH = os.path.join(BASE_PATH, 'beer_temps.db')
TEMPLATE_PATH = os.path.join(BASE_PATH, 'templates')
BASE_PATH = '/home/dsorber/Documents/phalanx-repo/software/bookmark_library/'
DB_PATH = os.path.join(BASE_PATH, 'bookmarks.db')
TEMPLATE_PATH = os.path.join(BASE_PATH, 'bmklib', 'web', 'templates')
class BaseHTMLController(object):
......
""" This function generates the actual response which is made up of two
parts, the response headers and the response body.
"""
self.build_content()
# Generate the stream and then render it to HTML
stream = self.template.generate(**response_args)
stream = self.template.generate(**self.content)
body = stream.render('html', doctype='html', encoding='utf-8')
# Set the appropriate response headers
......
self.environ = environ
# This string will be the response body
self.body
self.body = ''
def build_content(self):
""" This method is used to build the content that is used to generate
......
""" This function generates the actual response which is made up of two
parts, the response headers and the response body.
"""
self.build_content()
headers = [('Content-Type', 'text/plain'),
('Content-Length', str(len(self.body)))]
return headers, self.body
class TestController(BaseTextController):
def build_content(self):
self.body = 'hello there handsome'
software/bookmark_library/bmklib/web/bmklib.wsgi
import cgi
import datetime
import os
import sqlite3
from genshi.template import TemplateLoader
from genshi.template.base import Context
BASE_PATH = '/home/dsorber/bfcs'
DB_PATH = os.path.join(BASE_PATH, 'beer_temps.db')
TEMPLATE_PATH = os.path.join(BASE_PATH, 'templates')
from bmklib.web.controllers.main import MainPageController
# It accepts two arguments:
# environ points to a dictionary containing CGI like environment variables
......
# start_response is a callback function supplied by the server
# which will be used to send the HTTP status and headers to the server
def application(environ, start_response):
loader = TemplateLoader(TEMPLATE_PATH, auto_reload=True)
if not environ['PATH_INFO'] or environ['PATH_INFO'] == '/':
# Load the index template
template = loader.load('index.html')
# Create the response args
response_args = {'title': 'Beer Fermentation Control System'}
# Open up the connection to the database, execute the query,
# grab the results, then close the DB connection.
db_conn = sqlite3.connect(DB_PATH)
db = db_conn.cursor()
db.execute("select strftime('%m/%d/%Y', date(ts, 'unixepoch')), "
" count(ts), avg(temp1), max(temp1), min(temp1),"
" avg(temp2), max(temp2), min(temp2), avg(temp3),"
" max(temp3), min(temp3), avg(temp4), max(temp4),"
" min(temp4)"
"from temp_data "
"group by date(ts, 'unixepoch')")
response_args['results'] = db.fetchall()
db_conn.close()
# Generate the stream and then render it to HTML
stream = template.generate(**response_args)
response_body = stream.render('html', doctype='html', encoding='utf-8')
# Set the appropriate response headers
response_headers = [('Content-Type', 'text/html; charset=utf-8'),
('Content-Length', str(len(response_body)))]
elif environ['PATH_INFO'].startswith('/day/') and environ['PATH_INFO'].endswith('/all'):
# Load the all template
template = loader.load('all.html')
# Parse the date out of the URL (TODO: validate all this)
day = environ['PATH_INFO'][5:7]
month = environ['PATH_INFO'][7:9]
year = environ['PATH_INFO'][9:13]
date = '%s/%s/%s' % (month, day, year)
# Create the response args
response_args = {'title': 'Sensor Readings for %s' % date}
# Open up the connection to the database, execute the query
# (limit to today and the past 5 minutes),
# grab the results, then close the DB connection.
db_conn = sqlite3.connect(DB_PATH)
db = db_conn.cursor()
db.execute("select strftime('%%H:%%M:%%S', ts, 'unixepoch'), "
" temp1, temp2, temp3, temp4, relay_status "
"from temp_data "
"where date(ts, 'unixepoch') is date('%s-%s-%s')"
"order by ts desc" % (year, month, day))
response_args['results'] = db.fetchall()
db_conn.close()
# Generate the stream and then render it to HTML
stream = template.generate(**response_args)
response_body = stream.render('html', doctype='html', encoding='utf-8')
# Set the appropriate response headers
response_headers = [('Content-Type', 'text/html; charset=utf-8'),
('Content-Length', str(len(response_body)))]
elif environ['PATH_INFO'].startswith('/day/'):
# Load the day template
template = loader.load('day.html')
# Parse the date out of the URL (TODO: validate all this)
day = environ['PATH_INFO'][5:7]
month = environ['PATH_INFO'][7:9]
year = environ['PATH_INFO'][9:13]
date = '%s/%s/%s' % (month, day, year)
# Create the response args
response_args = {'title': 'Sensor Readings for %s' % date,
'url_date': environ['PATH_INFO'][5:13]}
# Open up the connection to the database, execute the query
# (limit to today and the past 5 minutes),
# grab the results, then close the DB connection.
db_conn = sqlite3.connect(DB_PATH)
db = db_conn.cursor()
db.execute("select strftime('%%H:%%M:%%S', ts, 'unixepoch'), "
" temp1, temp2, temp3, temp4, relay_status "
"from temp_data "
"where date(ts, 'unixepoch') is date('%s-%s-%s')"
"order by ts desc limit 300" % (year, month, day))
response_args['results'] = db.fetchall()
# Chart query
#
db.execute("select strftime('%%H:%%M:%%S', ts, 'unixepoch'), ts, temp1, "
" temp2, temp3, temp4 from ( "
"select ts, temp1, temp2, temp3, temp4 "
"from temp_data "
"where date(ts, 'unixepoch') is date('%s-%s-%s')"
"order by ts desc limit 60) order by ts"
% (year, month, day))
chart_results = db.fetchall()
# Process chart query results
sensor1_data = []
sensor2_data = []
sensor3_data = []
sensor4_data = []
for row in chart_results:
sensor1_data.append([int(row[1]) * 1000, row[2]])
sensor2_data.append([int(row[1]) * 1000, row[3]])
sensor3_data.append([int(row[1]) * 1000, row[4]])
sensor4_data.append([int(row[1]) * 1000, row[5]])
response_args['sensor1_data'] = str(sensor1_data)
response_args['sensor2_data'] = str(sensor2_data)
response_args['sensor3_data'] = str(sensor3_data)
response_args['sensor4_data'] = str(sensor4_data)
# This is a bit of hack to get around a javascript issue in
# the template
# response_args['chart_results'] = chart_results[:-1]
# response_args['chart_last_row'] = chart_results[-1]
db_conn.close()
# Generate the stream and then render it to HTML
stream = template.generate(**response_args)
response_body = stream.render('html', doctype='html', encoding='utf-8')
# Set the appropriate response headers
response_headers = [('Content-Type', 'text/html; charset=utf-8'),
('Content-Length', str(len(response_body)))]
elif environ['PATH_INFO'] == ('/chart_update'):
# Update the self updating chart
response_body = ''
if environ['QUERY_STRING']:
# Parse the query string to get the last timestamp from the client
get_args = cgi.parse_qs(environ['QUERY_STRING'])
last_ts = int(get_args['last_ts'][0])
date_from_ts = datetime.datetime.fromtimestamp(last_ts)
# Reconstruct portions of the date from the ts
year = date_from_ts.year
month = '%02d' % date_from_ts.month
day = '%02d' % date_from_ts.day
# Grab any entries from the supplied date that are greater than
# the last timestamp sent from the client javascript
db_conn = sqlite3.connect(DB_PATH)
db = db_conn.cursor()
db.execute("select strftime('%%H:%%M:%%S', ts, 'unixepoch'), ts, "
" temp1, temp2, temp3, temp4, relay_status "
"from temp_data "
"where date(ts, 'unixepoch') is date('%s-%s-%s') and "
" ts > %s "
"order by ts asc limit 60" % (year, month, day, last_ts))
db_rows = db.fetchall()
db_conn.close()
# Iterate over the rows fetched by the query and pretty them up
# in preparation of being sent back to the client javascript for
# display
result_rows = []
for row in db_rows:
result_rows.append('%s %s %s %s %s %s %s' %
(row[0], (int(row[1]) * 1000),
row[2], row[3], row[4], row[5],
int(row[6]) and 'on' or 'off'))
response_body = ','.join(result_rows)
response_body = response_body.encode('utf-8')
response_headers = [('Content-Type', 'text/plain; charset=utf-8'),
('Content-Length', str(len(response_body)))]
controller = MainPageController('main.html', environ)
response_headers, response_body = controller.generate_response()
else:
# User supplied an invalid URL
response_body = 'Invalid URL "%s"' % environ['PATH_INFO']
software/bookmark_library/bmklib/web/controllers/main.py
import sqlite3
from bmklib.web.base_controller import BaseHTMLController, DB_PATH
class MainPageController(BaseHTMLController):
def build_content(self):
conn = sqlite3.connect(DB_PATH)
db = conn.cursor()
db.execute("SELECT COUNT(*) FROM bookmarks")
row = db.fetchone()
self.content['total_num_bmks'] = row[0]
software/bookmark_library/bmklib/web/templates/main.html
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:py="http://genshi.edgewall.org/">
<head>
<title>Bookmark Library</title>
<style type="text/css">
body {
font-family: sans-serif;
font-size: 16px
}
h3 {
font-size: 24px;
}
table {
border: 1px solid #000;
border-spacing: 0px;
margin-left: auto;
margin-right: auto;
}
table a:link {
color: #000;
text-decoration: none;
}
table a:visited {
color: #000;
text-decoration: none;
}
table a:hover {
color: #000;
text-decoration: underline;
}
tr.even {
background-color: #FFF;
}
tr.odd {
background-color: #FFC;
}
th {
border: 1px solid #000;
padding: 10px;
border-spacing: 2px;
}
td {
border-top: 1px solid #000;
padding: 2px 5px;
}
</style>
</head>
<body>
<h1>Bookmark Library</h1>
There are currently ${total_num_bmks} bookmarks in the library.
</body>
</html>

Also available in: Unified diff