Commits

Robert Filipovich committed 58c9594

adding code

Comments (0)

Files changed (8)

+#!/usr/bin/python
+
+import sys, os, time, atexit
+from signal import SIGTERM 
+
+class Daemon:
+	"""
+	A generic daemon class.
+	
+	Usage: subclass the Daemon class and override the run() method
+	"""
+	def __init__(self, pidfile, stdin='/dev/null', stdout='/dev/null', stderr='/dev/null'):
+		self.stdin = stdin
+		self.stdout = stdout
+		self.stderr = stderr
+		self.pidfile = pidfile
+	
+	def daemonize(self):
+		"""
+		do the UNIX double-fork magic, see Stevens' "Advanced 
+		Programming in the UNIX Environment" for details (ISBN 0201563177)
+		http://www.erlenstar.demon.co.uk/unix/faq_2.html#SEC16
+		"""
+		try: 
+			pid = os.fork() 
+			if pid > 0:
+				# exit first parent
+				sys.exit(0) 
+		except OSError, e: 
+			sys.stderr.write("fork #1 failed: %d (%s)\n" % (e.errno, e.strerror))
+			sys.exit(1)
+	
+		# decouple from parent environment
+		os.chdir("/") 
+		os.setsid() 
+		os.umask(0) 
+	
+		# do second fork
+		try: 
+			pid = os.fork() 
+			if pid > 0:
+				# exit from second parent
+				sys.exit(0) 
+		except OSError, e: 
+			sys.stderr.write("fork #2 failed: %d (%s)\n" % (e.errno, e.strerror))
+			sys.exit(1) 
+	
+		# redirect standard file descriptors
+		sys.stdout.flush()
+		sys.stderr.flush()
+		si = file(self.stdin, 'r')
+		so = file(self.stdout, 'a+')
+		se = file(self.stderr, 'a+', 0)
+		os.dup2(si.fileno(), sys.stdin.fileno())
+		os.dup2(so.fileno(), sys.stdout.fileno())
+		os.dup2(se.fileno(), sys.stderr.fileno())
+	
+		# write pidfile
+		atexit.register(self.delpid)
+		pid = str(os.getpid())
+		file(self.pidfile,'w+').write("%s\n" % pid)
+	
+	def delpid(self):
+		os.remove(self.pidfile)
+
+	def start(self):
+		"""
+		Start the daemon
+		"""
+		# Check for a pidfile to see if the daemon already runs
+		try:
+			pf = file(self.pidfile,'r')
+			pid = int(pf.read().strip())
+			pf.close()
+		except IOError:
+			pid = None
+	
+		if pid:
+			message = "pidfile %s already exist. Daemon already running?\n"
+			sys.stderr.write(message % self.pidfile)
+			sys.exit(1)
+		
+		# Start the daemon
+		self.daemonize()
+		self.run()
+
+	def stop(self):
+		"""
+		Stop the daemon
+		"""
+		# Get the pid from the pidfile
+		try:
+			pf = file(self.pidfile,'r')
+			pid = int(pf.read().strip())
+			pf.close()
+		except IOError:
+			pid = None
+	
+		if not pid:
+			message = "pidfile %s does not exist. Daemon not running?\n"
+			sys.stderr.write(message % self.pidfile)
+			return # not an error in a restart
+
+		# Try killing the daemon process	
+		try:
+			while 1:
+				os.kill(pid, SIGTERM)
+				time.sleep(0.1)
+		except OSError, err:
+			err = str(err)
+			if err.find("No such process") > 0:
+				if os.path.exists(self.pidfile):
+					os.remove(self.pidfile)
+			else:
+				print str(err)
+				sys.exit(1)
+
+	def restart(self):
+		"""
+		Restart the daemon
+		"""
+		self.stop()
+		self.start()
+
+	def run(self):
+		"""
+		You should override this method when you subclass Daemon. It will be called after the process has been
+		daemonized by start() or restart().
+		"""

v0.1/gpsLogger.py

+#!/usr/bin/python -tt
+#gpslogger.py
+import logging
+
+logger = logging.getLogger('gpslogger')
+hdlr = logging.FileHandler('/var/log/gpslogger.log')
+formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
+hdlr.setFormatter(formatter)
+logger.addHandler(hdlr)
+logger.setLevel(logging.INFO)
+
+class gpslog:
+	
+	
+	def __init__(self, logtype, message):
+		self.logtype = logtype
+		self.logmessage = message
+		if self.logtype == 'ERROR':
+			logger.error(self.logmessage)
+		else:
+			logger.info(self.logmessage)

v0.1/gpsPostData.py

+#!/usr/bin/python -tt
+
+import urllib
+import urllib2
+import wddx
+from gpsLogger import gpslog
+
+import ConfigParser
+
+config = ConfigParser.RawConfigParser()
+config.read('/etc/gpstrack.conf')
+url = config.get("parms", "url")
+
+class postGPSData:
+	
+	def __init__(self, unit, gpsTime, gpsLat, gpsLong, gpsSpeed, gpsCourse):
+		self.unit = unit
+		self.gpsTime = gpsTime
+		self.gpsLat = gpsLat
+		self.gpsLong = gpsLong
+		self.gpsSpeed = gpsSpeed
+		self.gpsCourse = gpsCourse
+		try:
+			params = urllib.urlencode({
+				'method': 'gpsData',
+				'unit': self.unit,
+				'gpsTime': self.gpsTime,
+				'gpsLat':	self.gpsLat,
+				'gpsLong':self.gpsLong,
+				'gpsSpeed':	self.gpsSpeed,
+				'gpsCourse':self.gpsCourse
+				})
+			response = urllib2.urlopen(url, params).read()
+			test = wddx.loads(response)
+			print test[0]
+		except urllib2.URLError as err:
+			gpslog('ERROR', 'GPS POST ERROR: ' + err)
+			pass 

v0.1/gpsTrackLog.py

+#!/usr/bin/python -tt
+
+import logging
+
+logger = logging.getLogger('gpstrack')
+hdlr = logging.FileHandler('/var/log/gpstrack.log')
+formatter = logging.Formatter('%(asctime)s %(levelname)s %(message)s')
+hdlr.setFormatter(formatter)
+logger.addHandler(hdlr)
+logger.setLevel(logging.INFO)
+
+class gpstrack:
+	
+	
+	def __init__(self, logtype, message):
+		self.logtype = logtype
+		self.logmessage = message
+		if self.logtype == 'ERROR':
+			logger.error(self.logmessage)
+		else:
+			logger.info(self.logmessage)

v0.1/gpsserver.py

+#!/usr/bin/python -tt
+#gpsserver.py
+import ConfigParser
+import urllib2, os
+from serialGetGPS import startSerialCapture
+import sys, time
+from daemon import Daemon
+from gpsLogger import gpslog
+
+class MyDaemon(Daemon):
+	def run(self):
+		istatus = False
+		config = ConfigParser.RawConfigParser()
+		config.read('/etc/gpstrack.conf')
+		gpsunit = config.get("parms", "unitnumber")
+		while istatus == False:
+			try:
+				response=urllib2.urlopen('http://74.125.113.99',timeout=1)
+				istatus = True
+				##print 'Internet up starting serial Capture'
+				gpslog('INFO', 'Internet up starting serial Capture')
+				startSerialCapture(gpsunit)
+			except urllib2.URLError as err:
+				pass
+				istatus = False
+				print 'No internet still testing before serial capture starts'
+				gpslog('ERROR', 'No internet still testing before serial capture starts')
+				time.sleep(1)
+
+if __name__ == "__main__":
+	daemon = MyDaemon('/var/run/gpsserver.pid')
+	if len(sys.argv) == 2:
+		if 'start' == sys.argv[1]:
+			gpslog('INFO', 'GPS Server Started')
+			daemon.start()
+		elif 'stop' == sys.argv[1]:
+			gpslog('INFO', 'GPS Server Stopped')
+			daemon.stop()
+		elif 'restart' == sys.argv[1]:
+			gpslog('INFO', 'GPS Server Restarting')
+			daemon.restart()
+		else:
+			print "Unknown command"
+			sys.exit(2)
+		sys.exit(0)
+	else:
+		print "usage: %s start|stop|restart" % sys.argv[0]
+		sys.exit(2)

v0.1/parseNMEA.py

+#!/usr/bin/python -tt
+"""
+========
+NMEAgram
+========
+A Quick Parser for Common NMEA Sentences
+========================================
+
+:Copyright: Copyright 2007 Dean Hall.  All rights reserved.
+:Author: Dean Hall
+:Revision: 0.1
+:Date: 2007/07/17
+
+This module parses these 6 common NMEA sentence types:
+
+- GPGGA Global positioning system fixed data
+- GPGLL Geographic position- latitude/longitude
+- GPGSA GNSS DOP and active satellites
+- GPGSV GNSS satellites in view
+- GPRMC Recommended minimum specific GNSS data
+- GPVTG Course over ground and ground speed
+"""
+
+
+import string
+
+
+# This dict holds the global parsed data
+data = {}
+
+
+def toDecimalDegrees(ddmm):
+    """
+    Converts a string from ddmm.mmmm or dddmm.mmmm format
+    to a float in dd.dddddd format
+    """
+
+    splitat = string.find(ddmm, '.') - 2
+    return _float(ddmm[:splitat]) + _float(ddmm[splitat:]) / 60.0
+
+
+def _float(s):
+    """
+    Returns the float value of string s if it exists,
+    or None if s is an empty string.
+    """
+    if s:
+        return float(s)
+    else:
+        return None
+
+
+def _int(s):
+    """
+    Returns the int value of string s if it exists,
+    or None if s is an empty string.
+    """
+    if s:
+        return int(s)
+    else:
+        return None
+
+
+def calcCheckSum(line):
+    """
+    Returns the checksum as a one byte integer value.
+    In this case the checksum is the XOR of everything after '$' and before '*'.
+    """
+    s = 0
+    for c in line[1:-3]:
+        s = s ^ ord(c)
+    return s
+
+
+def parseGGA(fields):
+    """
+    Parses the Global Positioning System Fix Data sentence fields.
+    Stores the results in the global data dict.
+    """
+
+    # GGA has 15 fields
+    assert len(fields) == 15
+
+    # MsgId = fields[0]
+    data['UtcTime'] = fields[1]
+    data['Latitude'] = toDecimalDegrees(fields[2])
+    data['NsIndicator'] = fields[3]
+    data['Longitude'] = toDecimalDegrees(fields[4])
+    data['EwIndicator'] = fields[5]
+    data['PositionFix'] = fields[6]
+    data['SatellitesUsed'] = _int(fields[7])
+    data['HorizontalDilutionOfPrecision'] = _float(fields[8])
+    data['MslAltitude'] = _float(fields[9])
+    data['MslAltitudeUnits'] = fields[10]
+    data['GeoidSeparation'] = _float(fields[11])
+    data['GeoidSeparationUnits'] = fields[12]
+    data['AgeOfDiffCorr'] = _float(fields[13])
+    data['DiffRefStationId'] = fields[14]
+
+    # Attend to lat/lon plus/minus signs
+    if data['NsIndicator'] == 'S':
+        data['Latitude'] *= -1.0
+    if data['EwIndicator'] == 'W':
+        data['Longitude'] *= -1.0
+
+
+def parseGLL(fields):
+    """
+    Parses the Geographic Position-Latitude/Longitude sentence fields.
+    Stores the results in the global data dict.
+    """
+
+    # GLL has 8 fields
+    assert len(fields) == 7
+
+    # MsgId = fields[0]
+    data['Latitude'] = toDecimalDegrees(fields[1])
+    data['NsIndicator'] = fields[2]
+    data['Longitude'] = toDecimalDegrees(fields[3])
+    data['EwIndicator'] = fields[4]
+    data['UtcTime'] = fields[5]
+    data['GllStatus'] = fields[6]
+
+    # Attend to lat/lon plus/minus signs
+    if data['NsIndicator'] == 'S':
+        data['Latitude'] *= -1.0
+    if data['EwIndicator'] == 'W':
+        data['Longitude'] *= -1.0
+
+
+def parseGSA(fields):
+    """
+    Parses the GNSS DOP and Active Satellites sentence fields.
+    Stores the results in the global data dict.
+    """
+
+    # GSA has 18 fields
+    assert len(fields) == 18
+
+    # MsgId = fields[0]
+    data['Mode1'] = fields[1]
+    data['Mode2'] = _int(fields[2])
+    data['SatCh1'] = _int(fields[3])
+    data['SatCh2'] = _int(fields[4])
+    data['SatCh3'] = _int(fields[5])
+    data['SatCh4'] = _int(fields[6])
+    data['SatCh5'] = _int(fields[7])
+    data['SatCh6'] = _int(fields[8])
+    data['SatCh7'] = _int(fields[9])
+    data['SatCh8'] = _int(fields[10])
+    data['SatCh9'] = _int(fields[11])
+    data['SatCh10'] = _int(fields[12])
+    data['SatCh11'] = _int(fields[13])
+    data['SatCh12'] = _int(fields[14])
+    data['PDOP'] = _float(fields[15])
+    data['HDOP'] = _float(fields[16])
+    data['VDOP'] = _float(fields[17])
+
+
+def parseGSV(fields):
+    """
+    Parses the GNSS Satellites in View sentence fields.
+    Stores the results in the global data dict.
+    """
+
+    # GSV has a variable number of fields
+    numfields = len(fields)
+    assert numfields in (8, 12, 16, 20)
+
+    # MsgId = fields[0]
+    data['NumMsgs'] = _int(fields[1])
+    data['MsgNum'] = _int(fields[2])
+    data['SatsInView'] = fields[3]
+
+    # Create struct (only needed first time this is called)
+    if 'SatelliteId' not in data.keys():
+        data['SatelliteId'] = {}
+        data['Elevation'] = {}
+        data['Azimuth'] = {}
+        data['Snr'] = {}
+
+    # Calculate index offset
+    n = 4 * (int(fields[2]) - 1)
+
+    data['SatelliteId'][n] = _int(fields[4])
+    data['Elevation'][n] = _int(fields[5])
+    data['Azimuth'][n] = _int(fields[6])
+    data['Snr'][n] = _int(fields[7])
+
+    if numfields >= 12:
+        nn = n + 1
+        data['SatelliteId'][nn] = _int(fields[8])
+        data['Elevation'][nn] = _int(fields[9])
+        data['Azimuth'][nn] = _int(fields[10])
+        data['Snr'][nn] = _int(fields[11])
+
+    if numfields >= 16:
+        nn = n + 2
+        data['SatelliteId'][nn] = _int(fields[12])
+        data['Elevation'][nn] = _int(fields[13])
+        data['Azimuth'][nn] = _int(fields[14])
+        data['Snr'][nn] = _int(fields[15])
+
+    if numfields == 20:
+        nn = n + 3
+        data['SatelliteId'][nn] = _int(fields[16])
+        data['Elevation'][nn] = _int(fields[17])
+        data['Azimuth'][nn] = _int(fields[18])
+        data['Snr'][nn] = _int(fields[19])
+
+    # If this is the last GSV sentence in this series,
+    # erase old fields when fewer satellites are received than last series
+    if fields[1] == fields[2]:
+        while nn < len(data['SatelliteId']):
+            del data['SatelliteId'][nn]
+            del data['Elevation'][nn]
+            del data['Azimuth'][nn]
+            del data['Snr'][nn]
+            nn += 1
+
+
+def parseRMC(fields):
+    """
+    Parses the Recommended Minimum Specific GNSS Data sentence fields.
+    Stores the results in the global data dict.
+
+    WARNING: This parsing is based on an actual SiRFstar III RMC sentence
+    which differs from SiRF's NMEA manual revision 1.3 (Jan. 2005).
+    The actual data has one extra empty field after Magnetic Variation.
+    """
+
+    # RMC has 13 fields
+    assert len(fields) == 13
+
+    # MsgId = fields[0]
+    data['UtcTime'] = fields[1]
+    data['RmcStatus'] = fields[2]
+    data['Latitude'] = toDecimalDegrees(fields[3])
+    data['NsIndicator'] = fields[4]
+    data['Longitude'] = toDecimalDegrees(fields[5])
+    data['EwIndicator'] = fields[6]
+    data['SpeedOverGround'] = _float(fields[7])
+    data['CourseOverGround'] = _float(fields[8])
+    data['Date'] = fields[9]
+    data['MagneticVariation'] = fields[10]
+    data['UnknownEmptyField'] = fields[11]
+    data['RmcMode'] = fields[12]
+
+    # Attend to lat/lon plus/minus signs
+    if data['NsIndicator'] == 'S':
+        data['Latitude'] *= -1.0
+    if data['EwIndicator'] == 'W':
+        data['Longitude'] *= -1.0
+
+
+def parseVTG(fields):
+    """
+    Parses the Course Over Ground and Ground Speed sentence fields.
+    Stores the results in the global data dict.
+    """
+
+    # VTG has 10 fields
+    assert len(fields) == 10
+
+    # MsgId = fields[0]
+    data['Course0'] = _float(fields[1])
+    data['Reference0'] = fields[2]
+    data['Course1'] = _float(fields[3])
+    data['Reference1'] = fields[4]
+    data['Speed0'] = _float(fields[5])
+    data['Units0'] = fields[6]
+    data['Speed1'] = _float(fields[7])
+    data['Units1'] = fields[8]
+    data['VtgMode'] = fields[9]
+
+
+def parseLine(line):
+    """
+    Parses an NMEA sentence, sets fields in the global structure.
+    Raises an AssertionError if the checksum does not validate.
+    Returns the type of sentence that was parsed.
+    """
+
+    # Get rid of the \r\n if it exists
+    line = line.rstrip()
+
+    # Validate the sentence using the checksum
+
+    assert calcCheckSum(line) == int(line[-2:], 16)
+
+    # Pick the proper parsing function
+    parseFunc = {
+        "$GPGGA": parseGGA,
+        "$GPGLL": parseGLL,
+        "$GPGSA": parseGSA,
+        "$GPGSV": parseGSV,
+        "$GPRMC": parseRMC,
+        "$GPVTG": parseVTG,
+        }[line[:6]]
+
+    # Call the parser with fields split and the tail chars removed.
+    # The characters removed are the asterisk, the checksum (2 bytes) and \n\r.
+    parseFunc(string.split(line[:-3], ','))
+
+    # Return the type of sentence that was parsed
+    return line[3:6]
+
+
+def getField(fieldname):
+    """
+    Returns the value of the named field.
+    """
+    return data[fieldname]

v0.1/serialGetGPS.py

+#!/usr/bin/python -tt
+#serialGetGPS.py
+
+import serial, time, csv, sys
+import parseNMEA
+from gpsPostData import postGPSData
+from datetime import datetime
+from dateutil import tz
+from gpsTrackLog import gpstrack
+from gpsLogger import gpslog
+from unitCallHome import callhome
+
+def startSerialCapture(trackUnit):
+	##different commands to set the update rate from once a second (1 Hz) to 10 times a second (10Hz)
+	PMTK_SET_NMEA_UPDATE_1HZ = '$PMTK220,1000*1F\r\n'
+	PMTK_SET_NMEA_UPDATE_5HZ = '$PMTK220,200*2C\r\n'
+	PMTK_SET_NMEA_UPDATE_10H = '$PMTK220,100*2F\r\n'
+	unitNum = trackUnit
+	##print unitNum
+	##turn on only the second sentence (GPRMC)
+	PMTK_SET_NMEA_OUTPUT_RMCONLY = '$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n'
+	##turn on GPRMC and GGA
+	PMTK_SET_NMEA_OUTPUT_RMCGGA = '$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n'
+	##turn on ALL THE DATA
+	PMTK_SET_NMEA_OUTPUT_ALLDATA = '$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n'
+	## turn off output
+	PMTK_SET_NMEA_OUTPUT_OFF = '$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n'
+	knot=float(1.15077945)
+	
+	DEVICE = '/dev/ttyAMA0'
+	BAUD = 115200
+	ser = serial.Serial(DEVICE, BAUD)
+	ser.open()
+	ser.flush()
+	##ser.writelines(PMTK_SET_NMEA_UPDATE_1HZ, PMTK_SET_NMEA_OUTPUT_RMCONLY)
+	ser.write(PMTK_SET_NMEA_UPDATE_1HZ)
+	ser.write(PMTK_SET_NMEA_OUTPUT_RMCONLY)
+	##ser.write(PMTK_SET_NMEA_OUTPUT_RMCGGA)
+	
+	ser.close()
+	time.sleep(1)
+	BAUD = 9600
+	ser = serial.Serial(DEVICE, BAUD)
+	ser.open()
+	count = 0
+	out = ''
+	##callhome(trackUnit)
+	while True:
+		while ser.inWaiting() > 0:
+			out = ser.readline()
+			##	print "sats:" + str(numSats)
+			if out.startswith("$GPRMC"):
+				# Create the object
+				count = count + 1
+				##print count
+				##print repr(out)
+				##gpstrack('INFO', repr(out))
+				try:
+					parseNMEA.parseLine(out)
+					fail = 0
+				except (AssertionError, ValueError, TypeError) as e:
+					fail = 1
+					##print 'CHECKSUM ERROR 2'
+					gpslog('ERROR', 'CHECKSUM ERROR: '+ e)
+				
+				if fail == 0:
+					timeUTC = time.strftime("%H:%M:%S", time.strptime(parseNMEA.getField('UtcTime').split(".")[0],"%H%M%S"))
+					try:
+						speedGPS = parseNMEA.getField('SpeedOverGround')
+					except ValueError:
+						speedGPS = float(0)
+						##print "Error 2"
+						gpslog('ERROR', e)
+					mph = round(speedGPS*knot,2)
+					gpsLat = parseNMEA.getField('Latitude')
+					gpsLong = parseNMEA.getField('Longitude')
+					gpsCourse = round(parseNMEA.getField('CourseOverGround'))
+					logme = "time:", timeUTC, "lat:", gpsLat, "long:", gpsLong, "speed:", mph, "course:", gpsCourse
+					##gpstrack('INFO', logme)
+					if (count % 10) == 0:
+						postGPSData(unitNum, timeUTC, gpsLat, gpsLong, mph, gpsCourse)
+					
+					if (count % 600) == 0:
+						callhome(unitNum)
+			
+
+	
+##time.sleep(10)
+	

v0.1/unitCallHome.py

+#!/usr/bin/python -tt
+
+import urllib
+import urllib2
+import wddx, time
+from gpsLogger import gpslog
+import ConfigParser
+
+config = ConfigParser.RawConfigParser()
+config.read('/etc/gpstrack.conf')
+url = config.get("parms", "url")
+
+def callhome(trackunit):
+	try:
+		params = urllib.urlencode({
+		'method': 'unitCallHome',
+		'unit': trackunit
+		})
+		response = urllib2.urlopen(url, params).read()
+		test = wddx.loads(response)
+		gpslog('INFO', 'CALL HOME EXECUTED'+ str(test[0]))
+		
+	except urllib2.URLError as err:
+		gpslog('ERROR', 'CALL HOME ERROR: ' + err)
+		pass
+	
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.