From 9f9837f23712df0e51d009baeadb3053fe970a37 Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Sat, 8 Jan 2022 00:33:18 -0600 Subject: [PATCH] Digital precipitation data array packet --- ...igital_precipitation_data_array_packet.hpp | 50 +++++ ...igital_precipitation_data_array_packet.cpp | 184 ++++++++++++++++++ .../source/scwx/wsr88d/rpg/packet_factory.cpp | 2 + wxdata/wxdata.cmake | 6 +- 4 files changed, 240 insertions(+), 2 deletions(-) create mode 100644 wxdata/include/scwx/wsr88d/rpg/digital_precipitation_data_array_packet.hpp create mode 100644 wxdata/source/scwx/wsr88d/rpg/digital_precipitation_data_array_packet.cpp diff --git a/wxdata/include/scwx/wsr88d/rpg/digital_precipitation_data_array_packet.hpp b/wxdata/include/scwx/wsr88d/rpg/digital_precipitation_data_array_packet.hpp new file mode 100644 index 00000000..c86ccca6 --- /dev/null +++ b/wxdata/include/scwx/wsr88d/rpg/digital_precipitation_data_array_packet.hpp @@ -0,0 +1,50 @@ +#pragma once + +#include + +#include +#include + +namespace scwx +{ +namespace wsr88d +{ +namespace rpg +{ + +class DigitalPrecipitationDataArrayPacketImpl; + +class DigitalPrecipitationDataArrayPacket : public Packet +{ +public: + explicit DigitalPrecipitationDataArrayPacket(); + ~DigitalPrecipitationDataArrayPacket(); + + DigitalPrecipitationDataArrayPacket( + const DigitalPrecipitationDataArrayPacket&) = delete; + DigitalPrecipitationDataArrayPacket& + operator=(const DigitalPrecipitationDataArrayPacket&) = delete; + + DigitalPrecipitationDataArrayPacket( + DigitalPrecipitationDataArrayPacket&&) noexcept; + DigitalPrecipitationDataArrayPacket& + operator=(DigitalPrecipitationDataArrayPacket&&) noexcept; + + uint16_t packet_code() const; + uint16_t number_of_lfm_boxes_in_row() const; + uint16_t number_of_rows() const; + + size_t data_size() const override; + + bool Parse(std::istream& is) override; + + static std::shared_ptr + Create(std::istream& is); + +private: + std::unique_ptr p; +}; + +} // namespace rpg +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/source/scwx/wsr88d/rpg/digital_precipitation_data_array_packet.cpp b/wxdata/source/scwx/wsr88d/rpg/digital_precipitation_data_array_packet.cpp new file mode 100644 index 00000000..1d0e477c --- /dev/null +++ b/wxdata/source/scwx/wsr88d/rpg/digital_precipitation_data_array_packet.cpp @@ -0,0 +1,184 @@ +#include + +#include +#include + +#include + +namespace scwx +{ +namespace wsr88d +{ +namespace rpg +{ + +static const std::string logPrefix_ = + "[scwx::wsr88d::rpg::digital_precipitation_data_array_packet] "; + +struct Row +{ + uint16_t numberOfBytes_; + std::vector run_; + std::vector level_; + + Row() : numberOfBytes_ {0}, run_ {}, level_ {} {} +}; + +class DigitalPrecipitationDataArrayPacketImpl +{ +public: + explicit DigitalPrecipitationDataArrayPacketImpl() : + packetCode_ {0}, + numberOfLfmBoxesInRow_ {0}, + numberOfRows_ {0}, + row_ {}, + dataSize_ {0} {}; + ~DigitalPrecipitationDataArrayPacketImpl() = default; + + uint16_t packetCode_; + uint16_t numberOfLfmBoxesInRow_; + uint16_t numberOfRows_; + + // Repeat for each row + std::vector row_; + + size_t dataSize_; +}; + +DigitalPrecipitationDataArrayPacket::DigitalPrecipitationDataArrayPacket() : + p(std::make_unique()) +{ +} +DigitalPrecipitationDataArrayPacket::~DigitalPrecipitationDataArrayPacket() = + default; + +DigitalPrecipitationDataArrayPacket::DigitalPrecipitationDataArrayPacket( + DigitalPrecipitationDataArrayPacket&&) noexcept = default; +DigitalPrecipitationDataArrayPacket& +DigitalPrecipitationDataArrayPacket::operator =( + DigitalPrecipitationDataArrayPacket&&) noexcept = default; + +uint16_t DigitalPrecipitationDataArrayPacket::packet_code() const +{ + return p->packetCode_; +} + +uint16_t DigitalPrecipitationDataArrayPacket::number_of_lfm_boxes_in_row() const +{ + return p->numberOfLfmBoxesInRow_; +} + +uint16_t DigitalPrecipitationDataArrayPacket::number_of_rows() const +{ + return p->numberOfRows_; +} + +size_t DigitalPrecipitationDataArrayPacket::data_size() const +{ + return p->dataSize_; +} + +bool DigitalPrecipitationDataArrayPacket::Parse(std::istream& is) +{ + bool blockValid = true; + size_t bytesRead = 0; + + is.read(reinterpret_cast(&p->packetCode_), 2); + is.seekg(4, std::ios_base::cur); + is.read(reinterpret_cast(&p->numberOfLfmBoxesInRow_), 2); + is.read(reinterpret_cast(&p->numberOfRows_), 2); + bytesRead += 10; + + p->packetCode_ = ntohs(p->packetCode_); + p->numberOfLfmBoxesInRow_ = ntohs(p->numberOfLfmBoxesInRow_); + p->numberOfRows_ = ntohs(p->numberOfRows_); + + if (is.eof()) + { + BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Reached end of file"; + blockValid = false; + } + else + { + if (p->packetCode_ != 17) + { + BOOST_LOG_TRIVIAL(warning) + << logPrefix_ << "Invalid packet code: " << p->packetCode_; + blockValid = false; + } + if (p->numberOfRows_ != 131) + { + BOOST_LOG_TRIVIAL(warning) + << logPrefix_ << "Invalid number of rows: " << p->numberOfRows_; + blockValid = false; + } + } + + if (blockValid) + { + p->row_.resize(p->numberOfRows_); + + for (uint16_t r = 0; r < p->numberOfRows_; r++) + { + size_t rowBytesRead = 0; + + Row& row = p->row_[r]; + + is.read(reinterpret_cast(&row.numberOfBytes_), 2); + bytesRead += 2; + + row.numberOfBytes_ = ntohs(row.numberOfBytes_); + + if (row.numberOfBytes_ < 2 || row.numberOfBytes_ > 262 || + row.numberOfBytes_ % 2 != 0) + { + BOOST_LOG_TRIVIAL(warning) + << logPrefix_ + << "Invalid number of bytes in row: " << row.numberOfBytes_ + << " (Row " << r << ")"; + blockValid = false; + break; + } + + // Read row data + size_t recordCount = row.numberOfBytes_ / 2; + row.run_.resize(recordCount); + row.level_.resize(recordCount); + + for (size_t i = 0; i < recordCount; i++) + { + is.read(reinterpret_cast(&row.run_[i]), 1); + is.read(reinterpret_cast(&row.level_[i]), 1); + } + + bytesRead += row.numberOfBytes_; + } + } + + p->dataSize_ = bytesRead; + + if (!ValidateMessage(is, bytesRead)) + { + blockValid = false; + } + + return blockValid; +} + +std::shared_ptr +DigitalPrecipitationDataArrayPacket::Create(std::istream& is) +{ + std::shared_ptr packet = + std::make_shared(); + + if (!packet->Parse(is)) + { + packet.reset(); + } + + return packet; +} + +} // namespace rpg +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/source/scwx/wsr88d/rpg/packet_factory.cpp b/wxdata/source/scwx/wsr88d/rpg/packet_factory.cpp index ed02c776..37a0b984 100644 --- a/wxdata/source/scwx/wsr88d/rpg/packet_factory.cpp +++ b/wxdata/source/scwx/wsr88d/rpg/packet_factory.cpp @@ -1,5 +1,6 @@ #include +#include #include #include #include @@ -33,6 +34,7 @@ static const std::unordered_map create_ { {8, TextAndSpecialSymbolPacket::Create}, {9, LinkedVectorPacket::Create}, {10, UnlinkedVectorPacket::Create}, + {17, DigitalPrecipitationDataArrayPacket::Create}, {0x0802, SetColorLevelPacket::Create}, {0x0E03, LinkedContourVectorPacket::Create}, {0x3501, UnlinkedContourVectorPacket::Create}, diff --git a/wxdata/wxdata.cmake b/wxdata/wxdata.cmake index 30ef1e41..92bcce27 100644 --- a/wxdata/wxdata.cmake +++ b/wxdata/wxdata.cmake @@ -46,7 +46,8 @@ set(SRC_WSR88D_RDA source/scwx/wsr88d/rda/clutter_filter_map.cpp source/scwx/wsr88d/rda/rda_adaptation_data.cpp source/scwx/wsr88d/rda/rda_status_data.cpp source/scwx/wsr88d/rda/volume_coverage_pattern_data.cpp) -set(HDR_WSR88D_RPG include/scwx/wsr88d/rpg/level3_message_header.hpp +set(HDR_WSR88D_RPG include/scwx/wsr88d/rpg/digital_precipitation_data_array_packet.hpp + include/scwx/wsr88d/rpg/level3_message_header.hpp include/scwx/wsr88d/rpg/linked_contour_vector_packet.hpp include/scwx/wsr88d/rpg/linked_vector_packet.hpp include/scwx/wsr88d/rpg/packet.hpp @@ -60,7 +61,8 @@ set(HDR_WSR88D_RPG include/scwx/wsr88d/rpg/level3_message_header.hpp include/scwx/wsr88d/rpg/unlinked_contour_vector_packet.hpp include/scwx/wsr88d/rpg/unlinked_vector_packet.hpp include/scwx/wsr88d/rpg/wmo_header.hpp) -set(SRC_WSR88D_RPG source/scwx/wsr88d/rpg/level3_message_header.cpp +set(SRC_WSR88D_RPG source/scwx/wsr88d/rpg/digital_precipitation_data_array_packet.cpp + source/scwx/wsr88d/rpg/level3_message_header.cpp source/scwx/wsr88d/rpg/linked_contour_vector_packet.cpp source/scwx/wsr88d/rpg/linked_vector_packet.cpp source/scwx/wsr88d/rpg/packet.cpp