Compare commits

..

No commits in common. "33e95043fc3423b4bf56913a91936f816d063dd1" and "5f5834bc32edd021e6e01fb3e7f4ac03093bce31" have entirely different histories.

3 changed files with 38 additions and 174 deletions

1
.gitignore vendored
View file

@ -1,5 +1,4 @@
cron.log
tk102-*.gpx
tk102-*.log
tk102-*.txt

View file

@ -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

View file

@ -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 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]]))
if d["SOG"]:
pd["speed"] = float(d["SOG"]) # knots
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())