2015-07-31 23:10:59 +00:00
|
|
|
"""
|
|
|
|
This script parses the raw data from the pico tracker.
|
|
|
|
At the very bottom the data is printed. Feel free to change
|
|
|
|
the print statement to suit the data you're interested in.
|
|
|
|
The parsed data is a list of dicts, with keys 'time', 'coords',
|
|
|
|
'battery', 'solar', 'temperature' and 'satellites'.
|
|
|
|
|
|
|
|
Data is expected in the form of a series of lines containing
|
|
|
|
'/A={6 digits} {6 digits}z.{18 chars}{11 chars}\n'. Anything
|
|
|
|
else will be ignored.
|
|
|
|
"""
|
|
|
|
|
|
|
|
import re
|
|
|
|
import sys
|
2015-08-01 17:23:05 +00:00
|
|
|
from ukhas_format import *
|
2015-08-01 19:58:37 +00:00
|
|
|
from habitat_upload import *
|
2015-07-31 23:10:59 +00:00
|
|
|
from datetime import datetime
|
|
|
|
from math import log, exp
|
|
|
|
|
|
|
|
"""
|
|
|
|
Decodes a 'base 91' encoded string
|
|
|
|
"""
|
|
|
|
def base91_decode(enc_str):
|
|
|
|
enc_ints = [ord(x) - 33 for x in enc_str]
|
|
|
|
powers = range(len(enc_ints))[::-1]
|
|
|
|
return sum(x * pow(91, i) for x, i in zip(enc_ints, powers))
|
|
|
|
|
|
|
|
"""
|
|
|
|
Takes a parsed telemetry line and returns a datetime
|
|
|
|
Default year and month are 2015 and July
|
|
|
|
"""
|
|
|
|
def extract_time(line):
|
|
|
|
# Capture a 6 digit string
|
|
|
|
p = re.compile(r'(\d{6})z\S{18}')
|
2015-08-01 16:41:22 +00:00
|
|
|
match = p.match(line)
|
2015-07-31 23:10:59 +00:00
|
|
|
|
|
|
|
if match == None:
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
date_str = '201507' + match.group(1)
|
|
|
|
|
|
|
|
# Return a datetime object
|
|
|
|
return datetime.strptime(date_str, '%Y%m%d%H%M')
|
|
|
|
|
|
|
|
"""
|
|
|
|
Takes a parsed telemetry line and returns latitude, longitude and
|
|
|
|
altitude. It decodes from base 91 along the way
|
|
|
|
"""
|
|
|
|
def extract_lat_long_alt(line):
|
|
|
|
# Capture a 4 char encoded latitude
|
|
|
|
p = re.compile(r'\d{6}z(\S{4})(\S{4})(\S{2})\S{8}')
|
|
|
|
match = p.match(line)
|
|
|
|
|
|
|
|
if match == None:
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
enc_lat, enc_long, enc_alt = match.groups()
|
|
|
|
|
|
|
|
# Lat/long in fractional degrees, alt in metres
|
|
|
|
latitude = 90.0 - (base91_decode(enc_lat) / 380926.0)
|
|
|
|
longitude = -180.0 + (base91_decode(enc_long) / 190463.0)
|
|
|
|
altitude = exp(log(1.002) * base91_decode(enc_alt)) / 3.2808
|
|
|
|
|
|
|
|
return (latitude, longitude, altitude)
|
|
|
|
|
|
|
|
"""
|
|
|
|
Takes a parsed telemetry line and returns readings on battery, solar
|
|
|
|
temperature and satellite count. It decodes from base91 along the
|
|
|
|
way
|
|
|
|
"""
|
|
|
|
def extract_telemetry(line):
|
|
|
|
# Capture an 8 char encoded telemetry segment
|
|
|
|
p = re.compile(r'\d{6}z\S{10}(\S{8})')
|
|
|
|
match = p.match(line)
|
|
|
|
|
|
|
|
if match == None:
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
tel = match.group(1)
|
|
|
|
|
|
|
|
# Split into 2 char chunks
|
|
|
|
parts = [tel[i:i+2] for i in range(0, 8, 2)]
|
|
|
|
batt_enc, sol_enc, temp_enc, sat_enc = tuple(parts)
|
|
|
|
|
|
|
|
# Reverse Richard's conversions
|
|
|
|
battery = base91_decode(batt_enc) / 1000.0
|
|
|
|
solar = base91_decode(sol_enc) / 1000.0
|
|
|
|
temperature = (base91_decode(temp_enc) / 10) - 273.2
|
|
|
|
satellite_count = base91_decode(sat_enc)
|
|
|
|
|
|
|
|
return (battery, solar, temperature, satellite_count)
|
|
|
|
|
|
|
|
"""
|
|
|
|
Exracts the 'raw data' segment from a line of data; this is the 25
|
|
|
|
character section after /A={6 digits}
|
|
|
|
"""
|
|
|
|
def extract_raw_data(line):
|
|
|
|
# Capture the raw data segment
|
|
|
|
p = re.compile(r'/A=\d{6} (\S{25})\|\S{11}$')
|
|
|
|
match = p.search(line)
|
|
|
|
|
|
|
|
if match == None:
|
|
|
|
return None
|
|
|
|
else:
|
|
|
|
return match.group(1)
|
|
|
|
|
|
|
|
#-------------------------------------------------------------------------------
|
|
|
|
|
2015-08-01 16:41:22 +00:00
|
|
|
if len(sys.argv) == 2:
|
|
|
|
file_name = sys.argv[1]
|
|
|
|
else:
|
|
|
|
file_name = raw_input("File to read (rawdata.txt): ") or "rawdata.txt"
|
2015-07-31 23:10:59 +00:00
|
|
|
|
|
|
|
with open(file_name, 'r') as data_file:
|
|
|
|
data = []
|
|
|
|
|
|
|
|
for line in data_file:
|
|
|
|
# Extract raw data string
|
|
|
|
raw = extract_raw_data(line)
|
|
|
|
|
|
|
|
if raw == None:
|
|
|
|
continue
|
|
|
|
else:
|
|
|
|
tele = extract_telemetry(raw)
|
|
|
|
|
|
|
|
data.append({
|
|
|
|
'time': extract_time(raw),
|
|
|
|
'coords': extract_lat_long_alt(raw),
|
|
|
|
'battery': tele[0],
|
|
|
|
'solar': tele[1],
|
|
|
|
'temperature': tele[2],
|
|
|
|
'satellites': tele[3]
|
|
|
|
})
|
|
|
|
|
|
|
|
# Sort data lines by time
|
|
|
|
data = sorted(data, key=lambda x: x['time'])
|
|
|
|
|
|
|
|
# Print data
|
|
|
|
for datum in data:
|
|
|
|
print "%s: %s, %s" % ((str(datum['time']),) + datum['coords'][:2])
|
2015-08-01 19:58:37 +00:00
|
|
|
|
|
|
|
# Upload data to habitat
|
2015-08-02 12:02:46 +00:00
|
|
|
for datum in data[3:]:
|
|
|
|
ukhas_str = ukhas_format(datum)
|
|
|
|
try:
|
|
|
|
print ukhas_str
|
|
|
|
print habitat_upload(datum['time'], ukhas_str)
|
|
|
|
except:
|
|
|
|
None
|