Skip to content

Commit e6de241

Browse files
scottyoboxothnk423
andauthored
IGC Support (#44)
Added an IGC Logger. Co-authored-by: James Burgess <oxothnk@gmail.com>
1 parent cedcca9 commit e6de241

8 files changed

Lines changed: 164 additions & 14 deletions

File tree

platformio.ini

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ lib_deps =
4040
; WiFi Manager for configuring WiFi credentials over captive portal
4141
WiFiManager
4242

43+
; IGC Logger
44+
https://github.com/scottyob/IgcLogger.git
45+
46+
4347

4448

4549

src/vario/PageMenuLog.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,9 +118,7 @@ void LogMenuPage::setting_change(Button dir, ButtonState state, uint8_t count) {
118118
new_val = SETTING_LOG_FORMAT_ENTRIES - 1;
119119
}
120120

121-
// TODO: Enable more log formats
122-
LOG_FORMAT = LOG_FORMAT_KML;
123-
// LOG_FORMAT = (SettingLogFormat)new_val;
121+
LOG_FORMAT = (SettingLogFormat)new_val;
124122
break;
125123
}
126124
case cursor_log_saveLog: {

src/vario/log.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
#include "gps.h"
1010
#include "logbook/flight.h"
1111
#include "logbook/kml.h"
12+
#include "logbook/igc.h"
1213
#include "settings.h"
1314
#include "speaker.h"
1415
#include "string_utils.h"
@@ -25,6 +26,8 @@ bool DATAFILE = true; // set to false to disable data logging to SDcard
2526
Flight* flight =
2627
NULL; // Pointer to the current flight record (null if we're not deisred to be logging)
2728
Kml kmlFlight;
29+
Igc igcFlight;
30+
2831

2932
// TODO: Delete ME
3033

@@ -192,7 +195,8 @@ void flightTimer_start() {
192195
flight = &kmlFlight;
193196
break;
194197
case LOG_FORMAT_IGC:
195-
// TODO: Change the flight to IGC
198+
flight = &igcFlight;
199+
break;
196200
default:
197201
return; // DO not start the flight if it's an unknown format
198202
}

src/vario/logbook/flight.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@
88
void Flight::startFlight() {
99
File trackLogsDir = SD_MMC.open(this->desiredFilePath());
1010

11-
auto filePrefix = this->desiredFileName();
11+
auto filePrefix = this->desiredFilePath() + "/" + this->desiredFileName();
1212
auto suffix = this->fileNameSuffix();
1313
// Perform a directory listing of all the file in the tracks directory
1414
auto nextFile = trackLogsDir.getNextFileName();
1515
auto desiredFlightNum = 1;
1616
while (!nextFile.isEmpty()) {
17-
Serial.println("Doing dir listing");
1817
if (!nextFile.endsWith(suffix) || !nextFile.startsWith(filePrefix)) {
1918
nextFile = trackLogsDir.getNextFileName();
2019
continue;
@@ -25,19 +24,17 @@ void Flight::startFlight() {
2524
auto flightNumStr =
2625
nextFile.substring(filePrefix.length() + 1, nextFile.length() - suffix.length());
2726
auto flightNum = flightNumStr.toInt();
28-
if (flightNum > desiredFlightNum) {
27+
if (flightNum >= desiredFlightNum) {
2928
desiredFlightNum = flightNum + 1;
3029
}
3130

3231
nextFile = trackLogsDir.getNextFileName();
3332
}
3433

35-
String fileName = this->desiredFilePath() + "/" + filePrefix + "-" +
34+
String fileName = filePrefix + "-" +
3635
(desiredFlightNum < 10 ? String(0) + desiredFlightNum : desiredFlightNum) +
3736
"." + suffix;
3837

39-
Serial.println((String) "Recording flight: " + fileName);
40-
4138
// Create the file for writing
4239
file = SD_MMC.open(fileName, "w", true);
4340
}
@@ -47,6 +44,4 @@ void Flight::end(const FlightStats stats) {
4744
Telemetry.end(); // End and flush telemetry
4845
}
4946

50-
bool Flight::started() {
51-
return (boolean)file;
52-
}
47+
bool Flight::started() { return (boolean)file; }

src/vario/logbook/igc.cpp

Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
#include "igc.h"
2+
3+
#include <SD_MMC.h>
4+
5+
#include "Arduino.h"
6+
#include "ArduinoJson.h"
7+
#include "FS.h"
8+
#include "baro.h"
9+
#include "gps.h"
10+
#include "settings.h"
11+
#include "string_utils.h"
12+
#include "version.h"
13+
#include "time.h"
14+
15+
String latDegreeToStr(double degree) {
16+
char output[9]; // 8 bytes + null terminator
17+
char hemisphere = (degree >= 0) ? 'N' : 'S';
18+
degree = abs(degree);
19+
20+
int degrees = (int)degree;
21+
double minutes = (degree - degrees) * 60;
22+
int intMinutes = (int)minutes;
23+
int fractionalMinutes = (int)((minutes - intMinutes) * 1000);
24+
25+
snprintf(output, 9, "%02d%02d%03d%c", degrees, intMinutes, fractionalMinutes, hemisphere);
26+
return String(output);
27+
}
28+
29+
String lngDegreeToStr(double degree) {
30+
char output[10]; // 9 bytes + null terminator
31+
char hemisphere = (degree >= 0) ? 'E' : 'W';
32+
degree = abs(degree);
33+
34+
int degrees = (int)degree;
35+
double minutes = (degree - degrees) * 60;
36+
int intMinutes = (int)minutes;
37+
int fractionalMinutes = (int)((minutes - intMinutes) * 1000);
38+
39+
snprintf(output, 10, "%03d%02d%03d%c", degrees, intMinutes, fractionalMinutes, hemisphere);
40+
return String(output);
41+
}
42+
43+
const String Igc::desiredFileName() const {
44+
// Name of the file should be for example 2024-12-10-XFH-000-01.IGC
45+
// as per the IGC spec.
46+
char buf[11];
47+
tm cal;
48+
gps_getLocalDateTime(cal);
49+
strftime(buf, 11, "%F", &cal);
50+
51+
String ret = buf;
52+
ret += (String) "-" + IGC_MANUFACTURER_CODE + "-000";
53+
return ret;
54+
}
55+
56+
void Igc::log(unsigned long durationSec) {
57+
// Generate the time in HHMMSS
58+
char buf[8];
59+
tm cal;
60+
gps_getUtcDateTime(cal);
61+
strftime(buf, sizeof(buf), "%H%M%S", &cal);
62+
63+
logger.writeBRecord(buf, // Time in HHMMSS
64+
latDegreeToStr(gps.location.lat()),
65+
lngDegreeToStr(gps.location.lng()),
66+
true,
67+
baro.alt / 100, // cm to meters
68+
gps.altitude.meters(),
69+
toDigits((int)gpsAccuracy.error, 3));
70+
}
71+
72+
void Igc::startFlight() {
73+
Flight::startFlight();
74+
75+
logger.setOutput(file);
76+
77+
// Log the Header
78+
// A record to look like "AXLFLeaf1"
79+
logger.setManufacturerId(IGC_MANUFACTURER_CODE);
80+
logger.setLoggerId("Lea");
81+
logger.setIdExtension("f1");
82+
83+
logger.pilot = "Unknown";
84+
logger.glider_type = "Unknown";
85+
// Overwrite from file if set in the Pilot descriptor
86+
setPilotFromFile();
87+
88+
logger.firmware_version = VERSION;
89+
logger.hardware_version = "Leaf1";
90+
logger.logger_type = (String) "Leaf1," + VERSION;
91+
logger.gps_type = "GNSS LC86G";
92+
logger.pressure_type = "MS5611";
93+
logger.time_zone = (String)(TIME_ZONE / 60);
94+
95+
tm cal;
96+
gps_getUtcDateTime(cal);
97+
strftime(logger.date, sizeof(logger.date), "%d%m%y", &cal);
98+
99+
logger.writeHeader();
100+
101+
// Log the I record (saying we're going to log the, now manditory, FXA record)
102+
const IRecordExtension extensions[] = {IRecordExtension(3, "FXA")};
103+
logger.writeIRecord(sizeof(extensions) / sizeof(extensions[0]), extensions);
104+
}
105+
106+
void Igc::end(const FlightStats stats) {
107+
logger.writeGRecord();
108+
Flight::end(stats);
109+
}
110+
111+
void Igc::setPilotFromFile() {
112+
auto pilotFile = SD_MMC.open("/pilot.json", "r");
113+
if (!pilotFile) {
114+
return; // No pilot JSON file
115+
}
116+
JsonDocument doc;
117+
deserializeJson(doc, pilotFile);
118+
logger.pilot = (String)doc["pilot"];
119+
logger.glider_type = (String)doc["glider_type"];
120+
}

src/vario/logbook/igc.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
#pragma once
2+
#include "IgcLogger.h"
3+
#include "flight.h"
4+
5+
// X for non-registered, LF for Leaf
6+
#define IGC_MANUFACTURER_CODE "XLF"
7+
8+
class Igc : public Flight {
9+
public:
10+
void startFlight() override;
11+
void end(const FlightStats stats) override;
12+
13+
const String fileNameSuffix() const override { return "igc"; }
14+
15+
const String desiredFileName() const override;
16+
void log(unsigned long durationSec) override;
17+
18+
private:
19+
IgcLogger logger;
20+
void setPilotFromFile();
21+
};

src/vario/string_utils.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,9 @@ String formatSeconds(unsigned long seconds,
2727

2828
return String(buffer);
2929
}
30+
31+
String toDigits(const int src, const int numDigits) {
32+
char buffer[10];
33+
sprintf(buffer, ((String)"%0" + numDigits + "d").c_str(), src);
34+
return buffer;
35+
}

src/vario/string_utils.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,6 @@
77
// If rightAlignTo is set, we'll pad this many characters
88
String formatSeconds(unsigned long seconds,
99
const bool minified = false,
10-
const int rightAlignTo = 0);
10+
const int rightAlignTo = 0);
11+
12+
String toDigits(const int src, const int numDigits);

0 commit comments

Comments
 (0)