#! /usr/bin/env python # MeHere 0001 # Copyright 2005, Glen Murphy import os, sys, thread, time, string, random from urllib import urlopen, urlretrieve from serial import Serial from socket import * class EnhancedSerial(Serial): def __init__(self, *args, **kwargs): #ensure that a reasonable timeout is set timeout = kwargs.get('timeout',0.1) if timeout < 0.01: timeout = 0.1 kwargs['timeout'] = timeout Serial.__init__(self, *args, **kwargs) self.buf = '' def readline(self, maxsize=None, timeout=1): """maxsize is ignored, timeout in seconds is the max time that is way for a complete line""" tries = 0 while 1: self.buf += self.read(512) pos = self.buf.find('\n') if pos >= 0: line, self.buf = self.buf[:pos+1], self.buf[pos+1:] return line tries += 1 if tries * self.timeout > timeout: break line, self.buf = self.buf, '' return line def readlines(self, sizehint=None, timeout=1): """read all lines that are available. abort after timout when no more data arrives.""" lines = [] while 1: line = self.readline(timeout=timeout) if line: lines.append(line) if not line or line[-1:] != '\n': break return lines class mehere: def saveconfig(self): fp = open("config.ini", "w") fp.write(self.username+"\n") fp.write(self.password+"\n") fp.write(self.description+"\n") fp.write(self.gpsport+"\n") fp.close() def __init__(self): try: fp = open("config.ini", "r") self.username = fp.readline().strip() self.password = fp.readline().strip() self.description = fp.readline().strip() self.gpsport = fp.readline().strip() fp.close() except: self.username = "You" self.password = "" self.description = "" self.gpsport = "COM1" self.port = 7305 self.longitude = 0 self.latitude = 0 self.running = 1 self.ip = 0 self.public = 1 self.gpsdata = 0 self.gpsconnected = 0 # test if already running try: urlp = urlopen("http://localhost:7305/test") if urlp.read() == "1": print "Instance Already Running" self.openbrowser() self.running = 0 return urlp.close() except: pass if self.public: try: urlp = urlopen("http://glenmurphy.com/tools/ip.php") self.ip = urlp.read() urlp.close() print "External IP is %s" % self.ip except: print "Unable to determine IP, switching to private mode" self.public = 0 self.ip = "localhost" else: self.ip = "localhost" print "No external access." """ self.gps_thread = threading.Thread(target=self.gps) self.gps_thread.setDaemon(1) self.gps_thread.start() self.httpd_thread = threading.Thread(target=self.httpd) self.httpd_thread.setDaemon(1) self.httpd_thread.start() """ thread.start_new(self.gps, ()) thread.start_new(self.httpd, ()) ''' def __del__(self): self.s.close() print "serial port closed" self.sock.close() print "socket server closed" ''' def textblock(self, text): # UGLY, FIX ME output = "" for line in text.splitlines(): output += line.lstrip(" \t") + "\n"; return output def gps(self): # set up GPS connection while 1: self.gpsdata = 0 self.gpsconnected = 0 try: if self.s.isOpen(): self.s.close() except: pass if self.gpsport == "DEMOMODE": print "Entering Demo Mode" self.latitude = 37.39 self.longitude = -122.07 self.gpsconnected = 1 while self.gpsconnected: self.gpsdata = 1; self.latitude = self.latitude + 0.00001 self.longitude = self.longitude + 0.00001 time.sleep(1) else: while self.gpsconnected != 1: try: self.s = EnhancedSerial(self.gpsport, baudrate=4800, xonxoff=0, rtscts=0, timeout=1) self.gpsconnected = 1 print "%s Connected" % self.gpsport except: print "CONNECTION ERROR: %s" % self.gpsport self.gpsconnected = -1 self.gpsdata = 0 time.sleep(1) fails = 0 while self.gpsconnected: line = self.s.readline(timeout=1) datablock = line.split(',') if not self.s.isOpen(): print "GPS Disconnected" self.gpsconnected = 0 elif fails > 15: self.s.close() self.gpsconnected = 0 print "Too many serial port lines failed" elif line[0:6] == '$GPGGA' and datablock[2] and datablock[4]: latitude_in = string.atof(datablock[2]) longitude_in = string.atof(datablock[4]) if datablock[3] == 'S': latitude_in = -latitude_in if datablock[5] == 'W': longitude_in = -longitude_in latitude_degrees = int(latitude_in/100) latitude_minutes = latitude_in - latitude_degrees*100 longitude_degrees = int(longitude_in/100) longitude_minutes = longitude_in - longitude_degrees*100 self.latitude = latitude_degrees + (latitude_minutes/60) self.longitude = longitude_degrees + (longitude_minutes/60) self.gpsdata = 1 fails = 0 else: fails = fails + 1 def openbrowser(self): os.system("start http://localhost:7305/") def outputnetlink(self): if self.longitude != -999: return self.textblock("""\ HTTP/1.0 200 Content-type: text/xml %s %s %s %s 8000 0 0 %s,%s """ % ( self.username, self.description, self.longitude, self.latitude, self.longitude, self.latitude)) else: return self.textblock("""\ HTTP/1.0 200 Content-type: application/vnd.google-earth.kml+xml """) def outputshutdown(self): return self.textblock("""\ HTTP/1.0 200 Content-type: text/html Cheerio old bean. """) def outputgmaps(self): return self.textblock("""\ HTTP/1.0 200 Content-type: application/x-javascript var j = {x: %s, y: %s}; _m.map.recenterOrPanToLatLng(j); """ % (self.longitude, self.latitude)) def outputjs(self): return self.textblock("""\ HTTP/1.0 200 Content-type: application/x-javascript var mh_status = %s; var mh_coord = {long: %s, lat: %s}; """ % (self.gpsdata, self.longitude, self.latitude)) def outputcsv(self): return self.textblock("""\ HTTP/1.0 200 Content-type: text %s,%s,%s """ % (self.longitude, self.latitude, self.gpsdata)) def outputkmllocal(self): return self.textblock("""\ HTTP/1.0 200 Content-type: application/vnd.google-earth.kml+xml Content-disposition: attachment;filename=%s_googleearth.kml %s %s http://localhost:%s/netlink onInterval 1 onStop 1 """ % (self.username, self.username, self.description, self.port)) def outputkmlpublic(self): return self.textblock("""\ HTTP/1.0 200 Content-type: application/vnd.google-earth.kml+xml Content-disposition: attachment;filename=%s_googleearth.kml %s %s http://%s:%s/netlink onInterval 10 onStop 1 """ % (self.username, self.username, self.description, self.ip, self.port)) def xmlcoords(self): if self.gpsdata: return self.textblock('''\ HTTP/1.0 200 Content-type: text/xml ''') else: return self.textblock('''\ HTTP/1.0 200 Content-type: text/xml ''') def xmlstatus(self): if self.gpsconnected != 1: return self.textblock("""\ HTTP/1.0 200 Content-type: text/html ERROR:GPSCONNECTION""") elif self.gpsconnected == 1 and self.gpsdata == 0: return self.textblock("""\ HTTP/1.0 200 Content-type: text/html STATUS:GPSCONNECTED""") elif self.gpsconnected == 1 and self.gpsdata == 1: return self.textblock("""\ HTTP/1.0 200 Content-type: text/html READY""") def xmlsetcom(self, port): self.gpsport = port self.gpsconnected = 0 self.gpsdata = 0 self.saveconfig() return self.textblock("""\ HTTP/1.0 200 Content-type: text/html OK""") def outputinterface(self): if self.public: kmlstring = "Google Earth Public KML:
http://"+self.ip+":"+str(self.port)+"/kml" else: kmlstring = "Your machine is not publicly accessible, so public KML sharing is not enabled." return self.textblock("""\ HTTP/1.0 200 Content-type: text/html MeHere
""") def quit(self): time.sleep(1) self.running = 0 def handleClient(self, connection): data = connection.recv(2048) for line in data.splitlines(): guts = line.split(' ') if guts[0] == "GET": getargs = guts[1][1:].split('/') page = getargs[0] print page if page == "test": connection.send( "1" ) elif page[0:7] == "netlink": connection.send( self.outputnetlink() ) elif page == "kmllocal": connection.send( self.outputkmllocal() ) elif page == "kml": connection.send( self.outputkmlpublic() ) elif page == "csv": connection.send( self.outputcsv() ) elif page == "js": connection.send( self.outputjs() ) elif page == "" and self.address[0] == '127.0.0.1': connection.send( self.outputinterface() ) elif page == "xml" and self.address[0] == '127.0.0.1': if getargs[1] == "coords": connection.send( self.xmlcoords() ) elif getargs[1] == "status": connection.send( self.xmlstatus() ) elif getargs[1] == "setcom": connection.send( self.xmlsetcom(getargs[2]) ) elif page == "shutdown" and self.address[0] == '127.0.0.1': connection.send( self.outputshutdown() ) self.quit() else: connection.send( " " ) connection.close() def httpd(self): # set up webserver self.sock = socket( AF_INET, SOCK_STREAM ) if self.public: self.sock.bind( ("", self.port) ) else: self.sock.bind( ("localhost", self.port) ) self.sock.listen(5) print 'Creating server:' , self.sock.getsockname() self.openbrowser() while(1): self.newsock, self.address = self.sock.accept() # print "Incoming from: %s" % self.address[0] thread.start_new(self.handleClient, (self.newsock,)) n = mehere() while n.running == 1: time.sleep(1) del n