mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 19:50:05 +00:00
Add IEM load text product API functionality
This commit is contained in:
parent
f06191f290
commit
2720ad6a38
5 changed files with 90 additions and 20 deletions
|
|
@ -7,7 +7,7 @@ namespace scwx
|
||||||
namespace provider
|
namespace provider
|
||||||
{
|
{
|
||||||
|
|
||||||
TEST(IemWarningsProviderTest, LoadUpdatedFiles)
|
TEST(IemWarningsProviderTest, ListTextProducts)
|
||||||
{
|
{
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
using sys_days = time_point<system_clock, days>;
|
using sys_days = time_point<system_clock, days>;
|
||||||
|
|
@ -30,5 +30,18 @@ TEST(IemWarningsProviderTest, LoadUpdatedFiles)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(IemWarningsProviderTest, LoadTextProducts)
|
||||||
|
{
|
||||||
|
static const std::vector<std::string> productIds {
|
||||||
|
"202303250016-KMEG-WFUS54-TORMEG", //
|
||||||
|
"202303252015-KFFC-WFUS52-TORFFC"};
|
||||||
|
|
||||||
|
IemWarningsProvider provider {};
|
||||||
|
|
||||||
|
auto textProducts = provider.LoadTextProducts(productIds);
|
||||||
|
|
||||||
|
EXPECT_EQ(textProducts.size(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace provider
|
} // namespace provider
|
||||||
} // namespace scwx
|
} // namespace scwx
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <scwx/awips/text_product_file.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
@ -21,11 +23,14 @@ public:
|
||||||
IemWarningsProvider(IemWarningsProvider&&) noexcept;
|
IemWarningsProvider(IemWarningsProvider&&) noexcept;
|
||||||
IemWarningsProvider& operator=(IemWarningsProvider&&) noexcept;
|
IemWarningsProvider& operator=(IemWarningsProvider&&) noexcept;
|
||||||
|
|
||||||
std::vector<std::string>
|
static std::vector<std::string>
|
||||||
ListTextProducts(std::chrono::sys_time<std::chrono::days> date,
|
ListTextProducts(std::chrono::sys_time<std::chrono::days> date,
|
||||||
std::optional<std::string_view> cccc = {},
|
std::optional<std::string_view> cccc = {},
|
||||||
std::optional<std::string_view> pil = {});
|
std::optional<std::string_view> pil = {});
|
||||||
|
|
||||||
|
static std::vector<std::shared_ptr<awips::TextProductFile>>
|
||||||
|
LoadTextProducts(const std::vector<std::string>& textProducts);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class Impl;
|
class Impl;
|
||||||
std::unique_ptr<Impl> p;
|
std::unique_ptr<Impl> p;
|
||||||
|
|
|
||||||
|
|
@ -132,9 +132,19 @@ bool WmoHeader::Parse(std::istream& is)
|
||||||
{
|
{
|
||||||
util::getline(is, sohLine);
|
util::getline(is, sohLine);
|
||||||
util::getline(is, sequenceLine);
|
util::getline(is, sequenceLine);
|
||||||
|
util::getline(is, wmoLine);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// The next line could be the WMO line or the sequence line
|
||||||
|
util::getline(is, wmoLine);
|
||||||
|
if (wmoLine.length() < 18)
|
||||||
|
{
|
||||||
|
sequenceLine.swap(wmoLine);
|
||||||
|
util::getline(is, wmoLine);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
util::getline(is, wmoLine);
|
|
||||||
util::getline(is, awipsLine);
|
util::getline(is, awipsLine);
|
||||||
|
|
||||||
if (is.eof())
|
if (is.eof())
|
||||||
|
|
|
||||||
|
|
@ -27,11 +27,6 @@ public:
|
||||||
Impl& operator=(const Impl&) = delete;
|
Impl& operator=(const Impl&) = delete;
|
||||||
Impl(const Impl&&) = delete;
|
Impl(const Impl&&) = delete;
|
||||||
Impl& operator=(const Impl&&) = delete;
|
Impl& operator=(const Impl&&) = delete;
|
||||||
|
|
||||||
std::vector<std::string>
|
|
||||||
ListTextProducts(std::chrono::sys_time<std::chrono::days> date,
|
|
||||||
std::optional<std::string_view> cccc = {},
|
|
||||||
std::optional<std::string_view> pil = {});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
IemWarningsProvider::IemWarningsProvider() : p(std::make_unique<Impl>()) {}
|
IemWarningsProvider::IemWarningsProvider() : p(std::make_unique<Impl>()) {}
|
||||||
|
|
@ -46,14 +41,6 @@ std::vector<std::string> IemWarningsProvider::ListTextProducts(
|
||||||
std::chrono::sys_time<std::chrono::days> date,
|
std::chrono::sys_time<std::chrono::days> date,
|
||||||
std::optional<std::string_view> cccc,
|
std::optional<std::string_view> cccc,
|
||||||
std::optional<std::string_view> pil)
|
std::optional<std::string_view> pil)
|
||||||
{
|
|
||||||
return p->ListTextProducts(date, cccc, pil);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<std::string> IemWarningsProvider::Impl::ListTextProducts(
|
|
||||||
std::chrono::sys_time<std::chrono::days> date,
|
|
||||||
std::optional<std::string_view> cccc,
|
|
||||||
std::optional<std::string_view> pil)
|
|
||||||
{
|
{
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
|
|
||||||
|
|
@ -149,4 +136,51 @@ std::vector<std::string> IemWarningsProvider::Impl::ListTextProducts(
|
||||||
return textProducts;
|
return textProducts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<awips::TextProductFile>>
|
||||||
|
IemWarningsProvider::LoadTextProducts(
|
||||||
|
const std::vector<std::string>& textProducts)
|
||||||
|
{
|
||||||
|
auto parameters = cpr::Parameters {{"nolimit", "true"}};
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string_view, cpr::AsyncResponse>>
|
||||||
|
asyncResponses {};
|
||||||
|
|
||||||
|
for (auto& productId : textProducts)
|
||||||
|
{
|
||||||
|
asyncResponses.emplace_back(
|
||||||
|
productId,
|
||||||
|
cpr::GetAsync(
|
||||||
|
cpr::Url {kBaseUrl_ + kNwsTextProductEndpoint_ + productId},
|
||||||
|
network::cpr::GetHeader(),
|
||||||
|
parameters));
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<awips::TextProductFile>> textProductFiles;
|
||||||
|
|
||||||
|
for (auto& asyncResponse : asyncResponses)
|
||||||
|
{
|
||||||
|
auto response = asyncResponse.second.get();
|
||||||
|
|
||||||
|
if (response.status_code == cpr::status::HTTP_OK)
|
||||||
|
{
|
||||||
|
// Load file
|
||||||
|
std::shared_ptr<awips::TextProductFile> textProductFile {
|
||||||
|
std::make_shared<awips::TextProductFile>()};
|
||||||
|
std::istringstream responseBody {response.text};
|
||||||
|
if (textProductFile->LoadData(responseBody))
|
||||||
|
{
|
||||||
|
textProductFiles.push_back(textProductFile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logger_->warn("Could not load text product: {} ({})",
|
||||||
|
asyncResponse.first,
|
||||||
|
response.status_line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return textProductFiles;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace scwx::provider
|
} // namespace scwx::provider
|
||||||
|
|
|
||||||
|
|
@ -77,11 +77,19 @@ tag_invoke(boost::json::value_to_tag<ValidationError::Detail>,
|
||||||
detail.type_ = jo.at("type").as_string();
|
detail.type_ = jo.at("type").as_string();
|
||||||
detail.loc_ = boost::json::value_to<
|
detail.loc_ = boost::json::value_to<
|
||||||
std::vector<std::variant<std::int64_t, std::string>>>(jo.at("loc"));
|
std::vector<std::variant<std::int64_t, std::string>>>(jo.at("loc"));
|
||||||
detail.msg_ = jo.at("msg").as_string();
|
detail.msg_ = jo.at("msg").as_string();
|
||||||
detail.input_ = jo.at("input").as_string();
|
|
||||||
|
|
||||||
detail.ctx_ =
|
// Optional parameters
|
||||||
boost::json::value_to<ValidationError::Detail::Context>(jo.at("ctx"));
|
if (jo.contains("input"))
|
||||||
|
{
|
||||||
|
detail.input_ = jo.at("input").as_string();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jo.contains("ctx"))
|
||||||
|
{
|
||||||
|
detail.ctx_ =
|
||||||
|
boost::json::value_to<ValidationError::Detail::Context>(jo.at("ctx"));
|
||||||
|
}
|
||||||
|
|
||||||
return detail;
|
return detail;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue