diff --git a/README.md b/README.md index f21fb5e..c3f105b 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,11 @@ Work in progress. Goals are: parsing an IGC file containing flight data, giving analytics about the flight, and if I really have time to kill, making some kind of (3D??) view of the flight.. +TODO: +- header parsing +- data point doubly linked list +- Raylib 3d 3rd person flight line visualization???? + # License GNU GPL v3 diff --git a/a.out b/a.out index 73c46c5..3a4bce6 100755 Binary files a/a.out and b/a.out differ diff --git a/igc.c b/igc.c index f4e7f77..56b9177 100644 --- a/igc.c +++ b/igc.c @@ -49,18 +49,62 @@ struct IGC_DataPoint* parse_datapoint(char* line) dp->lon.cardinal = line[23] == EAST ? EAST : WEST; dp->baro_alt = atoi(baro_alt); dp->gps_alt = atoi(gps_alt); - - printf("Data point: %d:%d:%d | %d°%d'%d\"%c %d°%d'%d\"%c | Baro: %dm GPS: %dm\n", dp->hour, dp->minute, dp->second, dp->lat.deg, dp->lat.min, dp->lat.sec, dp->lat.cardinal, dp->lon.deg, dp->lon.min, dp->lon.sec, dp->lon.cardinal, dp->baro_alt, dp->gps_alt); return dp; } -void parse_header_record(char* line) +void show_datapoint(struct IGC_DataPoint* dp) +{ + printf("Data point: %02d:%02d:%02d | %d°%d'%d\"%c %d°%d'%d\"%c | Baro: %dm GPS: %dm\n", dp->hour, dp->minute, dp->second, dp->lat.deg, dp->lat.min, dp->lat.sec, dp->lat.cardinal, dp->lon.deg, dp->lon.min, dp->lon.sec, dp->lon.cardinal, dp->baro_alt, dp->gps_alt); +} + +void show_header_info(struct IGC_Header* hdr) +{ + printf("*** Flight information:\nDate: %02d/%02d/%02d\nPilot: %sCopilot: %sAircraft: %sRegistration: %s", hdr->day, hdr->month, hdr->year, hdr->pilot_name, hdr->crew2_name, hdr->aircraft_name, hdr->aircraft_registration_no); +} + +struct IGC_Header* parse_header_record(struct IGC_Header* hdr, char* line) { if (strncmp(line, "HFDTEDATE", 9) == 0) { - + strtok(line, ":"); + char* date_str = strtok(NULL, ":"); + char day[3], month[3], year[3] = {0}; + + memcpy(day, date_str, 2); + memcpy(month, date_str+2, 2); + memcpy(year, date_str+4, 2); + + hdr->day = atoi(day); + hdr->month = atoi(month); + hdr->year = atoi(year); } + if (strncmp(line, "HFPLTPILOTINCHARGE", 18) == 0) + { + strtok(line, ":"); + strncpy(hdr->pilot_name, strtok(NULL, ":"), SMALL_NAME_MAX); + } + if (strncmp(line, "HFCM2CREW2", 10) == 0) + { + strtok(line, ":"); + strncpy(hdr->crew2_name, strtok(NULL, ":"), SMALL_NAME_MAX); + } + if (strncmp(line, "HFGTYGLIDERTYPE", 15) == 0) + { + strtok(line, ":"); + strncpy(hdr->aircraft_name, strtok(NULL, ":"), SMALL_NAME_MAX); + } + if (strncmp(line, "HFGIDGLIDERID", 13) == 0) + { + strtok(line, ":"); + strncpy(hdr->aircraft_registration_no, strtok(NULL, ":"), SMALL_NAME_MAX); + } + if (strncmp(line, "HFDTMGPSDATUM", 13) == 0) + { + strtok(line, ":"); + strncpy(hdr->gps_datum, strtok(NULL, ":"), SMALL_NAME_MAX); + } + return hdr; } void parse_igc_file(FILE* fp) @@ -68,23 +112,36 @@ void parse_igc_file(FILE* fp) size_t len = 0; char* line = NULL; + struct IGC_Header* hdr = (struct IGC_Header*)calloc(1, sizeof(struct IGC_Header)); + while (getline(&line, &len, fp) != -1) { switch(line[0]) { + case MANUFACTURER: + printf("Manufacturer info: %s", line); + break; + case COMMENT: + printf("Comment: %s", line); + break; case DATAPOINT: struct IGC_DataPoint* dp = parse_datapoint(line); + // show_datapoint(dp); // Doubly linked list of points (so theyre joined in chronological order; opens possibilities for analysis later) // append_datapoint(dp); break; case HEADER: - parse_header_record(line); + hdr = parse_header_record(hdr, line); break; + case SEC_KEY: + printf("Security key found: %s", line); + break; default: - printf("Unrecognized record type '%c'\n", line[0]); + printf("Unhandled record type '%c'\n", line[0]); break; } } + show_header_info(hdr); } int main(int argc, char* argv[]) diff --git a/igc.h b/igc.h index 87759b6..9122ac2 100644 --- a/igc.h +++ b/igc.h @@ -9,11 +9,10 @@ #ifndef IGC_H #define IGC_H +#define SMALL_NAME_MAX 32 #define NAME_MAX 256 #define TMP_SIZE 8 -void parse_igc_file(FILE* fp); - enum IGC_RecordType { MANUFACTURER = 'A', @@ -27,7 +26,7 @@ enum IGC_RecordType PILOT_EVENT = 'E', GEN_PURPOSE_PLACEHOLDER = 'K', COMMENT = 'L', - SEC_KEY = 'G' + SEC_KEY = 'G', }; enum Cardinals @@ -53,16 +52,18 @@ struct IGC_Header int year; // Not exhaustive - char pilot_name[NAME_MAX] = {0}; - char crew2_name[NAME_MAX] = {0}; - char aircraft_name[NAME_MAX] = {0}; - char aircraft_registration_no[NAME_MAX] = {0}; - char gps_datum[NAME_MAX] = {0}; - char firmware_ver[NAME_MAX] = {0}; - char hardware_ver[NAME_MAX] = {0}; - char frtype[NAME_MAX] = {0}; - char press_alt_sensor[NAME_MAX] = {0}; -} + char pilot_name[NAME_MAX]; + char crew2_name[NAME_MAX]; + char aircraft_name[NAME_MAX]; + char aircraft_registration_no[NAME_MAX]; + char gps_datum[NAME_MAX]; + + // (not too important; ignored for now, may be part of "verbose" setting later) + char firmware_ver[NAME_MAX]; + char hardware_ver[NAME_MAX]; + char frtype[NAME_MAX]; + char press_alt_sensor[NAME_MAX]; +}; struct IGC_DataPoint { @@ -80,4 +81,10 @@ struct IGC_DataPoint int gps_alt; }; +void parse_igc_file(FILE* fp); +struct IGC_DataPoint* parse_datapoint(char* line); +void show_datapoint(struct IGC_DataPoint* dp); +void show_header_info(struct IGC_Header* hdr); +struct IGC_Header* parse_header_record(struct IGC_Header* hdr, char* line); + #endif