diff --git a/kml2g1000.py b/kml2g1000.py index 582c51f..409a139 100644 --- a/kml2g1000.py +++ b/kml2g1000.py @@ -25,6 +25,15 @@ def calcSpeed(fm, to, start, end): dt = (end - start).total_seconds() / 3600.0 # hours return round(dx / dt) if dt else 0 +# Parse date time but do not crash if some entries have fractional seconds and others do not. E.g. ADSBExchange exports with fractional seconds +def parse_datetime(date_str): + # Try the version with fractional seconds first + try: + return datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S.%f") + except ValueError: + # Fall back to the version without fractional seconds + return datetime.strptime(date_str, "%Y-%m-%d %H:%M:%S") + # Converts a kml tracklog exported from flightaware.com to G1000 csv format. def export(kml, folder=None): if not folder: @@ -38,10 +47,11 @@ def export(kml, folder=None): print("Skipping " + fileName + " (already exists)") return + # G1000 header, format, and trailing commas for data we do not set. hdr = ' Lcl Date, Lcl Time, UTCOfst, AtvWpt, Latitude, Longitude, AltB, BaroA, AltMSL, OAT, IAS, GndSpd, VSpd, Pitch, Roll, LatAc, NormAc, HDG, TRK, volt1, FQtyL, FQtyR, E1 FFlow, E1 FPres, E1 OilT, E1 OilP, E1 MAP, E1 RPM, E1 CHT1, E1 CHT2, E1 CHT3, E1 CHT4, E1 EGT1, E1 EGT2, E1 EGT3, E1 EGT4, AltGPS, TAS, HSIS, CRS, NAV1, NAV2, COM1, COM2, HCDI, VCDI, WndSpd, WndDr, WptDst, WptBrg, MagVar, AfcsOn, RollM, PitchM, RollC, PichC, VSpdG, GPSfix, HAL, VAL, HPLwas, HPLfd, VPLwas' - fmt = '{date}, {time}, 00:00, , {lat: >12}, {lng: >12}, , , {alt: >7}, , , {gspd: >6}' - tail = ', , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ' + fmt = '{date},{time},00:00,,{lat: >12},{lng: >12},,,{alt: >7},,,{gspd: >6}' + tail = ',,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,' tree = ET.parse(kml) root = tree.getroot() @@ -67,16 +77,24 @@ def export(kml, folder=None): # This is a very rough estimate based on the reported breadcrumbs. # FlightAware appears to collect actual data from ADS-B, but does not include it in the kml unfortuantely. to = (float(lat), float(lng)) - end = datetime.strptime(date + ' ' + time, '%Y-%m-%d %H:%M:%S') + end = parse_datetime(date + ' ' + time) + + # strip fractional sections such as exported from ADSBExchange, which is not compatible with ForeFlight + timenofraction = end.strftime('%H:%M:%S') + gspd = calcSpeed(fm, to, start, end) if fm and start else 0 fm = to start = end # FlightAware KLM altitude is in meters, while G1000 wants feet. alt = round(float(alt) * 3.28084) + + # round lat, long to 4 decimal places because ForeFlight will fail if more than 4 decimal places and ADSBExchange exports 6 decimal places + lat = round(float(lat), 4) + lng = round(float(lng), 4) # Append data with trailing commas for unset values. - csv.append(fmt.format(date=date, time=time, lat=lat, lng=lng, alt=alt, gspd=gspd) + tail) + csv.append(fmt.format(date=date, time=timenofraction, lat=lat, lng=lng, alt=alt, gspd=gspd) + tail) # Write file to disk. with open(fileName, 'w') as f: