Digital radial data array packet

This commit is contained in:
Dan Paulat 2022-01-08 18:19:00 -06:00
parent 1fbb5e5387
commit f1472275bc
4 changed files with 290 additions and 0 deletions

View file

@ -0,0 +1,234 @@
#include <scwx/wsr88d/rpg/digital_radial_data_array_packet.hpp>
#include <istream>
#include <string>
#include <boost/log/trivial.hpp>
namespace scwx
{
namespace wsr88d
{
namespace rpg
{
static const std::string logPrefix_ =
"[scwx::wsr88d::rpg::digital_radial_data_array_packet] ";
class DigitalRadialDataArrayPacketImpl
{
public:
struct Radial
{
uint16_t numberOfBytes_;
uint16_t startAngle_;
uint16_t deltaAngle_;
std::vector<uint8_t> level_;
Radial() : numberOfBytes_ {0}, startAngle_ {0}, deltaAngle_ {0}, level_ {}
{
}
};
explicit DigitalRadialDataArrayPacketImpl() :
packetCode_ {0},
indexOfFirstRangeBin_ {0},
numberOfRangeBins_ {0},
iCenterOfSweep_ {0},
jCenterOfSweep_ {0},
rangeScaleFactor_ {0},
radial_ {},
dataSize_ {0}
{
}
~DigitalRadialDataArrayPacketImpl() = default;
uint16_t packetCode_;
uint16_t indexOfFirstRangeBin_;
uint16_t numberOfRangeBins_;
int16_t iCenterOfSweep_;
int16_t jCenterOfSweep_;
uint16_t rangeScaleFactor_;
uint16_t numberOfRadials_;
// Repeat for each radial
std::vector<Radial> radial_;
size_t dataSize_;
};
DigitalRadialDataArrayPacket::DigitalRadialDataArrayPacket() :
p(std::make_unique<DigitalRadialDataArrayPacketImpl>())
{
}
DigitalRadialDataArrayPacket::~DigitalRadialDataArrayPacket() = default;
DigitalRadialDataArrayPacket::DigitalRadialDataArrayPacket(
DigitalRadialDataArrayPacket&&) noexcept = default;
DigitalRadialDataArrayPacket& DigitalRadialDataArrayPacket::operator=(
DigitalRadialDataArrayPacket&&) noexcept = default;
uint16_t DigitalRadialDataArrayPacket::packet_code() const
{
return p->packetCode_;
}
uint16_t DigitalRadialDataArrayPacket::index_of_first_range_bin() const
{
return p->indexOfFirstRangeBin_;
}
uint16_t DigitalRadialDataArrayPacket::number_of_range_bins() const
{
return p->numberOfRangeBins_;
}
int16_t DigitalRadialDataArrayPacket::i_center_of_sweep() const
{
return p->iCenterOfSweep_;
}
int16_t DigitalRadialDataArrayPacket::j_center_of_sweep() const
{
return p->jCenterOfSweep_;
}
float DigitalRadialDataArrayPacket::range_scale_factor() const
{
return p->rangeScaleFactor_ * 0.001f;
}
uint16_t DigitalRadialDataArrayPacket::number_of_radials() const
{
return p->numberOfRadials_;
}
size_t DigitalRadialDataArrayPacket::data_size() const
{
return p->dataSize_;
}
bool DigitalRadialDataArrayPacket::Parse(std::istream& is)
{
bool blockValid = true;
size_t bytesRead = 0;
is.read(reinterpret_cast<char*>(&p->packetCode_), 2);
is.read(reinterpret_cast<char*>(&p->indexOfFirstRangeBin_), 2);
is.read(reinterpret_cast<char*>(&p->numberOfRangeBins_), 2);
is.read(reinterpret_cast<char*>(&p->iCenterOfSweep_), 2);
is.read(reinterpret_cast<char*>(&p->jCenterOfSweep_), 2);
is.read(reinterpret_cast<char*>(&p->rangeScaleFactor_), 2);
is.read(reinterpret_cast<char*>(&p->numberOfRadials_), 2);
bytesRead += 14;
p->packetCode_ = ntohs(p->packetCode_);
p->indexOfFirstRangeBin_ = ntohs(p->indexOfFirstRangeBin_);
p->numberOfRangeBins_ = ntohs(p->numberOfRangeBins_);
p->iCenterOfSweep_ = ntohs(p->iCenterOfSweep_);
p->jCenterOfSweep_ = ntohs(p->jCenterOfSweep_);
p->rangeScaleFactor_ = ntohs(p->rangeScaleFactor_);
p->numberOfRadials_ = ntohs(p->numberOfRadials_);
if (is.eof())
{
BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Reached end of file";
blockValid = false;
}
else
{
if (p->packetCode_ != 16)
{
BOOST_LOG_TRIVIAL(warning)
<< logPrefix_ << "Invalid packet code: " << p->packetCode_;
blockValid = false;
}
if (p->numberOfRangeBins_ < 0 || p->numberOfRangeBins_ > 1840)
{
BOOST_LOG_TRIVIAL(warning)
<< logPrefix_
<< "Invalid number of range bins: " << p->numberOfRangeBins_;
blockValid = false;
}
if (p->numberOfRadials_ < 1 || p->numberOfRadials_ > 720)
{
BOOST_LOG_TRIVIAL(warning)
<< logPrefix_
<< "Invalid number of radials: " << p->numberOfRadials_;
blockValid = false;
}
}
if (blockValid)
{
p->radial_.resize(p->numberOfRadials_);
for (uint16_t r = 0; r < p->numberOfRadials_; r++)
{
auto& radial = p->radial_[r];
is.read(reinterpret_cast<char*>(&radial.numberOfBytes_), 2);
is.read(reinterpret_cast<char*>(&radial.startAngle_), 2);
is.read(reinterpret_cast<char*>(&radial.deltaAngle_), 2);
bytesRead += 6;
radial.numberOfBytes_ = ntohs(radial.numberOfBytes_);
radial.startAngle_ = ntohs(radial.startAngle_);
radial.deltaAngle_ = ntohs(radial.deltaAngle_);
if (radial.numberOfBytes_ < 1 || radial.numberOfBytes_ > 1840)
{
BOOST_LOG_TRIVIAL(warning)
<< logPrefix_
<< "Invalid number of bytes: " << radial.numberOfBytes_
<< " (Radial " << r << ")";
blockValid = false;
break;
}
else if (radial.numberOfBytes_ < p->numberOfRangeBins_)
{
BOOST_LOG_TRIVIAL(warning)
<< logPrefix_ << "Number of bytes < number of range bins: "
<< radial.numberOfBytes_ << " < " << p->numberOfRangeBins_
<< " (Radial " << r << ")";
blockValid = false;
break;
}
// Read radial bins
size_t dataSize = p->numberOfRangeBins_;
radial.level_.resize(dataSize);
is.read(reinterpret_cast<char*>(radial.level_.data()), dataSize);
is.seekg(radial.numberOfBytes_ - dataSize, std::ios_base::cur);
bytesRead += radial.numberOfBytes_;
}
}
p->dataSize_ = bytesRead;
if (!ValidateMessage(is, bytesRead))
{
blockValid = false;
}
return blockValid;
}
std::shared_ptr<DigitalRadialDataArrayPacket>
DigitalRadialDataArrayPacket::Create(std::istream& is)
{
std::shared_ptr<DigitalRadialDataArrayPacket> packet =
std::make_shared<DigitalRadialDataArrayPacket>();
if (!packet->Parse(is))
{
packet.reset();
}
return packet;
}
} // namespace rpg
} // namespace wsr88d
} // namespace scwx

View file

@ -1,6 +1,7 @@
#include <scwx/wsr88d/rpg/packet_factory.hpp>
#include <scwx/wsr88d/rpg/digital_precipitation_data_array_packet.hpp>
#include <scwx/wsr88d/rpg/digital_radial_data_array_packet.hpp>
#include <scwx/wsr88d/rpg/linked_contour_vector_packet.hpp>
#include <scwx/wsr88d/rpg/linked_vector_packet.hpp>
#include <scwx/wsr88d/rpg/precipitation_rate_data_array_packet.hpp>
@ -35,6 +36,7 @@ static const std::unordered_map<uint16_t, CreateMessageFunction> create_ {
{8, TextAndSpecialSymbolPacket::Create},
{9, LinkedVectorPacket::Create},
{10, UnlinkedVectorPacket::Create},
{16, DigitalRadialDataArrayPacket::Create},
{17, DigitalPrecipitationDataArrayPacket::Create},
{18, PrecipitationRateDataArrayPacket::Create},
{0x0802, SetColorLevelPacket::Create},