From 6544b9df74b402b4e22e39c5df8d7a9396841a9d Mon Sep 17 00:00:00 2001 From: Dan Paulat Date: Tue, 28 Dec 2021 15:46:49 -0600 Subject: [PATCH] Initial product symbology block implementation, missing packet support --- .../wsr88d/rpg/product_symbology_block.hpp | 43 ++++++ .../wsr88d/rpg/product_description_block.cpp | 8 + .../wsr88d/rpg/product_symbology_block.cpp | 138 ++++++++++++++++++ 3 files changed, 189 insertions(+) create mode 100644 wxdata/include/scwx/wsr88d/rpg/product_symbology_block.hpp create mode 100644 wxdata/source/scwx/wsr88d/rpg/product_symbology_block.cpp diff --git a/wxdata/include/scwx/wsr88d/rpg/product_symbology_block.hpp b/wxdata/include/scwx/wsr88d/rpg/product_symbology_block.hpp new file mode 100644 index 00000000..14527720 --- /dev/null +++ b/wxdata/include/scwx/wsr88d/rpg/product_symbology_block.hpp @@ -0,0 +1,43 @@ +#pragma once + +#include + +#include +#include + +namespace scwx +{ +namespace wsr88d +{ +namespace rpg +{ + +class ProductSymbologyBlockImpl; + +class ProductSymbologyBlock : public Message +{ +public: + explicit ProductSymbologyBlock(); + ~ProductSymbologyBlock(); + + ProductSymbologyBlock(const ProductSymbologyBlock&) = delete; + ProductSymbologyBlock& operator=(const ProductSymbologyBlock&) = delete; + + ProductSymbologyBlock(ProductSymbologyBlock&&) noexcept; + ProductSymbologyBlock& operator=(ProductSymbologyBlock&&) noexcept; + + int16_t block_divider() const; + + size_t data_size() const override; + + bool Parse(std::istream& is); + + static constexpr size_t SIZE = 102u; + +private: + std::unique_ptr p; +}; + +} // namespace rpg +} // namespace wsr88d +} // namespace scwx diff --git a/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp b/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp index afd70106..68bbf4e4 100644 --- a/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp +++ b/wxdata/source/scwx/wsr88d/rpg/product_description_block.cpp @@ -212,6 +212,8 @@ bool ProductDescriptionBlock::Parse(std::istream& is) { bool blockValid = true; + const std::streampos blockStart = is.tellg(); + is.read(reinterpret_cast(&p->blockDivider_), 2); // 10 is.read(reinterpret_cast(&p->latitudeOfRadar_), 4); // 11-12 is.read(reinterpret_cast(&p->longitudeOfRadar_), 4); // 13-14 @@ -297,6 +299,12 @@ bool ProductDescriptionBlock::Parse(std::istream& is) << logPrefix_ << "Product code: " << p->productCode_; } + const std::streampos blockEnd = is.tellg(); + if (!ValidateMessage(is, blockEnd - blockStart)) + { + blockValid = false; + } + return blockValid; } diff --git a/wxdata/source/scwx/wsr88d/rpg/product_symbology_block.cpp b/wxdata/source/scwx/wsr88d/rpg/product_symbology_block.cpp new file mode 100644 index 00000000..3114ffbc --- /dev/null +++ b/wxdata/source/scwx/wsr88d/rpg/product_symbology_block.cpp @@ -0,0 +1,138 @@ +#include + +#include +#include + +#include + +namespace scwx +{ +namespace wsr88d +{ +namespace rpg +{ + +static const std::string logPrefix_ = + "[scwx::wsr88d::rpg::product_symbology_block] "; + +class ProductSymbologyBlockImpl +{ +public: + explicit ProductSymbologyBlockImpl() : + blockDivider_ {}, blockId_ {}, lengthOfBlock_ {}, numberOfLayers_ {} {}; + ~ProductSymbologyBlockImpl() = default; + + int16_t blockDivider_; + int16_t blockId_; + uint32_t lengthOfBlock_; + uint16_t numberOfLayers_; +}; + +ProductSymbologyBlock::ProductSymbologyBlock() : + Message(), p(std::make_unique()) +{ +} +ProductSymbologyBlock::~ProductSymbologyBlock() = default; + +ProductSymbologyBlock::ProductSymbologyBlock(ProductSymbologyBlock&&) noexcept = + default; +ProductSymbologyBlock& +ProductSymbologyBlock::operator=(ProductSymbologyBlock&&) noexcept = default; + +int16_t ProductSymbologyBlock::block_divider() const +{ + return p->blockDivider_; +} + +size_t ProductSymbologyBlock::data_size() const +{ + return p->lengthOfBlock_; +} + +bool ProductSymbologyBlock::Parse(std::istream& is) +{ + bool blockValid = true; + + const std::streampos blockStart = is.tellg(); + + is.read(reinterpret_cast(&p->blockDivider_), 2); + is.read(reinterpret_cast(&p->blockId_), 2); + is.read(reinterpret_cast(&p->lengthOfBlock_), 4); + is.read(reinterpret_cast(&p->numberOfLayers_), 2); + + p->blockDivider_ = ntohs(p->blockDivider_); + p->blockId_ = ntohs(p->blockId_); + p->lengthOfBlock_ = ntohl(p->lengthOfBlock_); + p->numberOfLayers_ = ntohs(p->numberOfLayers_); + + if (is.eof()) + { + BOOST_LOG_TRIVIAL(debug) << logPrefix_ << "Reached end of file"; + blockValid = false; + } + else + { + if (p->blockDivider_ != -1) + { + BOOST_LOG_TRIVIAL(warning) + << logPrefix_ << "Invalid block divider: " << p->blockDivider_; + blockValid = false; + } + if (p->blockId_ != 1) + { + BOOST_LOG_TRIVIAL(warning) + << logPrefix_ << "Invalid block ID: " << p->blockId_; + blockValid = false; + } + if (p->lengthOfBlock_ < 10) + { + BOOST_LOG_TRIVIAL(warning) + << logPrefix_ << "Invalid block length: " << p->lengthOfBlock_; + blockValid = false; + } + if (p->numberOfLayers_ < 1 || p->numberOfLayers_ > 18) + { + BOOST_LOG_TRIVIAL(warning) + << logPrefix_ << "Invalid number of layers: " << p->numberOfLayers_; + blockValid = false; + } + } + + if (blockValid) + { + int16_t layerDivider; + uint32_t lengthOfDataLayer; + uint16_t packetCode; + + for (uint16_t i = 0; i < p->numberOfLayers_; i++) + { + is.read(reinterpret_cast(&layerDivider), 2); + is.read(reinterpret_cast(&lengthOfDataLayer), 4); + + layerDivider = ntohs(layerDivider); + lengthOfDataLayer = ntohl(lengthOfDataLayer); + + is.read(reinterpret_cast(&packetCode), 2); + packetCode = ntohs(packetCode); + is.seekg(-2, std::ios_base::cur); + + BOOST_LOG_TRIVIAL(debug) + << logPrefix_ << "Reading packet: " << packetCode; + + // TODO: Read packets + is.seekg(lengthOfDataLayer, std::ios_base::cur); + } + } + + const std::streampos blockEnd = is.tellg(); + if (!ValidateMessage(is, blockEnd - blockStart)) + { + blockValid = false; + } + + return blockValid; +} + +} // namespace rpg +} // namespace wsr88d +} // namespace scwx