# 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

""" ### ### ### STATUS_FOOTER_HTML = """
GeneratorON
""" # 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("GeneratorON") else: self.wfile.write("GeneratorOFF") if (sample_data[3] == "1"): self.wfile.write("Air ConditionerON") else: self.wfile.write("Air ConditionerOFF") self.wfile.write("Fuel (History)") fuel = int(sample_data[4]) * 0.09775171 if (fuel < 50): self.wfile.write("") else: self.wfile.write("") self.wfile.write(fuel) self.wfile.write("%") self.wfile.write("Camera Heading") self.wfile.write(sample_data[5]) self.wfile.write("") self.wfile.write("Timestamp") self.wfile.write(sample_data[0]) self.wfile.write(" ") self.wfile.write(sample_data[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()