# Access Arduino data from SheevaPlug
# Graph data and serve as web pages
#
# Copyright 2009 Ken Shirriff
# http://arcfn.com
import os
import serial
import threading
import time
from BaseHTTPServer import HTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
FUEL_GNUPLOT_CMD = """\
set xdata time
set format x "%m/%d"
set xtic 86400
set timefmt "%m/%d/%Y %H:%M"
set terminal png xeeeeee x000000 size 500, 500
set output 'fuel_graph.png'
set xlabel "Date"
set ylabel "Fuel"
set title "Fuel Status"
plot "/tmp/data" using 1:5 title "" with lines
"""
FUEL_GRAPH_HTML = """
Fuel History
Graph of available fuel
Note: the fuel level is in arbitrary units 0-1023
"""
STATUS_HEADER_HTML = """
Telemetry Demo
Current Status
"""
###
###
Generator
ON
###
STATUS_FOOTER_HTML = """
"""
# The web server. Supports /graph (page containing the graph)
# and static web pages
class MyHandler(SimpleHTTPRequestHandler):
def do_GET(self):
if self.path == '/fuel_graph':
return self.fuel_graph()
if self.path == '/status':
return self.status_table()
if self.path == '/raw':
return self.latest()
# Static file
return SimpleHTTPRequestHandler.do_GET(self)
# return raw data
def latest(self):
latest = os.popen('tail -1 /tmp/latest','r')
line = latest.readline()
self.send_response(200)
self.send_header('Content-type', 'text/plain')
self.end_headers()
self.wfile.write(line)
# Generate and display the graph
def graph(self):
g = os.popen('gnuplot', 'w')
print >>g, GNUPLOT_CMD
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(GRAPH_HTML)
# Generate and display the fuel graph
def fuel_graph(self):
g = os.popen('gnuplot', 'w')
print >>g, FUEL_GNUPLOT_CMD
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(FUEL_GRAPH_HTML)
# Status table generator
def status_table(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
self.wfile.write(STATUS_HEADER_HTML)
###latest = open('/tmp/latest','r')
latest = os.popen('tail -1 /tmp/latest','r')
line = latest.readline()
sample_data = line.split();
if (sample_data[2] == "1"):
self.wfile.write("
")
self.wfile.write(STATUS_FOOTER_HTML)
latest.flush()
latest.close()
# Read data from Arduino serial port a line at a time
# and dump to file with timestamps
class Arduino(threading.Thread):
def run(self):
f = open('/tmp/data', 'a')
latest = open('/tmp/latest', 'w')
# Port may vary from /dev/ttyUSB1
self.ser = serial.Serial('/dev/ttyUSB0', 115200, timeout=10)
self.ser.flushInput()
old_timestamp = None
while 1:
data = self.ser.readline().strip()
if data:
timestamp = time.strftime("%m/%d/%Y %H:%M", time.localtime())
if timestamp != old_timestamp:
# Only log once per minute
print >>f, timestamp, data.strip()
old_timestamp = timestamp
print >>latest, timestamp, data.strip()
f.flush()
latest.flush()
def main():
ard = Arduino()
ard.start()
server = HTTPServer(('', 80), MyHandler)
print 'Starting server'
server.serve_forever()
if __name__ == '__main__':
main()