mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-10-30 21:10:04 +00:00
243 lines
5.4 KiB
C++
243 lines
5.4 KiB
C++
#include <scwx/awips/wmo_header.hpp>
|
|
#include <scwx/util/logger.hpp>
|
|
#include <scwx/util/streams.hpp>
|
|
|
|
#include <istream>
|
|
#include <sstream>
|
|
#include <string>
|
|
|
|
#ifdef _WIN32
|
|
# include <WinSock2.h>
|
|
#else
|
|
# include <arpa/inet.h>
|
|
#endif
|
|
|
|
namespace scwx
|
|
{
|
|
namespace awips
|
|
{
|
|
|
|
static const std::string logPrefix_ = "scwx::awips::wmo_header";
|
|
static const auto logger_ = util::Logger::Create(logPrefix_);
|
|
|
|
class WmoHeaderImpl
|
|
{
|
|
public:
|
|
explicit WmoHeaderImpl() :
|
|
sequenceNumber_ {},
|
|
dataType_ {},
|
|
geographicDesignator_ {},
|
|
bulletinId_ {},
|
|
icao_ {},
|
|
dateTime_ {},
|
|
bbbIndicator_ {},
|
|
productCategory_ {},
|
|
productDesignator_ {}
|
|
{
|
|
}
|
|
~WmoHeaderImpl() = default;
|
|
|
|
bool operator==(const WmoHeaderImpl& o) const;
|
|
|
|
std::string sequenceNumber_;
|
|
std::string dataType_;
|
|
std::string geographicDesignator_;
|
|
std::string bulletinId_;
|
|
std::string icao_;
|
|
std::string dateTime_;
|
|
std::string bbbIndicator_;
|
|
std::string productCategory_;
|
|
std::string productDesignator_;
|
|
};
|
|
|
|
WmoHeader::WmoHeader() : p(std::make_unique<WmoHeaderImpl>()) {}
|
|
WmoHeader::~WmoHeader() = default;
|
|
|
|
WmoHeader::WmoHeader(WmoHeader&&) noexcept = default;
|
|
WmoHeader& WmoHeader::operator=(WmoHeader&&) noexcept = default;
|
|
|
|
bool WmoHeader::operator==(const WmoHeader& o) const
|
|
{
|
|
return (*p.get() == *o.p.get());
|
|
}
|
|
|
|
bool WmoHeaderImpl::operator==(const WmoHeaderImpl& o) const
|
|
{
|
|
return (sequenceNumber_ == o.sequenceNumber_ && //
|
|
dataType_ == o.dataType_ && //
|
|
geographicDesignator_ == o.geographicDesignator_ && //
|
|
bulletinId_ == o.bulletinId_ && //
|
|
icao_ == o.icao_ && //
|
|
dateTime_ == o.dateTime_ && //
|
|
bbbIndicator_ == o.bbbIndicator_ && //
|
|
productCategory_ == o.productCategory_ && //
|
|
productDesignator_ == o.productDesignator_);
|
|
}
|
|
|
|
std::string WmoHeader::sequence_number() const
|
|
{
|
|
return p->sequenceNumber_;
|
|
}
|
|
|
|
std::string WmoHeader::data_type() const
|
|
{
|
|
return p->dataType_;
|
|
}
|
|
|
|
std::string WmoHeader::geographic_designator() const
|
|
{
|
|
return p->geographicDesignator_;
|
|
}
|
|
|
|
std::string WmoHeader::bulletin_id() const
|
|
{
|
|
return p->bulletinId_;
|
|
}
|
|
|
|
std::string WmoHeader::icao() const
|
|
{
|
|
return p->icao_;
|
|
}
|
|
|
|
std::string WmoHeader::date_time() const
|
|
{
|
|
return p->dateTime_;
|
|
}
|
|
|
|
std::string WmoHeader::bbb_indicator() const
|
|
{
|
|
return p->bbbIndicator_;
|
|
}
|
|
|
|
std::string WmoHeader::product_category() const
|
|
{
|
|
return p->productCategory_;
|
|
}
|
|
|
|
std::string WmoHeader::product_designator() const
|
|
{
|
|
return p->productDesignator_;
|
|
}
|
|
|
|
bool WmoHeader::Parse(std::istream& is)
|
|
{
|
|
bool headerValid = true;
|
|
|
|
std::string sohLine;
|
|
std::string sequenceLine;
|
|
std::string wmoLine;
|
|
std::string awipsLine;
|
|
|
|
if (is.peek() == 0x01)
|
|
{
|
|
util::getline(is, sohLine);
|
|
util::getline(is, sequenceLine);
|
|
}
|
|
|
|
util::getline(is, wmoLine);
|
|
util::getline(is, awipsLine);
|
|
|
|
if (is.eof())
|
|
{
|
|
logger_->trace("Reached end of file");
|
|
headerValid = false;
|
|
}
|
|
else
|
|
{
|
|
// Remove delimiters from the end of the line
|
|
while (sequenceLine.ends_with(' '))
|
|
{
|
|
sequenceLine.erase(sequenceLine.length() - 1);
|
|
}
|
|
}
|
|
|
|
// Transmission Header:
|
|
// [SOH]
|
|
// nnn
|
|
|
|
if (headerValid && !sequenceLine.empty())
|
|
{
|
|
p->sequenceNumber_ = sequenceLine;
|
|
}
|
|
|
|
// WMO Abbreviated Heading Line:
|
|
// T1T2A1A2ii CCCC YYGGgg (BBB)
|
|
|
|
if (headerValid)
|
|
{
|
|
std::string token;
|
|
std::istringstream wmoTokens(wmoLine);
|
|
std::vector<std::string> wmoTokenList;
|
|
|
|
while (wmoTokens >> token)
|
|
{
|
|
wmoTokenList.push_back(token);
|
|
}
|
|
|
|
if (wmoTokenList.size() < 3 || wmoTokenList.size() > 4)
|
|
{
|
|
logger_->warn("Invalid number of WMO tokens");
|
|
headerValid = false;
|
|
}
|
|
else if (wmoTokenList[0].size() != 6)
|
|
{
|
|
logger_->warn("WMO identifier malformed");
|
|
headerValid = false;
|
|
}
|
|
else if (wmoTokenList[1].size() != 4)
|
|
{
|
|
logger_->warn("ICAO malformed");
|
|
headerValid = false;
|
|
}
|
|
else if (wmoTokenList[2].size() != 6)
|
|
{
|
|
logger_->warn("Date/time malformed");
|
|
headerValid = false;
|
|
}
|
|
else if (wmoTokenList.size() == 4 && wmoTokenList[3].size() != 3)
|
|
{
|
|
// BBB indicator is optional
|
|
logger_->warn("BBB indicator malformed");
|
|
headerValid = false;
|
|
}
|
|
else
|
|
{
|
|
p->dataType_ = wmoTokenList[0].substr(0, 2);
|
|
p->geographicDesignator_ = wmoTokenList[0].substr(2, 2);
|
|
p->bulletinId_ = wmoTokenList[0].substr(4, 2);
|
|
p->icao_ = wmoTokenList[1];
|
|
p->dateTime_ = wmoTokenList[2];
|
|
|
|
if (wmoTokenList.size() == 4)
|
|
{
|
|
p->bbbIndicator_ = wmoTokenList[3];
|
|
}
|
|
else
|
|
{
|
|
p->bbbIndicator_ = "";
|
|
}
|
|
}
|
|
}
|
|
|
|
// AWIPS Identifer Line:
|
|
// NNNxxx
|
|
|
|
if (headerValid)
|
|
{
|
|
if (awipsLine.size() != 6)
|
|
{
|
|
logger_->warn("AWIPS Identifier Line bad size");
|
|
headerValid = false;
|
|
}
|
|
else
|
|
{
|
|
p->productCategory_ = awipsLine.substr(0, 3);
|
|
p->productDesignator_ = awipsLine.substr(3, 3);
|
|
}
|
|
}
|
|
|
|
return headerValid;
|
|
}
|
|
|
|
} // namespace awips
|
|
} // namespace scwx
|