|
The attached program uses USPP to read from a serial
port (USB for example). Daniel Kersten wrote: Hi all, --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Python Ireland" group. To post to this group, send email to [email protected] To unsubscribe from this group, send email to [email protected] For more options, visit this group at http://groups.google.ie/group/pythonireland?hl=en -~----------~----~----~----~------~----~------~--~--- |
################################################################################# ## ## readlog.py - Read gps tracklogs from Wintec 201 and write them into a .tk1 file. ## ## Version 1.0 - Copyright (c) 2007 Steffen Siebert <[email protected]> ## ################################################################################# ## ## This program is free software; you can redistribute it and/or modify ## it under the terms of the GNU General Public License as published by ## the Free Software Foundation; either version 2 of the License, or ## (at your option) any later version. ## ## This program is distributed in the hope that it will be useful, ## but WITHOUT ANY WARRANTY; without even the implied warranty of ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ## GNU General Public License for more details. ## ## You should have received a copy of the GNU General Public License ## along with this program; if not, write to the Free Software ## Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA ## ################################################################################# ## Requirements ## ################################################################################# ## ## Python 2.2 or later: ## <http://www.python.org> ## ## Required Python libraries: ## uspp-1.0 from http://ibarona.googlepages.com/uspp ## For usage with windows: pywin32 from http://sourceforge.net/projects/pywin32/ (required by uspp) ## ################################################################################# ## Known Problems: ## ################################################################################# ## ## - Several fields in the tk1 header and footer are filled with dummy values, ## thus the created tk1 file is not identical with a tk1 file created by ## Time Machine X. But the files created by readlog.py can be read and ## converted in other file formats with Time Machine X. ## - The code for deleting the tracks from the Wintec 201 is included, but ## disabled. ## ################################################################################# ## Support ## ################################################################################# ## ## The latest version of webcheck is always available from my homepage: ## <http://www.SteffenSiebert.de/soft/python/wintec_tools.html> ## ## If you have bug reports, patches or some questions, just send a mail to ## <[email protected]> ## #################################################################################
from winteclib import *
import datetime
import getopt
import struct
import sys
import time
import uspp
#debug = None
def isChecksumCorrect(buffer, checksum):
cs = 0
for char in buffer:
cs = cs ^ ord(char)
return checksum == "%02X" % cs
def getLogString(tty):
line = tty.readline()
if debug:
print line
return line.split(",")[-1].strip()
def getLogValue(tty):
return int(getLogString(tty))
def writeBytes(f, byte, count):
for i in range(count):
f.write(byte)
def writeFooterEntry(f, tracknumber, trackvalues):
# 24 Bytes per track.
# 0x00-0x03: tracknumber
# 0x04-0x07: Offset first track
# 0x08-0x0b: Trackpoint count
# 0x0c-0x0f: Track duration in seconds
# 0x10-0x17: Track length as double
f.write(struct.pack('l', tracknumber))
f.write(struct.pack('l', trackvalues[0]))
f.write(struct.pack('l', trackvalues[1]))
f.write(struct.pack('l', trackvalues[2]))
f.write(struct.pack('d', trackvalues[3]))
def writeHeader(f, devicename, deviceinfo, trackpointcount, footerpos,
trackcount):
f.write('WintecLogFormat' + chr(0x00))
f.write(chr(0x00)+chr(0x00)+chr(0x80)+chr(0x3f))
f.write(chr(0x00)+chr(0x00)+chr(0x80)+chr(0x3f))
f.write(chr(0x00)+chr(0x00)+chr(0x80)+chr(0x3f))
f.write(chr(0x41)+chr(0xbf)+chr(0x10)+chr(0x00))
f.write(struct.pack('l', trackpointcount))
f.write(chr(0x00)+chr(0x00)+chr(0x00)+chr(0x00))
f.write(devicename)
writeBytes(f, chr(0), 20-len(devicename))
f.write(deviceinfo)
writeBytes(f, chr(0), 20-len(deviceinfo))
f.write('YYMM1234567890'+chr(0x00)+chr(0x00))
writeBytes(f, chr(0), 24)
f.write(time.strftime("%Y_%m_%d_%H:%M:%S", time.localtime()) +chr(0))
f.write(struct.pack('l', footerpos))
f.write(struct.pack('l', trackcount))
writeBytes(f, chr(0), 876)
def parseTracklog(data):
outputFile = None
dataPos = 0
trackCount = 0
trackPointCount = 0
trackStartPos = 0x400
trackStartDateTime = None
trackDistance = float(0)
previousDateTime = None
previousLatitude = None
previousLongitude = None
tracks = {}
while dataPos < len(data):
byte = data[dataPos]
dateTime = convertToDateTime(readLongWord(data, dataPos+2))
# The first trackpoint might not be marked with the trackstart flag.
if ord(byte) & 0x01 == 1 or dataPos == 0:
if previousDateTime != None:
trackDuration = previousDateTime - trackStartDateTime
tracks[trackCount-1] = (trackStartPos, trackPointCount,
trackDuration.days * 24 * 60 * 60 + trackDuration.seconds, trackDistance)
# Start of new Track
trackPointCount = 0
trackStartPos = dataPos + 0x400
trackStartDateTime = dateTime
trackDistance = float(0)
previousDateTime = None
previousLatitude = None
previousLongitude = None
trackCount = trackCount + 1
latitude = float(readSignedLongWord(data, dataPos+6))
longitude = float(readSignedLongWord(data, dataPos+10))
altitude = float(readSignedWord(data, dataPos+14))
speed = 0
if previousLatitude:
trackDistance = trackDistance +
calculateVincentyDistance(previousLatitude / 10000000.0, previousLongitude /
10000000.0, latitude / 10000000.0, longitude / 10000000.0)
previousDateTime = dateTime
previousLatitude = latitude
previousLongitude = longitude
trackPointCount = trackPointCount + 1
dataPos = dataPos + 16
if previousDateTime != None:
trackDuration = previousDateTime - trackStartDateTime
tracks[trackCount-1] = (trackStartPos, trackPointCount,
trackDuration.days * 24 * 60 * 60 + trackDuration.seconds, trackDistance)
return tracks
def usage():
print "Usage: python readlog.py [-v] [-p password] [-d] [serial port]
[filename]"
print "-v: Print debug info"
print "-p: Wintec password (4 digits)"
print "-d: Delete log from Wintec after transfer"
def main():
global debug
BAUDRATE = 57600
READ_TIMEOUT = 3000 # 3 seconds
deleteLog = None
password = None
debug = None
try:
opts, args = getopt.getopt(sys.argv[1:], "?hvp:d")
except getopt.GetoptError:
# print help information and exit:
usage()
sys.exit(2)
if len(args) != 2:
usage()
sys.exit(1)
for o, a in opts:
if o == "-v":
debug = 1
if o in ("-h", "-?"):
usage()
sys.exit()
if o == "-d":
deleteLog = 1
if o == "-p":
password = a
tty = None
f = None
try:
tty = uspp.SerialPort(args[0], READ_TIMEOUT, BAUDRATE)
# I'm not sure why, but the next two lines seem to be necessary to
enter command code.
time.sleep(1)
tty.readline()
print "Enter command mode"
if password:
tty.write("@AL,1%s\n" % password)
else:
tty.write("@AL,\n")
ready = 0
retrycount = 50
while 1:
try:
line = tty.readline()
except uspp.SerialPortException, ex:
if str(ex) == "Timeout" and line == '@AL\n' and password ==
None:
print "Device seem to be password protected!"
print "Please provide the correct password using option -p"
sys.exit(1)
else:
raise ex
sys.exit(1)
if debug:
print line
if line == "@AL,LoginOK\n":
ready = 1
break
if password and line == "@AL,PassworError\n":
print "Wrong Password"
sys.exit(1)
retrycount = retrycount - 1
if retrycount <= 0:
break
if ready == 1:
tty.write("@AL,07,01\n")
devicename = getLogString(tty)
tty.write("@AL,07,02\n")
deviceinfo = getLogString(tty)
tty.write("@AL,01,01\n")
autosleep = getLogString(tty)
tty.write("@AL,01,02\n")
overspeed = getLogString(tty)
tty.write("@AL,05,01\n")
logstart = getLogValue(tty)
tty.write("@AL,05,02\n")
logend = getLogValue(tty)
tty.write("@AL,05,09\n")
logareastart = getLogValue(tty)
tty.write("@AL,05,10\n")
logareaend = getLogValue(tty)
print "Logarea: %s-%s" % (logareastart, logareaend)
print "Log: %s-%s" % (logstart, logend)
logcapacy = (logareaend - logareastart) / 16
if logcapacy < 4096:
readcount = logcapacy
else:
readcount = 4096
readstart = int(logstart)
lastsection = 0
tracklog = ''
while 1:
print "Read buffer at %s (%s Bytes)" % (readstart, readcount)
tty.write("@AL,05,03,%i\n" % readstart)
try:
buffer = tty.read(readcount)
except uspp.SerialPortException:
print "Buffer read timeout, retrying"
continue
line = tty.readline()
if debug:
print line
checksum = line.split(",")[2]
if debug:
print "Expected block checksum: " + checksum
if not isChecksumCorrect(buffer, checksum):
print "Buffer read error, retrying"
continue
else:
tracklog = tracklog + buffer
line = tty.readline()
if debug:
print line
if lastsection == 1:
break
readstart = readstart + len(buffer)
if readstart >= logareaend:
readstart = logareastart
if (readstart < logend) and (readstart + 4096 >= logend):
readcount = logend - readstart
lastsection = 1
# Write data as .tk1 file
f = open(args[1], "wb")
tracks = parseTracklog(tracklog)
writeHeader(f, devicename, deviceinfo, len(tracklog)/16,
len(tracklog) + 0x0400, len(tracks))
f.write(tracklog)
for key in tracks.keys():
writeFooterEntry(f, key, tracks[key])
f.close()
if deleteLog:
tty.write("@AL,05,06\n")
else:
print "Can't switch into command mode!"
finally:
print "Exit command mode"
if tty != None:
tty.write("@AL,02,01\n")
del tty
if __name__ == "__main__":
main()
