Add RdaPrfData (message type 32)

This commit is contained in:
Dan Paulat 2025-05-13 00:28:31 -05:00
parent fd6c224fc2
commit f709380a97
5 changed files with 188 additions and 3 deletions

View file

@ -121,13 +121,44 @@ public:
[](auto& p) { p.second = SwapFloat(p.second); }); [](auto& p) { p.second = SwapFloat(p.second); });
} }
static void SwapVector(std::vector<std::uint16_t>& v) template<typename T>
static void SwapVector(std::vector<T>& v)
{ {
std::transform(std::execution::par_unseq, std::transform(std::execution::par_unseq,
v.begin(), v.begin(),
v.end(), v.end(),
v.begin(), v.begin(),
[](std::uint16_t u) { return ntohs(u); }); [](T u)
{
if constexpr (std::is_same_v<T, std::uint16_t> ||
std::is_same_v<T, std::int16_t>)
{
return static_cast<T>(ntohs(u));
}
else if constexpr (std::is_same_v<T, std::uint32_t> ||
std::is_same_v<T, std::int32_t>)
{
return static_cast<T>(ntohl(u));
}
else if constexpr (std::is_same_v<T, std::uint64_t> ||
std::is_same_v<T, std::int64_t>)
{
return static_cast<T>(ntohll(u));
}
else if constexpr (std::is_same_v<T, float>)
{
return SwapFloat(u);
}
else if constexpr (std::is_same_v<T, double>)
{
return SwapDouble(u);
}
else
{
static_assert(std::is_same_v<T, void>,
"Unsupported type for SwapVector");
}
});
} }
private: private:

View file

@ -0,0 +1,30 @@
#pragma once
#include <scwx/wsr88d/rda/level2_message.hpp>
namespace scwx::wsr88d::rda
{
class RdaPrfData : public Level2Message
{
public:
explicit RdaPrfData();
~RdaPrfData();
RdaPrfData(const RdaPrfData&) = delete;
RdaPrfData& operator=(const RdaPrfData&) = delete;
RdaPrfData(RdaPrfData&&) noexcept;
RdaPrfData& operator=(RdaPrfData&&) noexcept;
bool Parse(std::istream& is) override;
static std::shared_ptr<RdaPrfData> Create(Level2MessageHeader&& header,
std::istream& is);
private:
class Impl;
std::unique_ptr<Impl> p;
};
} // namespace scwx::wsr88d::rda

View file

@ -8,6 +8,7 @@
#include <scwx/wsr88d/rda/digital_radar_data_generic.hpp> #include <scwx/wsr88d/rda/digital_radar_data_generic.hpp>
#include <scwx/wsr88d/rda/performance_maintenance_data.hpp> #include <scwx/wsr88d/rda/performance_maintenance_data.hpp>
#include <scwx/wsr88d/rda/rda_adaptation_data.hpp> #include <scwx/wsr88d/rda/rda_adaptation_data.hpp>
#include <scwx/wsr88d/rda/rda_prf_data.hpp>
#include <scwx/wsr88d/rda/rda_status_data.hpp> #include <scwx/wsr88d/rda/rda_status_data.hpp>
#include <scwx/wsr88d/rda/volume_coverage_pattern_data.hpp> #include <scwx/wsr88d/rda/volume_coverage_pattern_data.hpp>
@ -37,7 +38,8 @@ static const std::unordered_map<unsigned int, CreateLevel2MessageFunction>
{13, ClutterFilterBypassMap::Create}, {13, ClutterFilterBypassMap::Create},
{15, ClutterFilterMap::Create}, {15, ClutterFilterMap::Create},
{18, RdaAdaptationData::Create}, {18, RdaAdaptationData::Create},
{31, DigitalRadarDataGeneric::Create}}; {31, DigitalRadarDataGeneric::Create},
{32, RdaPrfData::Create}};
struct Level2MessageFactory::Context struct Level2MessageFactory::Context
{ {

View file

@ -0,0 +1,120 @@
#include <scwx/wsr88d/rda/rda_prf_data.hpp>
#include <scwx/util/logger.hpp>
namespace scwx::wsr88d::rda
{
static const std::string logPrefix_ = "scwx::wsr88d::rda::rda_prf_data";
static const auto logger_ = scwx::util::Logger::Create(logPrefix_);
struct RdaPrfWaveformData
{
std::uint16_t waveformType_ {0};
std::uint16_t prfCount_ {0};
std::vector<std::uint32_t> prfValues_ {};
};
class RdaPrfData::Impl
{
public:
explicit Impl() = default;
~Impl() = default;
Impl(const Impl&) = delete;
Impl& operator=(const Impl&) = delete;
Impl(const Impl&&) = delete;
Impl& operator=(const Impl&&) = delete;
std::uint16_t numberOfWaveforms_ {0};
std::vector<RdaPrfWaveformData> waveformData_ {};
};
RdaPrfData::RdaPrfData() : p(std::make_unique<Impl>()) {}
RdaPrfData::~RdaPrfData() = default;
RdaPrfData::RdaPrfData(RdaPrfData&&) noexcept = default;
RdaPrfData& RdaPrfData::operator=(RdaPrfData&&) noexcept = default;
bool RdaPrfData::Parse(std::istream& is)
{
logger_->trace("Parsing RDA PRF Data (Message Type 32)");
bool messageValid = true;
std::size_t bytesRead = 0;
std::streampos isBegin = is.tellg();
is.read(reinterpret_cast<char*>(&p->numberOfWaveforms_), 2); // 1
is.seekg(2, std::ios_base::cur); // 2
bytesRead += 4;
p->numberOfWaveforms_ = ntohs(p->numberOfWaveforms_);
// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers): Readability
if (p->numberOfWaveforms_ < 1 || p->numberOfWaveforms_ > 5)
{
logger_->warn("Invalid number of waveforms: {}", p->numberOfWaveforms_);
p->numberOfWaveforms_ = 0;
messageValid = false;
}
p->waveformData_.resize(p->numberOfWaveforms_);
for (std::uint16_t i = 0; i < p->numberOfWaveforms_; ++i)
{
auto& w = p->waveformData_[i];
is.read(reinterpret_cast<char*>(&w.waveformType_), 2); // P1
is.read(reinterpret_cast<char*>(&w.prfCount_), 2); // P2
w.waveformType_ = ntohs(w.waveformType_);
w.prfCount_ = ntohs(w.prfCount_);
bytesRead += 4;
// NOLINTNEXTLINE(cppcoreguidelines-avoid-magic-numbers): Readability
if (w.prfCount_ > 255)
{
logger_->warn("Invalid PRF count: {} (waveform {})", w.prfCount_, i);
w.prfCount_ = 0;
messageValid = false;
break;
}
w.prfValues_.resize(w.prfCount_);
for (std::uint16_t j = 0; j < w.prfCount_; ++j)
{
is.read(reinterpret_cast<char*>(&w.prfValues_[j]), 4);
}
bytesRead += static_cast<std::size_t>(w.prfCount_) * 4;
SwapVector(w.prfValues_);
}
is.seekg(isBegin, std::ios_base::beg);
if (!ValidateMessage(is, bytesRead))
{
messageValid = false;
}
return messageValid;
}
std::shared_ptr<RdaPrfData> RdaPrfData::Create(Level2MessageHeader&& header,
std::istream& is)
{
std::shared_ptr<RdaPrfData> message = std::make_shared<RdaPrfData>();
message->set_header(std::move(header));
if (!message->Parse(is))
{
message.reset();
}
return message;
}
} // namespace scwx::wsr88d::rda

View file

@ -125,6 +125,7 @@ set(HDR_WSR88D_RDA include/scwx/wsr88d/rda/clutter_filter_bypass_map.hpp
include/scwx/wsr88d/rda/level2_message_header.hpp include/scwx/wsr88d/rda/level2_message_header.hpp
include/scwx/wsr88d/rda/performance_maintenance_data.hpp include/scwx/wsr88d/rda/performance_maintenance_data.hpp
include/scwx/wsr88d/rda/rda_adaptation_data.hpp include/scwx/wsr88d/rda/rda_adaptation_data.hpp
include/scwx/wsr88d/rda/rda_prf_data.hpp
include/scwx/wsr88d/rda/rda_status_data.hpp include/scwx/wsr88d/rda/rda_status_data.hpp
include/scwx/wsr88d/rda/rda_types.hpp include/scwx/wsr88d/rda/rda_types.hpp
include/scwx/wsr88d/rda/volume_coverage_pattern_data.hpp) include/scwx/wsr88d/rda/volume_coverage_pattern_data.hpp)
@ -138,6 +139,7 @@ set(SRC_WSR88D_RDA source/scwx/wsr88d/rda/clutter_filter_bypass_map.cpp
source/scwx/wsr88d/rda/level2_message_header.cpp source/scwx/wsr88d/rda/level2_message_header.cpp
source/scwx/wsr88d/rda/performance_maintenance_data.cpp source/scwx/wsr88d/rda/performance_maintenance_data.cpp
source/scwx/wsr88d/rda/rda_adaptation_data.cpp source/scwx/wsr88d/rda/rda_adaptation_data.cpp
source/scwx/wsr88d/rda/rda_prf_data.cpp
source/scwx/wsr88d/rda/rda_status_data.cpp source/scwx/wsr88d/rda/rda_status_data.cpp
source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp) source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp)
set(HDR_WSR88D_RPG include/scwx/wsr88d/rpg/ccb_header.hpp set(HDR_WSR88D_RPG include/scwx/wsr88d/rpg/ccb_header.hpp