2

I have some very basic gpxlogger code that writes all the data to file quite well. (below)

gpxlogger -d  -f /home/pi/Desktop/EPQ/temp_gps/gpslog

However I would like this code to always write to the same file without overwriting it. So if possible when it started logging it would go to the bottom of the file and start logging the data there, below what has already been logged.

Thanks, Dan.

Javascript to read xml file

  <script src="http://maps.google.com/maps?file=api&amp;v=2&amp;key=ABQIAAAA7_kD1t_m22HBF9feCaDPZxQwcATY4FXmxYwkk9LNWGtAQdNKTBS1kBsTEqrRPg2kWxuNdmf2JVCIkQ" type="text/javascript"></script>
    <script src="http://gmaps-utility-library.googlecode.com/svn/trunk/markermanager/release/src/markermanager.js">   </script><script>
     var map;

     function initialize () {  
      if (GBrowserIsCompatible()) {
         map = new GMap2(document.getElementById("map_canvas"));
         map.setCenter(new GLatLng(53.423027, -1.523462), 10);  
     map.addControl(new GLargeMapControl());
         map.addControl(new GMapTypeControl());
         map.addMapType(G_PHYSICAL_MAP);
     map.setMapType(G_PHYSICAL_MAP);

     addMarkersFromXML();

      }

      }

      function addMarkersFromXML(){
       var batch = [];
       mgr = new MarkerManager(map); 

       var request = GXmlHttp.create();
       request.open('GET', 'gpslog.xml', true);
       request.onreadystatechange = function() {
       if (request.readyState == 4 && request.status == 200) {
        var xmlDoc = request.responseXML;
        var xmlrows = xmlDoc.documentElement.getElementsByTagName("trkpt");

        for (var i = 0; i < xmlrows.length; i++) {
            var xmlrow = xmlrows[i];

            var xmlcellLatitude = parseFloat(xmlrows[i].getAttribute("lat"));
          var xmlcellLongitude = parseFloat(xmlrows[i].getAttribute("lon"));
          var point = new GLatLng(xmlcellLatitude,xmlcellLongitude);

          //get the time of the pin plot
            var xmlcellplottime = xmlrow.getElementsByTagName("time")[0];
            var celltextplottime = xmlcellplottime.firstChild.data;

          //get the elevation of the pin plot
            var xmlcellplotelevation = xmlrow.getElementsByTagName("ele")[0];
            var celltextplotelevation = xmlcellplotelevation.firstChild.data;

          //get the number of satellites at the time of the pin plot
            var xmlcellplotsat = xmlrow.getElementsByTagName("sat")[0];
            var celltextplotsat = xmlcellplotsat.firstChild.data;


            var htmlString = "Time: " + celltextplottime + "<br>" + "Elevation: " + celltextplotelevation + "<br>" + "Satellites: " + celltextplotsat;
            //var htmlString = 'yes'

            var marker = createMarker(point,htmlString);
            batch.push(marker);

        }

        mgr.addMarkers(batch,10);
        mgr.refresh();

      }
        }
    request.send(null);

      }

     function createMarker(point,html) {
           var marker = new GMarker(point);
           GEvent.addListener(marker, "click", function() {
             marker.openInfoWindowHtml(html);
           });
           return marker;
     }

    </script>
  </head>
  <body onload="initialize()" onunload="GUnload()">
    <div id="map_canvas" style="width: 1350px; height: 800px"></div>
    <div id="message"></div>
  </body>
</html>

4 Answers4

1

Here's another option.

Look at gps3.py, put it, and the following script into a directory.

It reads data from the gpsd; creates the gpx log file if it doesn't exist; appends "trackpoint" data to it when data exists; while maintaining the same file and appending "trackpoint" data after a restart.

Place both in the same directory and then have you javascript read the file..or put the entire structure in the same script.

#!/usr/bin/env python
# coding=utf-8
""" gpx logger to create and append a gpx formatted log of gpsd data """ 
import os
import time
import gps3
from datetime import datetime

the_connection = gps3.GPSDSocket()
the_fix = gps3.Fix()
the_log = '/tmp/gpx3.gpx'  

creation = datetime.utcnow()
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
genesis = creation.strftime(fmt)

if not os.path.isfile(the_log):
    header = ('<?xml version = "1.0" encoding = "utf-8"?>\n'
              '<gpx version = "1.1" '
              'creator = "GPSD 3.9 - http://catb.org/gpsd" '
              'client = "gps3.py - http://github.com/wadda/gps3"'
              'xmlns:xsi = "http://www.w3.org/2001/XMLSchema-instance"'
              'xmlns = "http://www.topografix.com/GPX/1/1"'
              'xsi:schemaLocation = "http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd">\n '
              '<metadata>\n '
              '     <time>{}\n'
              '</metadata>\n').format(genesis)
    f = open(the_log, 'w')
    f.write(header)
    f.close()

try:
    for new_data in the_connection:
        if new_data:
            the_fix.refresh(new_data)
            if not isinstance(the_fix.TPV['lat'], str):  # lat determinate of when data is 'valid'                    
                latitude = the_fix.TPV['lat']
                longitude = the_fix.TPV['lon']
                altitude = the_fix.TPV['alt']
                time = the_fix.TPV['time']
                mode = the_fix.TPV['mode']
                tag = the_fix.TPV['tag']

                sats = the_fix.satellites_used()
                hdop = the_fix.SKY['hdop']
                vdop = the_fix.SKY['vdop']
                pdop = the_fix.SKY['pdop']

                trackpoint = ('<trkpt lat = {} lon = {}>\n'
                              '    <ele>{}</ele>\n'
                              '    <time>{}</time>\n'
                              '    <src>GPSD tag ="{}"</src>\n'
                              '    <fix>{}</fix >\n'
                              '    <sat>{}</sat>\n'
                              '    <hdop>{}</hdop>\n'
                              '    <vdop>{}</vdop>\n'
                              '    <pdop>{}</pdop>\n'
                              '</trkpt>\n').format(latitude, longitude, altitude, time, tag, mode, sats[1], hdop, vdop, pdop)
                addendum = open(the_log, 'a')
                addendum.write(trackpoint)
                addendum.close()


except Exception as error:
    print('Danger-Danger',error)
Nodak
  • 929
  • 1
  • 8
  • 14
  • Thanks, that solves most of the issue. However for some reason the google map will not load the pins unless there is at the end of the xml document. Is there a way to add this in with the header, ensuring new data is inserted between the opening and closing tags? Thanks again. – Dan Woolfall Mar 15 '15 at 14:57
  • @DanWoolfall, yes, bit of a bugger. See the latest solution using `minodom`. – Nodak Apr 01 '15 at 07:14
0

You run into the problem of a daemonised gpxlogger requiring a -f flag for a file name and that will overwrite the file. This you know.

I see there are two options. Not run gpxlogger as a daemon

gpxlogger >> /home/pi/Desktop/EPQ/temp_gps/gpslog

or run it as a daemon and cat the file to an append-able file

gpxlogger -d  -f /home/pi/Desktop/EPQ/temp_gps/gpslog & cat /home/pi/Desktop/EPQ/temp_gps/gpslog >> /home/pi/Desktop/EPQ/temp_gps/gpslog_concatenated
Nodak
  • 929
  • 1
  • 8
  • 14
  • But the problem with a simple execution of the second option is the `xml` and `gpx` headers get concatenated every time as well. – Nodak Mar 10 '15 at 03:16
  • This method has merged the code perfectly. However the code is being read by a javascript file which finds the longitude and latitude and puts a pin onto a google map. The fact the merging of the xml files repeats the gpx and xml tags is causing it to somehow not see the new data. Apologies I am a novice! I will add the code to my original question, if you can help that would be great. – Dan Woolfall Mar 10 '15 at 19:00
0

Another way to look at it would be to create sequential logs, and then concatenate them with gpsbable, but in order to do that you need to have a script, and an index.

Make the index echo 0 > ~/.gpxfilecount

Open a favourite editor and create a file including something like:

#! /usr/bin/bash

COUNT=`cat ~/.gpxfilecount`
echo $(($COUNT + 1 )) > ~/.gpxfilecount

filename="gpxlogfile${COUNT}.gpx"
exec  gpxlogger -d  -f $filename

Mark the script executable chmod +x ~/bin/gpxer.sh (or favourite name).

Every time you fire up the gpxlogger an incremented filename is created. Those file can then be concatenated without tears by gpsbable gpsbabel -i geo -f gpxlogfile1.gpx -f gpxlogfile2.gpx -f gpxlogfile3.gpx -o gpx -F biglogcat.gpx ...or however gpsbable works.

Nodak
  • 929
  • 1
  • 8
  • 14
0

I was curious what building a gpx file from scratch would look like using only minidom. Unfortunately life intervened, sorry for the delay...

When this script (below) gpex3.py, still a little crude and inefficient (read/write every second), is placed in the same directory as gps3.py it creates an appendable gpx file at /tmp/gpx3.gpx

#! /usr/bin/python3
# coding=utf-8
"""banana"""
import xml.dom.minidom
import gps3
import time
from datetime import datetime, timezone, timedelta
import os
import sys

gps_connection = gps3.GPSDSocket()
gps_fix = gps3.Fix()

the_log = '/tmp/gpx3.gpx'


def start_time():
    """time in the beginning"""
    timestart = str(datetime.utcnow().replace(tzinfo=(timezone(timedelta(0)))))
    return timestart


def close(doc):
    """write file to disk and close"""
    log_write = open(the_log, "w")
    doc.writexml(log_write)
    log_write.close()


if os.path.isfile(the_log):
    doc = xml.dom.minidom.parse(the_log)  # opens the pre-existing
    gpx_element = doc.firstChild

else:
    doc = xml.dom.minidom.Document()
    gpx_element = doc.createElement("gpx")
    doc.appendChild(gpx_element)

trk_element = doc.createElement("trkseg")
trk_element.setAttribute("began", start_time())
gpx_element.appendChild(trk_element)
utc = alt = hdop = vdop = pdop = mode = sats = tag = 'n/a'
try:
    tpv_list = {'time': utc, 'ele': alt, 'tag': tag}
    sky_list = {'hdop': hdop, 'vdop': vdop, 'pdop': pdop}
    # misc_list = {'sat': sats, 'fix':mode}  # just an account
    element = {}
    x = 1  # for the 'is it working?'
    for new_data in gps_connection:
        if new_data:
            gps_fix.refresh(new_data)
        if not isinstance(gps_fix.TPV['lat'], str):
            trkpt_element = doc.createElement("trkpt")
            trk_element.appendChild(trkpt_element)
            trkpt_element.setAttribute('lat', str(gps_fix.TPV['lat']))
            trkpt_element.setAttribute('lon', str(gps_fix.TPV['lon']))

            # tpv_list[key]
            for key in tpv_list:
                if key == 'ele':
                    element[key] = '{}'.format(gps_fix.TPV['alt'])  # because consistency with labels is a horrible.
                else:
                    element[key] = '{}'.format(gps_fix.TPV[key])
            # sky_list[key]
            for key in sky_list:
                element[key] = '{}'.format(gps_fix.SKY[key])
            # Misc.
            element['sat'] = '{}'.format(gps_fix.satellites_used()[1])
            element['fix'] = '{}'.format(("ZERO", "NO_FIX", "2D", "3D")[gps_fix.TPV['mode']])

            for key in element:
                trkpt_data = doc.createElement(key)
                trkpt_element.appendChild(trkpt_data)

                new_value = doc.createTextNode(element[key])
                trkpt_data.appendChild(new_value)

            # print(doc.toprettyxml())
            close(doc)  # write to file with every trackpoint
            print('Cycle', x)  # Only an "is it working?"
            x += 1
            time.sleep(1)

except KeyboardInterrupt:
    gps_connection.close()
    print("\nTerminated by user\nGood Bye.\n")

if __name__ == '__main__':
    pass
Nodak
  • 929
  • 1
  • 8
  • 14