GPS Event [2] – Object

After some tinkering I was able to cook up some Python code to get the GPS data. So, a Magellan Meridian Gold GPS is connected over the serial port to a PC running Windows XP and Python. The Python version I am using is 2.52 and if you want to play with the code you may want to install the pySerial library before starting.

First, here is the result—cut & paste—from Python Shell.

<?xml version="1.0" encoding="UTF-8"?>
<event>
    <head>
        <id>91ce7524-3336-4619-a9a0-e8ee32d2f609</id>
        <type>GPS</type>
        <time_stamp>2008-12-30T20:19:31Z</time_stamp>
        <entity>DS_GPS_001</entity>
    </head>
    <body>
        <latitude>43 38.8317 N</latitude>
        <longitude>079 23.8942 W</longitude>
        <speed>00.0</speed>
        <course>000.0</course>
        <valid>True</valid>
    </body>
</event>

<?xml version="1.0" encoding="UTF-8"?>
<event>
    <head>
        <id>aed3e5b7-f98a-49d1-b950-4434331df8ae</id>
        <type>GPS</type>
        <time_stamp>2008-12-30T20:19:42Z</time_stamp>
        <entity>DS_GPS_001</entity>
    </head>
    <body>
        <latitude>43 38.8289 N</latitude>
        <longitude>079 23.8965 W</longitude>
        <speed>00.0</speed>
        <course>000.0</course>
        <valid>True</valid>
    </body>
</event>

 

The program reads the serial port every 10-12 seconds, extracts the position and speed data from a $GPRMC message and packages the data into XML form of an event object.

The Python code has two modules (files), the first one— gps_event_template.py —contains only a template for XML and JSON strings; the main module— gps_event.py —has all the working code.

The template has placeholders—like $time_stamp_here$ —which are simply later replaced by GPS data.

"""
gps_event_template.py
XML & JSON templates for GPS event
"
""
 
def xml_template():
    """<?xml version="1.0" encoding="UTF-8"?>
<event>
    <head>
        <id>$id_here$</id>
        <type>$type_here$</type>
        <time_stamp>$time_stamp_here$</time_stamp>
        <entity>$entity_here$</entity>
    </head>
    <body>
        <latitude>$latitude_here$</latitude>
        <longitude>$longitude_here$</longitude>
        <speed>$speed_here$</speed>
        <course>$course_here$</course>
        <valid>$valid_here$</valid>
    </body>
</event>
"
""
 
 
def json_template():
    """{
"
event":{
        "
head":{"id":"$id_here$",
                "
type":"$type_here$",
                "
time_stamp":"$time_stamp_here$",
                "
entity":"$entity_here$"
               },
        "
body":{"latitude":"$latitude_here$",
                "
longitude":"$longitude_here$",
                "
speed":"$speed_here$",
                "
course":"$course_here$",
                "
valid":"$valid_here$"
               }
        }
}
"
""   
 
 
def compress_template(s):
    """ Compress XML or JSON template """
    rli = {'{ ':'{', ' }':'}', ', "':',"', '> <':'><'}
    st = ' '.join(s.split())
    for (k, v) in rli.items():
        st = st.replace(k, v)
    return st
 
   
if __name__ == "__main__":
    print xml_template.__doc__   
    print json_template.__doc__
    print compress_template(xml_template.__doc__)
    print compress_template(json_template.__doc__)

 

Here is the main module; if running from Python Shell, start this one. Python is an easy read, so you should not have trouble following. The sendToCep(xst) function simply prints the XML to the Shell; I need to tinker with the CEP server before implementing this one. Keep in mind that this is a blog-as-you-go project.

 

"""
gps_event.py
 
Reads position and speed data from Magellan Meridian Gold GPS
--connected on COM 1-- every 10-12 seconds.
 
Packages GPS data into XML and sends to a CEP server.
"
""
 
from datetime import datetime
import time
import serial
import uuid
import gps_event_template
import gps_aws
 
ser = serial.Serial()
ser_mode = True
sample_delay = 10
msg_cnt = 1
 
obj = {'id':'','type':'GPS','time_stamp':'','entity':'DS_GPS_001',
       'latitude':'', 'longitude':'','speed':'', 'course':'', 'valid':''}
 
 
def gps_main():
    """ Read GPS every 10-12 seconds, send XML to CEP """
    (ser.port, ser.baudrate, ser.timeout) = (0, 4800, 4)
    ser.open()
    try:
        while 1:
            st = readGps()
            if st:
                sendToCep(st)
            else:
                # break
                pass
            time.sleep(sample_delay)
    finally:
        ser.close()
        return '*** ABORTING gps_event.py ***'
 
def readGps():
    """ Read GPS, create XML if valid reading """
    global ser_mode
    ser.flushInput()
    li = readCom(ser_mode)         
    if li[0] == '$GPRMC':
        obj['id'] = str(uuid.uuid4())
        parseGpsData(li)
        st = makeOutputString(fmt = 'X', pretty = 0)
    else:
        st = None
    return st
 
 
def makeOutputString(fmt = 'X', pretty = 0):
    """ Make XML or JSON string """
    if fmt == 'J':
        st = gps_event_template.json_template.__doc__
    else:
        st = gps_event_template.xml_template.__doc__
 
    if pretty == 0:
        st = gps_event_template.compress_template(st)
 
    for (k,v) in obj.items():
            st = st.replace('$%s_here$'%(k,), v)
 
    return st
 
 
def parseGpsData(li):
    """ Parse GPS list to object """
    obj['time_stamp'] = make_ts(li[1],li[9])
    obj['latitude'] = make_ll(li[3],li[4])
    obj['longitude'] = make_ll(li[5],li[6])
    obj['course'] = li[8]
    obj['speed'] = li[7]
    obj['valid'] = 'True' if li[2] == 'A' else 'False'
 
 
def readCom(sm = False):
    """ Read COM port, split GPS string to a list """
    (i, st) = (0, ['?'])
    while (i <25):
        i = i + 1
        if sm:
            ln = ser.readline()
        else:
            ln = "$GPRMC,172021.20,A,4338.8243,N,"
            ln = ln + "07923.9149,W,00.0,000.0,291208,11,W*48"
        if ln:
            s1 = ln.split(",")
            # print s1
            if s1[0] == '$GPRMC':
                st = s1
                break 
    return st
 
 
def make_ts(tim, dte):
    """ Make time-stamp """
    return datetime(int('20' + dte[4:]), int(dte[2:4]), int(dte [0:2]),
           int(tim[0:2]), int(tim[2:4]), int(tim[4:6])).isoformat() + 'Z'
 
 
def make_ll(c, s):
    """ Make lattitude and longitude """
    i = len(c) - 7
    return ' '.join([c[:i], c[i:], s])
 
 
def sendToCep(xst):
    """ Send XML string to EP/CEP/BUS """
    print xst # just print for now
 
 
if __name__ == "__main__":
    print gps_main()

 

So the next step is a CEP server—install, configure, communicate, do something with.

To be continued.

One Comment

  1. Column 2 : Bookmarks for December 31st:

    [...] Damir Systems Inc. » Blog Archive » GPS Event [2] - My intrepid other half, bored over the holidays, teaches himself Python, hacks his GPS and starts experimenting with pushing the data into CEP. Posted by Sandy Kemsley on Wednesday, December 31, 2008, at 12:00 pm. Filed under Links. Follow any responses to this post with its comments RSS feed. You can post a comment or trackback from your blog. [...]

Leave a comment