mirror of
https://codeberg.org/ET-Kiel/tk102gpx.git
synced 2026-05-01 13:44:23 +02:00
Compare commits
No commits in common. "33e95043fc3423b4bf56913a91936f816d063dd1" and "5f5834bc32edd021e6e01fb3e7f4ac03093bce31" have entirely different histories.
33e95043fc
...
5f5834bc32
3 changed files with 38 additions and 174 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -1,5 +1,4 @@
|
|||
cron.log
|
||||
tk102-*.gpx
|
||||
tk102-*.log
|
||||
tk102-*.txt
|
||||
|
||||
|
|
|
|||
10
Makefile
10
Makefile
|
|
@ -6,11 +6,5 @@ all: $(patsubst %, %.gpx, $(FILES))
|
|||
%.gpx: %.log
|
||||
./tk102gpx.py $< > $@
|
||||
|
||||
nc%: tk102-%.log
|
||||
(while true; do nc -lp 1020$* -w 999; done) | tee -a $< | cat -v
|
||||
|
||||
tail%: tk102-%.log
|
||||
./tk102gpx.py -t1w -CFf $< | tee tk102-$*.txt
|
||||
|
||||
%.txt: t%.log
|
||||
./tk102gpx.py -CF $< > $@
|
||||
capture:
|
||||
(while true; do nc -lp 10201; done) | tee -a tk102-1.log | cat -v
|
||||
|
|
|
|||
197
tk102gpx.py
197
tk102gpx.py
|
|
@ -1,58 +1,9 @@
|
|||
#! /usr/bin/python3
|
||||
|
||||
import sys, re, time
|
||||
import sys, re
|
||||
import gpxpy
|
||||
import gpxpy.gpx
|
||||
from datetime import datetime
|
||||
from getopt import getopt
|
||||
|
||||
options, files = getopt(sys.argv[1:],
|
||||
"qvft:s:RDCXF",
|
||||
["quiet", "verbose", "follow", "time=", "serial=",
|
||||
"raw", "data", "cooked", "gpx", "fieldnames"])
|
||||
|
||||
follow = False
|
||||
serial = b"0"
|
||||
verbose = 1
|
||||
raw = 0
|
||||
fieldnames = False
|
||||
|
||||
print(options, file=sys.stderr)
|
||||
|
||||
for o,v in options:
|
||||
o = " "+o
|
||||
if o in " -q --quiet":
|
||||
verbose = 0
|
||||
if o in " -v --verbose":
|
||||
verbose += 1
|
||||
if o in " -f --follow":
|
||||
follow = True
|
||||
if o in " -D --data":
|
||||
raw = 1
|
||||
if o in " -C --cooked":
|
||||
raw = 2
|
||||
if o in " -R --raw":
|
||||
raw = 3
|
||||
if o in " -X --gpx":
|
||||
raw = 0
|
||||
if o in " -F --fieldnames":
|
||||
fieldnames = True
|
||||
if o in " -s --serial":
|
||||
serial = v.encode()
|
||||
if o in " -t --time":
|
||||
if v[-1]=="m":
|
||||
t = float(v[:-1])*60
|
||||
elif v[-1]=="h":
|
||||
t = float(v[:-1])*3600
|
||||
elif v[-1]=="d":
|
||||
t = float(v[:-1])*86400
|
||||
elif v[-1]=="w":
|
||||
t = float(v[:-1])*86400*7
|
||||
else:
|
||||
t = float(v)
|
||||
serial = time.strftime("%y%m%d%H%M", time.gmtime(time.time()-t)).encode()
|
||||
if verbose:
|
||||
print(f"--serial={serial}", file=sys.stderr)
|
||||
|
||||
tk_re = re.compile(b"".join((
|
||||
b"(?P<SERIAL>[0-9]+)?,",
|
||||
|
|
@ -70,7 +21,7 @@ tk_re = re.compile(b"".join((
|
|||
b"(?P<VAR>[^,]+)?,",
|
||||
b"(?P<WHAT>[^,]*,)?",
|
||||
b"A\*(?P<GPCKS>[0-9A-F][0-9A-F]),",
|
||||
b"(?P<BAT>[FL])?,",
|
||||
b"(?P<F>[A-Z])?,",
|
||||
b"imei:(?P<IMEI>[0-9]+),",
|
||||
b"(?P<LEN>[0-9]{3})",
|
||||
b"(?P<BCKS>..)"
|
||||
|
|
@ -85,132 +36,50 @@ def gprmc2deg(d,dd):
|
|||
|
||||
class TKGPX(gpxpy.gpx.GPX):
|
||||
|
||||
def tk_newtrack(self, files):
|
||||
if files:
|
||||
fn = files[0]
|
||||
files[:1] = []
|
||||
inp = open(fn, "rb")
|
||||
else:
|
||||
fn = None
|
||||
inp = sys.stdin.buffer
|
||||
track = gpxpy.gpx.GPXTrack(name=fn)
|
||||
def __init__(self, inp):
|
||||
|
||||
super().__init__()
|
||||
track = gpxpy.gpx.GPXTrack()
|
||||
self.tracks.append(track)
|
||||
segment = gpxpy.gpx.GPXTrackSegment()
|
||||
track.segments.append(segment)
|
||||
return inp, segment
|
||||
|
||||
def __init__(self, files):
|
||||
|
||||
super().__init__()
|
||||
inp, segment = self.tk_newtrack(files)
|
||||
|
||||
slept = False
|
||||
data = inp.read(0x100000)
|
||||
while data or follow or files:
|
||||
while data:
|
||||
if len(data)<256:
|
||||
data += inp.read(0x100000)
|
||||
m = tk_re.search(data)
|
||||
while not m:
|
||||
ndata = inp.read(0x100000)
|
||||
while not ndata and files:
|
||||
inp.close()
|
||||
imp, segment = self.tk_newtrack(files)
|
||||
ndata = inp.read(0x100000)
|
||||
if not ndata:
|
||||
break
|
||||
data += ndata
|
||||
if m is None:
|
||||
if not follow:
|
||||
break
|
||||
sys.stdout.flush()
|
||||
try:
|
||||
if verbose >= 2:
|
||||
slept = True
|
||||
sys.stderr.write(".")
|
||||
sys.stderr.flush()
|
||||
time.sleep(60)
|
||||
except KeyboardInterrupt:
|
||||
break
|
||||
continue
|
||||
if slept:
|
||||
sys.stderr.write("\n")
|
||||
slept = False
|
||||
|
||||
if m.start() and verbose >= 2:
|
||||
if m is None or m.end()<1:
|
||||
break
|
||||
if m.start():
|
||||
print(f"discarded: {repr(data[:m.start()])}", file=sys.stderr)
|
||||
data = data[m.end():]
|
||||
rd = m.groupdict()
|
||||
|
||||
if not rd["LAT"] or not rd["LON"] or rd["SERIAL"] < serial:
|
||||
if verbose >= 3:
|
||||
print(f"DROPPED: {repr(rd)}", file=sys.stderr)
|
||||
continue
|
||||
|
||||
if verbose >= 3:
|
||||
print(repr(rd), file=sys.stderr)
|
||||
|
||||
if verbose>0 and rd["BAT"] != b"F":
|
||||
print(f"Battery is {repr(rd['BAT'])} at {rd['SERIAL']}", file=sys.stderr)
|
||||
|
||||
d = m.groupdict()
|
||||
print(int(d["LEN"]), m.end()-m.start()-int(d["LEN"]), repr(m.group()), file=sys.stderr)
|
||||
print(repr(d), file=sys.stderr)
|
||||
if not d["LAT"] or not d["LON"]:
|
||||
break
|
||||
pd = {
|
||||
"latitude": gprmc2deg(rd["LAT"], rd["NS"]),
|
||||
"longitude": gprmc2deg(rd["LON"], rd["EW"]),
|
||||
"latitude": gprmc2deg(d["LAT"], d["NS"]),
|
||||
"longitude": gprmc2deg(d["LON"], d["EW"]),
|
||||
}
|
||||
if rd["TIME"] and rd["DATE"]:
|
||||
if d["TIME"] and d["DATE"]:
|
||||
pd["time"] = datetime(
|
||||
int(rd["DATE"][4:6])+2000,
|
||||
int(rd["DATE"][2:4]),
|
||||
int(rd["DATE"][0:2]),
|
||||
int(rd["TIME"][0:2]),
|
||||
int(rd["TIME"][2:4]),
|
||||
int(rd["TIME"][4:6])
|
||||
int(d["DATE"][0:2])+2000,
|
||||
int(d["DATE"][2:4]),
|
||||
int(d["DATE"][4:6]),
|
||||
int(d["TIME"][0:2]),
|
||||
int(d["TIME"][2:4]),
|
||||
int(d["TIME"][4:6])
|
||||
)
|
||||
if rd["SOG"]:
|
||||
pd["speed"] = float(rd["SOG"]) # knots
|
||||
if d["SOG"]:
|
||||
pd["speed"] = float(d["SOG"]) # knots
|
||||
|
||||
if verbose == 2:
|
||||
print(repr(pd), file=sys.stderr)
|
||||
|
||||
if raw==1:
|
||||
if fieldnames:
|
||||
print(", ".join([f"{k}={pd[k]}" for k in pd]))
|
||||
else:
|
||||
print(" ".join([f"{pd[k]}" for k in pd]))
|
||||
|
||||
if raw==2:
|
||||
cd = {}
|
||||
cd.update(strorbytes(rd, 'BAT'))
|
||||
cd.update(strorbytes(rd, 'SERIAL'))
|
||||
cd.update(strorbytes(rd, 'PHONE'))
|
||||
cd['time'] = pd['time'].isoformat()+'Z'
|
||||
cd['lat'] = f"{rd['LAT'][:2].decode()}°{rd['LAT'][2:].decode()}'{rd['NS'].decode()}"
|
||||
cd['lon'] = f"{rd['LON'][:3].decode()}°{rd['LAT'][3:].decode()}'{rd['EW'].decode()}"
|
||||
cd.update(strorbytes(rd, 'SOG'))
|
||||
cd.update(strorbytes(rd, 'COG'))
|
||||
if fieldnames:
|
||||
print(", ".join([f"{k}={cd[k]}" for k in cd]))
|
||||
else:
|
||||
print(" ".join([cd[k] for k in cd]))
|
||||
|
||||
if raw==3:
|
||||
if fieldnames:
|
||||
print(", ".join([f"{k}={repr(rd[k])[2:-1]}" for k in rd if rd[k]]))
|
||||
else:
|
||||
print(" ".join([f"{repr(rd[k])[2:-1]}" for k in rd if rd[k]]))
|
||||
print(repr(pd), file=sys.stderr)
|
||||
|
||||
point = gpxpy.gpx.GPXTrackPoint(**pd)
|
||||
segment.points.append(point)
|
||||
|
||||
if follow and not raw and verbose < 2:
|
||||
print(repr(point), file=sys.stderr)
|
||||
|
||||
def strorbytes(rd, f):
|
||||
if not f in rd:
|
||||
return {}
|
||||
try:
|
||||
return {f: rd[f].decode()}
|
||||
except:
|
||||
pass
|
||||
return {f: repr(rd[f])[2:-1]}
|
||||
|
||||
# gpxpy.gpx.GPXTrackPoint(
|
||||
# latitude: Optional[float] = None,
|
||||
# longitude: Optional[float] = None,
|
||||
|
|
@ -225,6 +94,8 @@ def strorbytes(rd, f):
|
|||
# name: Optional[str] = None,
|
||||
# ) -> None
|
||||
|
||||
X = TKGPX(files)
|
||||
if not raw:
|
||||
print(X.to_xml())
|
||||
inp = sys.stdin.buffer
|
||||
if len(sys.argv) > 1:
|
||||
inp = open(sys.argv[1], "rb")
|
||||
|
||||
print(TKGPX(inp).to_xml())
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue