2024-09-27 20:20:51 +02:00
|
|
|
#include "archive_loader.h"
|
|
|
|
|
|
|
|
|
|
#include "common/utils.h"
|
2025-12-08 17:50:52 +01:00
|
|
|
#include "handlers/processing/processing.h"
|
2025-07-08 17:42:18 +01:00
|
|
|
#include "libs/base64/base64.h"
|
2024-09-27 20:20:51 +02:00
|
|
|
#include "logger.h"
|
|
|
|
|
#include "main_ui.h"
|
2025-07-08 17:42:18 +01:00
|
|
|
#include "nlohmann/json.hpp"
|
2025-05-26 19:21:10 +01:00
|
|
|
#include "utils/http.h"
|
2025-07-08 17:42:18 +01:00
|
|
|
#include "utils/time.h"
|
2024-09-27 20:20:51 +02:00
|
|
|
|
|
|
|
|
namespace satdump
|
|
|
|
|
{
|
|
|
|
|
struct EumetSatProductItem
|
|
|
|
|
{
|
|
|
|
|
std::string name;
|
|
|
|
|
std::string id;
|
2024-09-28 12:53:03 +02:00
|
|
|
bool is_hdf;
|
2025-08-14 15:30:29 +02:00
|
|
|
bool is_single_hdf;
|
2026-03-13 07:54:12 +01:00
|
|
|
bool legacy;
|
2024-09-27 20:20:51 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
std::vector<EumetSatProductItem> eumetsat_products = {
|
|
|
|
|
{
|
|
|
|
|
"MTG FCI 0 deg Normal Resolution",
|
|
|
|
|
"EO%3AEUM%3ADAT%3A0662",
|
2024-09-28 12:53:03 +02:00
|
|
|
true,
|
2025-08-14 15:30:29 +02:00
|
|
|
false,
|
2026-03-13 07:54:12 +01:00
|
|
|
false,
|
2024-09-27 20:20:51 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"MTG FCI 0 deg Full Resolution",
|
|
|
|
|
"EO%3AEUM%3ADAT%3A0665",
|
2024-09-28 12:53:03 +02:00
|
|
|
true,
|
2025-08-14 15:30:29 +02:00
|
|
|
false,
|
2026-03-13 07:54:12 +01:00
|
|
|
false,
|
2024-09-27 20:20:51 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"MSG SEVIRI 0 deg",
|
|
|
|
|
"EO%3AEUM%3ADAT%3AMSG%3AHRSEVIRI",
|
2024-09-28 12:53:03 +02:00
|
|
|
false,
|
2025-08-14 15:30:29 +02:00
|
|
|
false,
|
2026-03-13 07:54:12 +01:00
|
|
|
false,
|
2024-09-27 20:20:51 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"MSG SEVIRI 0 deg RSS",
|
|
|
|
|
"EO%3AEUM%3ADAT%3AMSG%3AMSG15-RSS",
|
2024-09-28 12:53:03 +02:00
|
|
|
false,
|
2025-08-14 15:30:29 +02:00
|
|
|
false,
|
2026-03-13 07:54:12 +01:00
|
|
|
false,
|
2024-09-27 20:20:51 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"MSG SEVIRI IODC",
|
|
|
|
|
"EO%3AEUM%3ADAT%3AMSG%3AHRSEVIRI-IODC",
|
2024-09-28 12:53:03 +02:00
|
|
|
false,
|
2025-08-14 15:30:29 +02:00
|
|
|
false,
|
2026-03-13 07:54:12 +01:00
|
|
|
false,
|
2024-09-27 20:20:51 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"MetOp AVHRR",
|
|
|
|
|
"EO%3AEUM%3ADAT%3AMETOP%3AAVHRRL1",
|
2024-09-28 12:53:03 +02:00
|
|
|
false,
|
2025-08-14 15:30:29 +02:00
|
|
|
false,
|
2026-03-13 07:54:12 +01:00
|
|
|
false,
|
2024-09-27 20:20:51 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"MetOp MHS",
|
|
|
|
|
"EO%3AEUM%3ADAT%3AMETOP%3AMHSL1",
|
2024-09-28 12:53:03 +02:00
|
|
|
false,
|
2025-08-14 15:30:29 +02:00
|
|
|
false,
|
2026-03-13 07:54:12 +01:00
|
|
|
false,
|
2024-09-27 20:20:51 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"MetOp AMSU",
|
|
|
|
|
"EO%3AEUM%3ADAT%3AMETOP%3AAMSUL1",
|
2024-09-28 12:53:03 +02:00
|
|
|
false,
|
2025-08-14 15:30:29 +02:00
|
|
|
false,
|
2026-03-13 07:54:12 +01:00
|
|
|
false,
|
2024-09-27 20:20:51 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"MetOp HIRS",
|
|
|
|
|
"EO%3AEUM%3ADAT%3AMETOP%3AHIRSL1",
|
2024-09-28 12:53:03 +02:00
|
|
|
false,
|
2025-08-14 15:30:29 +02:00
|
|
|
false,
|
2026-03-13 07:54:12 +01:00
|
|
|
false,
|
2025-08-14 15:30:29 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"AWS MWR",
|
|
|
|
|
"EO%3AEUM%3ADAT%3A0905",
|
|
|
|
|
true,
|
|
|
|
|
true,
|
2026-03-13 07:54:12 +01:00
|
|
|
false,
|
2024-09-28 12:53:03 +02:00
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"Sentinel-3 OLCI Full Resolution",
|
|
|
|
|
"EO%3AEUM%3ADAT%3A0409",
|
|
|
|
|
true,
|
2025-08-14 15:30:29 +02:00
|
|
|
false,
|
2026-03-13 07:54:12 +01:00
|
|
|
true,
|
2024-09-28 12:53:03 +02:00
|
|
|
},
|
2024-10-04 15:54:15 +02:00
|
|
|
{
|
|
|
|
|
"Sentinel-3 SLSTR",
|
|
|
|
|
"EO%3AEUM%3ADAT%3A0411",
|
|
|
|
|
true,
|
2025-08-14 15:30:29 +02:00
|
|
|
false,
|
2026-03-13 07:54:12 +01:00
|
|
|
true,
|
2024-10-04 15:54:15 +02:00
|
|
|
},
|
2024-09-28 12:53:03 +02:00
|
|
|
};
|
2024-09-27 20:20:51 +02:00
|
|
|
|
|
|
|
|
std::string ArchiveLoader::getEumetSatToken()
|
|
|
|
|
{
|
2024-09-27 23:25:22 +02:00
|
|
|
std::string final_token = macaron::Base64::Encode(eumetsat_user_consumer_credential + ":" + eumetsat_user_consumer_secret);
|
|
|
|
|
|
2024-09-27 20:20:51 +02:00
|
|
|
std::string resp = "";
|
2025-05-26 19:21:10 +01:00
|
|
|
if (satdump::perform_http_request_post("https://api.eumetsat.int/token", resp, "grant_type=client_credentials", "Authorization: Basic " + final_token) != 1)
|
2024-09-27 20:20:51 +02:00
|
|
|
resp = nlohmann::json::parse(resp)["access_token"];
|
|
|
|
|
logger->trace("Token " + resp);
|
|
|
|
|
return resp;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void ArchiveLoader::updateEUMETSAT()
|
|
|
|
|
{
|
2024-09-27 23:25:22 +02:00
|
|
|
try
|
2024-09-27 20:20:51 +02:00
|
|
|
{
|
2024-09-27 23:25:22 +02:00
|
|
|
int year, month, day;
|
|
|
|
|
{
|
|
|
|
|
time_t tttime = request_time.get();
|
|
|
|
|
std::tm *timeReadable = gmtime(&tttime);
|
|
|
|
|
year = timeReadable->tm_year + 1900;
|
|
|
|
|
month = timeReadable->tm_mon + 1;
|
|
|
|
|
day = timeReadable->tm_mday;
|
|
|
|
|
}
|
2024-09-27 20:20:51 +02:00
|
|
|
|
2025-07-08 17:42:18 +01:00
|
|
|
std::string url = "https://api.eumetsat.int/data/browse/1.0.0/collections/" + std::string(eumetsat_products[eumetsat_selected_dataset].id) + "/dates/" + std::to_string(year) + "/" +
|
|
|
|
|
(month < 10 ? "0" : "") + std::to_string(month) + "/" + (day < 10 ? "0" : "") + std::to_string(day) + "/products?format=json";
|
2024-09-27 23:25:22 +02:00
|
|
|
std::string resp;
|
|
|
|
|
logger->info(url);
|
2025-05-26 19:21:10 +01:00
|
|
|
if (satdump::perform_http_request(url, resp, "") != 1)
|
2024-09-27 20:20:51 +02:00
|
|
|
{
|
2024-09-27 23:25:22 +02:00
|
|
|
eumetsat_list.clear();
|
|
|
|
|
|
|
|
|
|
nlohmann::json respj = nlohmann::json::parse(resp);
|
|
|
|
|
// saveJsonFile("test.json", respj);
|
|
|
|
|
if (respj.contains("products"))
|
2024-09-27 20:20:51 +02:00
|
|
|
{
|
2024-12-12 22:51:48 -05:00
|
|
|
for (size_t i = 0; i < respj["products"].size(); i++)
|
2024-09-27 23:25:22 +02:00
|
|
|
{
|
|
|
|
|
auto &prod = respj["products"][i];
|
2024-09-27 20:20:51 +02:00
|
|
|
|
2024-09-27 23:25:22 +02:00
|
|
|
std::tm timeS;
|
|
|
|
|
memset(&timeS, 0, sizeof(std::tm));
|
2024-09-27 20:20:51 +02:00
|
|
|
|
2025-07-08 17:42:18 +01:00
|
|
|
if (sscanf(prod["date"].get<std::string>().c_str(), "%4d-%2d-%2dT%2d:%2d:%2d.%*dZ/%*d-%*d-%*dT%*d:%*d:%*d.%*dZ", &timeS.tm_year, &timeS.tm_mon, &timeS.tm_mday, &timeS.tm_hour,
|
|
|
|
|
&timeS.tm_min, &timeS.tm_sec) == 6)
|
2024-09-27 23:25:22 +02:00
|
|
|
{
|
|
|
|
|
timeS.tm_year -= 1900;
|
|
|
|
|
timeS.tm_mon -= 1;
|
|
|
|
|
timeS.tm_isdst = -1;
|
|
|
|
|
time_t timestamp = timegm(&timeS);
|
2024-09-27 20:20:51 +02:00
|
|
|
|
2024-09-27 23:25:22 +02:00
|
|
|
std::string prod_d = prod["links"][0]["href"];
|
2025-05-26 19:21:10 +01:00
|
|
|
eumetsat_list.push_back({satdump::timestamp_to_string(timestamp), prod_d});
|
2024-09-27 23:25:22 +02:00
|
|
|
}
|
2024-09-27 20:20:51 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-27 23:25:22 +02:00
|
|
|
catch (std::exception &e)
|
|
|
|
|
{
|
|
|
|
|
logger->error("Error updating product list! %s", e.what());
|
|
|
|
|
}
|
2024-09-27 20:20:51 +02:00
|
|
|
}
|
|
|
|
|
|
2026-01-26 21:16:04 +01:00
|
|
|
struct ExceptionReport
|
|
|
|
|
{
|
|
|
|
|
std::string type;
|
|
|
|
|
std::string exceptionCode;
|
|
|
|
|
std::string exceptionText;
|
|
|
|
|
|
|
|
|
|
NLOHMANN_DEFINE_TYPE_INTRUSIVE(ExceptionReport, type, exceptionCode, exceptionText)
|
|
|
|
|
};
|
|
|
|
|
|
2024-09-27 20:20:51 +02:00
|
|
|
void ArchiveLoader::renderEumetsat(ImVec2 wsize)
|
|
|
|
|
{
|
2025-07-08 17:42:18 +01:00
|
|
|
bool should_disable = file_downloader.is_busy();
|
2024-09-27 20:20:51 +02:00
|
|
|
|
|
|
|
|
if (should_disable)
|
|
|
|
|
style::beginDisabled();
|
|
|
|
|
|
2024-09-27 23:25:22 +02:00
|
|
|
if (ImGui::BeginCombo("##archiveloader_dataset", eumetsat_products[eumetsat_selected_dataset].name.c_str()))
|
2024-09-27 20:20:51 +02:00
|
|
|
{
|
2024-12-12 22:51:48 -05:00
|
|
|
for (int i = 0; i < (int)eumetsat_products.size(); i++)
|
2024-09-27 20:20:51 +02:00
|
|
|
if (ImGui::Selectable(eumetsat_products[i].name.c_str(), eumetsat_selected_dataset == i))
|
|
|
|
|
{
|
|
|
|
|
eumetsat_selected_dataset = i;
|
|
|
|
|
updateEUMETSAT();
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndCombo();
|
|
|
|
|
}
|
2024-09-27 23:25:22 +02:00
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Refresh##archiveloader_refresh"))
|
|
|
|
|
updateEUMETSAT();
|
|
|
|
|
|
2024-12-11 13:30:10 -05:00
|
|
|
ImGui::TextUnformatted("Date: ");
|
|
|
|
|
ImGui::SameLine();
|
2024-09-27 23:25:22 +02:00
|
|
|
request_time.draw();
|
|
|
|
|
ImGui::SameLine();
|
|
|
|
|
if (ImGui::Button("Current##archiveloader_setcurrenttime"))
|
|
|
|
|
request_time.set(time(0));
|
2024-09-27 20:20:51 +02:00
|
|
|
|
2024-12-12 22:51:48 -05:00
|
|
|
float target_height = wsize.y - 260 * ui_scale;
|
2025-07-08 17:42:18 +01:00
|
|
|
ImGui::BeginChild("##archiveloader_subwindow", {ImGui::GetContentRegionAvail().x, target_height < 5 * ui_scale ? 5 * ui_scale : target_height}, false,
|
|
|
|
|
ImGuiWindowFlags_AlwaysVerticalScrollbar);
|
2024-09-27 20:20:51 +02:00
|
|
|
if (ImGui::BeginTable("##archiveloadertable", 2, ImGuiTableFlags_Resizable | ImGuiTableFlags_Borders | ImGuiTableFlags_RowBg))
|
|
|
|
|
{
|
|
|
|
|
ImGui::TableSetupColumn("##archiveloadertable_name", ImGuiTableColumnFlags_None);
|
|
|
|
|
ImGui::TableSetupColumn("##archiveloadertable_butt", ImGuiTableColumnFlags_None);
|
|
|
|
|
|
|
|
|
|
for (auto &str : eumetsat_list)
|
|
|
|
|
{
|
|
|
|
|
ImGui::TableNextColumn();
|
2024-09-27 23:25:22 +02:00
|
|
|
ImGui::Text("%s", str.timestamp.c_str());
|
2024-09-27 20:20:51 +02:00
|
|
|
|
|
|
|
|
ImGui::TableNextColumn();
|
2024-09-27 23:25:22 +02:00
|
|
|
if (ImGui::Button(std::string("Load##archiveloadertablebutton_" + str.timestamp).c_str()))
|
2024-09-27 20:20:51 +02:00
|
|
|
{
|
|
|
|
|
std::string resp;
|
2025-05-26 19:21:10 +01:00
|
|
|
if (satdump::perform_http_request(str.href, resp, "") != 1)
|
2024-09-27 20:20:51 +02:00
|
|
|
{
|
|
|
|
|
nlohmann::json respj = nlohmann::json::parse(resp);
|
2025-08-14 15:30:29 +02:00
|
|
|
// printf("\n%s\n", respj.dump(4).c_str());
|
2024-09-27 20:20:51 +02:00
|
|
|
|
|
|
|
|
std::string nat_link, file_name;
|
2025-08-14 15:30:29 +02:00
|
|
|
if (eumetsat_products[eumetsat_selected_dataset].is_hdf && !eumetsat_products[eumetsat_selected_dataset].is_single_hdf)
|
2024-09-27 20:20:51 +02:00
|
|
|
{
|
|
|
|
|
auto &respj2 = respj["properties"]["links"]["data"];
|
|
|
|
|
|
|
|
|
|
for (auto &item : respj2.items())
|
|
|
|
|
if (item.value()["mediaType"].get<std::string>() == "application/zip")
|
|
|
|
|
{
|
|
|
|
|
nat_link = item.value()["href"].get<std::string>();
|
|
|
|
|
file_name = respj["id"].get<std::string>() + ".zip";
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
auto &respj2 = respj["properties"]["links"]["sip-entries"];
|
|
|
|
|
|
2025-08-14 15:30:29 +02:00
|
|
|
if (eumetsat_products[eumetsat_selected_dataset].is_single_hdf)
|
|
|
|
|
{
|
|
|
|
|
for (auto &item : respj2.items())
|
|
|
|
|
if (item.value()["mediaType"].get<std::string>() == "application/x-netcdf")
|
|
|
|
|
{
|
|
|
|
|
nat_link = item.value()["href"].get<std::string>();
|
|
|
|
|
file_name = item.value()["title"].get<std::string>();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
for (auto &item : respj2.items())
|
|
|
|
|
if (item.value()["mediaType"].get<std::string>() == "application/octet-stream")
|
|
|
|
|
{
|
|
|
|
|
nat_link = item.value()["href"].get<std::string>();
|
|
|
|
|
file_name = item.value()["title"].get<std::string>();
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-09-27 20:20:51 +02:00
|
|
|
}
|
|
|
|
|
|
2025-07-08 17:42:18 +01:00
|
|
|
// logger->trace("\n%s\n", nat_link.c_str());
|
2024-09-27 20:20:51 +02:00
|
|
|
|
|
|
|
|
std::string download_path = products_download_and_process_directory + "/" + file_name;
|
2025-07-08 17:42:18 +01:00
|
|
|
std::string process_path = (download_location && output_selection.isValid() ? output_selection.getPath() : products_download_and_process_directory) + "/" +
|
|
|
|
|
std::filesystem::path(file_name).stem().string();
|
2026-03-13 07:54:12 +01:00
|
|
|
bool is_legacy = eumetsat_products[eumetsat_selected_dataset].legacy;
|
2024-09-27 20:20:51 +02:00
|
|
|
|
2026-03-13 07:54:12 +01:00
|
|
|
auto func = [this, nat_link, download_path, process_path, is_legacy](int)
|
2024-09-27 20:20:51 +02:00
|
|
|
{
|
2024-09-27 23:25:22 +02:00
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (file_downloader.download_file(nat_link, download_path, "Authorization: Bearer " + getEumetSatToken()) != 1)
|
|
|
|
|
{
|
2026-01-26 21:16:04 +01:00
|
|
|
size_t size = getFilesize(download_path);
|
|
|
|
|
|
|
|
|
|
if (size < 100e3)
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
auto json = loadJsonFile(download_path);
|
|
|
|
|
if (json["type"] == "ExceptionReport")
|
|
|
|
|
{
|
|
|
|
|
std::vector<ExceptionReport> errs = json["exceptions"];
|
|
|
|
|
for (auto &e : errs)
|
|
|
|
|
logger->critical("EUMETSAT Error : " + e.exceptionText);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (std::exception &e)
|
|
|
|
|
{
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-03-13 07:54:12 +01:00
|
|
|
if (is_legacy)
|
|
|
|
|
eventBus->fire_event<explorer::ExplorerAddHandlerEvent>(
|
|
|
|
|
{std::make_shared<handlers::OffProcessingHandler>("off2pro", "file", download_path, process_path, nlohmann::json()), true, true});
|
|
|
|
|
else
|
|
|
|
|
eventBus->fire_event<explorer::ExplorerLoadFileEvent>({download_path});
|
2024-09-27 23:25:22 +02:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
catch (std::exception &e)
|
2024-09-27 20:20:51 +02:00
|
|
|
{
|
2024-12-06 19:45:48 +01:00
|
|
|
logger->error("Failed downloading file from EUMETSAT! %s", e.what());
|
2024-09-27 20:20:51 +02:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
ui_thread_pool.push(func);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ImGui::EndTable();
|
|
|
|
|
}
|
|
|
|
|
ImGui::EndChild();
|
|
|
|
|
if (should_disable)
|
|
|
|
|
style::endDisabled();
|
|
|
|
|
}
|
2025-07-08 17:42:18 +01:00
|
|
|
} // namespace satdump
|