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.