diff --git a/firmware/application/file.cpp b/firmware/application/file.cpp index 57ae0899..0964b0da 100644 --- a/firmware/application/file.cpp +++ b/firmware/application/file.cpp @@ -461,6 +461,15 @@ std::string path::string() const { return conv.to_bytes(native()); } +// appends a string to the end of filename, but leaves the extension asd.txt + "fg" -> asdfg.txt +path& path::append_filename(const string_type& str) { + const auto t = extension().native(); + _s.erase(_s.size() - t.size()); // remove extension + _s += str; // append string + _s += t; // add back extension + return *this; +} + path& path::replace_extension(const path& replacement) { const auto t = extension().native(); _s.erase(_s.size() - t.size()); diff --git a/firmware/application/file.hpp b/firmware/application/file.hpp index 35632685..ae602f48 100644 --- a/firmware/application/file.hpp +++ b/firmware/application/file.hpp @@ -155,6 +155,8 @@ struct path { path& replace_extension(const path& replacement = path()); + path& append_filename(const string_type& str); + private: string_type _s; }; diff --git a/firmware/application/metadata_file.cpp b/firmware/application/metadata_file.cpp index 3eb34521..bc5d696e 100644 --- a/firmware/application/metadata_file.cpp +++ b/firmware/application/metadata_file.cpp @@ -31,6 +31,9 @@ using namespace std::literals; const std::string_view center_freq_name = "center_frequency"sv; const std::string_view sample_rate_name = "sample_rate"sv; +const std::string_view latitude_name = "latitude"sv; +const std::string_view longitude_name = "longitude"sv; +const std::string_view satinuse_name = "satinuse"sv; fs::path get_metadata_path(const fs::path& capture_path) { auto temp = capture_path; @@ -54,6 +57,23 @@ Optional write_metadata_file(const fs::path& path, capture_metadata if (error) return error; + // add gps data if available + if (metadata.latitude != 0 && metadata.longitude != 0 && metadata.latitude < 200 && metadata.longitude < 200) { + error = f.write_line(std::string{latitude_name} + "=" + + to_string_decimal(metadata.latitude, 7)); + if (error) + return error; + + error = f.write_line(std::string{longitude_name} + "=" + + to_string_decimal(metadata.longitude, 7)); + if (error) + return error; + + error = f.write_line(std::string{satinuse_name} + "=" + + to_string_dec_uint(metadata.satinuse)); + if (error) + return error; + } return {}; } @@ -77,6 +97,12 @@ Optional read_metadata_file(const fs::path& path) { parse_int(cols[1], metadata.center_frequency); else if (cols[0] == sample_rate_name) parse_int(cols[1], metadata.sample_rate); + else if (cols[0] == latitude_name) + parse_float_meta(cols[1], metadata.latitude); + else if (cols[0] == longitude_name) + parse_float_meta(cols[1], metadata.longitude); + else if (cols[0] == satinuse_name) + parse_int(cols[1], metadata.satinuse); else continue; } @@ -86,3 +112,18 @@ Optional read_metadata_file(const fs::path& path) { return metadata; } + +bool parse_float_meta(std::string_view str, float& out_val) { + out_val = {}; + + if (str.size() > max_parse_int_length) + return false; + + // Copy onto the stack and null terminate. + char zstr[max_parse_int_length + 1]; + std::memcpy(zstr, str.data(), str.size()); + zstr[str.size()] = '\0'; + errno = 0; + out_val = strtod(zstr, nullptr); + return (errno == 0); +} \ No newline at end of file diff --git a/firmware/application/metadata_file.hpp b/firmware/application/metadata_file.hpp index d3e055e4..a9d47f01 100644 --- a/firmware/application/metadata_file.hpp +++ b/firmware/application/metadata_file.hpp @@ -29,6 +29,9 @@ struct capture_metadata { rf::Frequency center_frequency; uint32_t sample_rate; + float latitude = 0; + float longitude = 0; + uint8_t satinuse = 0; }; std::filesystem::path get_metadata_path(const std::filesystem::path& capture_path); @@ -36,4 +39,5 @@ std::filesystem::path get_metadata_path(const std::filesystem::path& capture_pat Optional write_metadata_file(const std::filesystem::path& path, capture_metadata metadata); Optional read_metadata_file(const std::filesystem::path& path); +bool parse_float_meta(std::string_view str, float& out_val); #endif // __METADATA_FILE_HPP__ \ No newline at end of file diff --git a/firmware/application/ui_record_view.cpp b/firmware/application/ui_record_view.cpp index 9aac8945..23691044 100644 --- a/firmware/application/ui_record_view.cpp +++ b/firmware/application/ui_record_view.cpp @@ -205,6 +205,11 @@ void RecordView::start() { return; } + // check for geo data, if present append filename with _GEO + if (latitude != 0 && longitude != 0 && latitude < 200 && longitude < 200) { + base_path.append_filename(u"_GEO"); + } + std::unique_ptr writer; switch (file_type) { case FileType::WAV: { @@ -223,7 +228,7 @@ void RecordView::start() { case FileType::RawS8: case FileType::RawS16: { const auto metadata_file_error = write_metadata_file( - get_metadata_path(base_path), {receiver_model.target_frequency(), sampling_rate}); + get_metadata_path(base_path), {receiver_model.target_frequency(), sampling_rate, latitude, longitude, satinuse}); if (metadata_file_error.is_valid()) { handle_error(metadata_file_error.value()); return; @@ -342,6 +347,12 @@ void RecordView::trim_capture() { trim_path = {}; } +void RecordView::on_gps(const GPSPosDataMessage* msg) { + latitude = msg->lat; + longitude = msg->lon; + satinuse = msg->satinuse; +} + void RecordView::handle_capture_thread_done(const File::Error error) { stop(); if (error.code()) { diff --git a/firmware/application/ui_record_view.hpp b/firmware/application/ui_record_view.hpp index 785f1428..9d94d5cf 100644 --- a/firmware/application/ui_record_view.hpp +++ b/firmware/application/ui_record_view.hpp @@ -88,6 +88,7 @@ class RecordView : public View { OversampleRate get_oversample_rate(uint32_t sample_rate); + void on_gps(const GPSPosDataMessage* msg); // bool pitch_rssi_enabled = false; // Time Stamp @@ -95,6 +96,10 @@ class RecordView : public View { bool filename_as_is = false; rtc::RTC datetime{}; + float latitude = 0; // for wardriwing with ext module + float longitude = 0; + uint8_t satinuse = 0; // to see if there was enough sats used or not + const std::filesystem::path filename_stem_pattern; const std::filesystem::path folder; FileType file_type; @@ -147,6 +152,13 @@ class RecordView : public View { const auto message = *reinterpret_cast(p); this->handle_capture_thread_done(message.error); }}; + + MessageHandlerRegistration message_handler_gps{ + Message::ID::GPSPosData, + [this](Message* const p) { + const auto message = static_cast(p); + this->on_gps(message); + }}; }; } /* namespace ui */ diff --git a/firmware/application/usb_serial_shell.cpp b/firmware/application/usb_serial_shell.cpp index e00b7f4b..21fc12c0 100644 --- a/firmware/application/usb_serial_shell.cpp +++ b/firmware/application/usb_serial_shell.cpp @@ -905,8 +905,8 @@ static void cmd_cpld_read(BaseSequentialStream* chp, int argc, char* argv[]) { } static void cmd_gotgps(BaseSequentialStream* chp, int argc, char* argv[]) { - const char* usage = "usage: gotgps [altitude] [speed]\r\n"; - if (argc < 2 || argc > 4) { + const char* usage = "usage: gotgps [altitude] [speed] [satinuse]\r\n"; + if (argc < 2 || argc > 5) { chprintf(chp, usage); return; } @@ -914,9 +914,11 @@ static void cmd_gotgps(BaseSequentialStream* chp, int argc, char* argv[]) { float lon = atof(argv[1]); int32_t altitude = 0; int32_t speed = 0; + uint8_t satinuse = 0; if (argc >= 3) altitude = strtol(argv[2], NULL, 10); if (argc >= 4) speed = strtol(argv[3], NULL, 10); - GPSPosDataMessage msg{lat, lon, altitude, speed}; + if (argc >= 5) satinuse = strtol(argv[4], NULL, 10); + GPSPosDataMessage msg{lat, lon, altitude, speed, satinuse}; EventDispatcher::send_message(msg); chprintf(chp, "ok\r\n"); } diff --git a/firmware/common/message.hpp b/firmware/common/message.hpp index 4873ee83..717fb50b 100644 --- a/firmware/common/message.hpp +++ b/firmware/common/message.hpp @@ -1313,17 +1313,20 @@ class GPSPosDataMessage : public Message { float lat = 200.0, float lon = 200.0, int32_t altitude = 0, - int32_t speed = 0) + int32_t speed = 0, + uint8_t satinuse = 0) : Message{ID::GPSPosData}, lat{lat}, lon{lon}, altitude{altitude}, - speed{speed} { + speed{speed}, + satinuse{satinuse} { } float lat = 200.0; float lon = 200.0; int32_t altitude = 0; int32_t speed = 0; + uint8_t satinuse = 0; }; class OrientationDataMessage : public Message {