How to handle sockets - easily?
nickname at banelli.biz.invalid
Wed Feb 16 18:26:40 CET 2011
Richard Kettlewell's log on stardate 10 vlj 2011
> Rewrites can help but they can also go badly wrong. Rewriting into a
> language you don't yet know seems especially likely to fall into the
> latter category!
However, it seems to be quite "doable", as it took me from 0 knowledge
of Python to come up with a solution that does only part of the thing
(it's missing CRC check for GPS data and NMEA checksum, user control
for changing device setup on the fly via web and few more details).
Here's the code (ATTN: may wrap):
#! /usr/bin/env python
data = self.recv(128) #payload size
data = string.lstrip(data,"\n") #sometimes a 0xOA stays
data_len = len (data) #get payload length
trackerID_hex = data[4:11] #tracker ID
trackerID = "" #create empty string
for i in trackerID_hex:
trackerID += str('%02X'%ord(i)) #convert hex integer to string and append to trackerID
trackerID = string.rstrip(trackerID,"F") #remove stuffed F's from tracker ID
checksum = ""
checksum_hex = data[data_len-4:data_len-1] #second part of command payload, checksum
for i in checksum_hex:
checksum += str('%02X'%ord(i)) #convert hex integer to string and append to trackerID
GPSdata = data[13:data_len-4] #GPRMC - hhmmss.dd,S,xxmm.dddd,<N|S>,yyymm.dddd,<E|W>,s.s,h.h,ddmmyy
l = list()
l = string.split(GPSdata, ",")
n = len(l)
if n > 1: #hack! devices can mess the output, so just discard the data and go to another sample
GPStime = l
GPStime = GPStime[0:2] + ":" + GPStime[2:4] + ":" + GPStime[4:6]
GPSstatus = l
GPSlatitude = l
GPSlatitude = float(GPSlatitude[0:2]) + float(GPSlatitude[2:10]) / 60
GPSNS = l
GPSlongitude = l
GPSlongitude = float(GPSlongitude[0:3]) + float(GPSlongitude[3:11]) / 60
GPSEW = l
GPSspeed = float(l)
GPSspeed = 0
GPSspeed *= 1.852
GPSheading = float(l)
GPSheading = 0
GPSdate = l
GPSdate = "20" + GPSdate[4:6] + "-" + GPSdate[2:4] + "-" + GPSdate[0:2]
conn = MySQLdb.connect (host = "localhost", user = "", passwd = "", db = "") #:p
except MySQLdb.Error, e:
print "Error %d: %s" % (e.args, e.args)
cursor = conn.cursor()
query = "INSERT INTO data (trackerID, GPStime, GPSstatus, GPSlatitude, GPSNS, GPSlongitude, GPSEW, GPSspeed, GPSheading, GPSdate) VALUES ('" + trackerID + "', '" + GPStime + "', '" + GPSstatus + "', '" + str(GPSlatitude) + "', '" + GPSNS + "', '" + str(GPSlongitude) + "', '" + GPSEW + "', '" + str(GPSspeed) + "', '" + str(GPSheading) + "', '" + GPSdate + "')"
def __init__(self, host, port):
pair = self.accept()
if pair is None:
sock, addr = pair
print 'Incoming connection from %s' % repr(addr)
handler = Handler(sock)
server = Server('', 2020)
C code did not parse data, but rather put the whole payload to SQL
database, which would be parsed afterwards. This code takes almost
twice LOC less that C code.
I do, however, have some more questions (thus crosspost to
comp.lang.python) - how many connections can this server handle without
a problem? I'm using Asyncore module, as it can be seen.
Is it necessary, due to the fact that it should serve more than
thousand devices that send data every 10 seconds, to do threading (I
believe that is already done with Asyncore for sockets, but what about
Any other general code suggestions (since this is the first time I
write anything in Python)?
"If you lie to the compiler,
it will get its revenge."
More information about the Python-list