diff --git a/src/blackcore/weathermanager.cpp b/src/blackcore/weathermanager.cpp index caa7cd804..0603a6e64 100644 --- a/src/blackcore/weathermanager.cpp +++ b/src/blackcore/weathermanager.cpp @@ -71,6 +71,17 @@ namespace BlackCore void CWeatherManager::requestWeatherGrid(const CWeatherGrid &initialWeatherGrid, const CIdentifier &identifier) { + if (identifier.isNull() || initialWeatherGrid.isEmpty() || initialWeatherGrid.frontOrDefault().getPosition().isNull()) + { + if (CBuildConfig::isLocalDeveloperDebugBuild()) + { + BLACK_VERIFY_X(!identifier.isNull(), Q_FUNC_INFO, "Missing callback"); + BLACK_VERIFY_X(!initialWeatherGrid.isEmpty(), Q_FUNC_INFO, "Empty grid, need position"); + BLACK_VERIFY_X(!initialWeatherGrid.frontOrDefault().getPosition().isNull(), Q_FUNC_INFO, "NULL position"); + } + return; + } + const WeatherRequest weatherRequest { {}, identifier, initialWeatherGrid, {} }; this->appendRequest(weatherRequest); @@ -81,8 +92,16 @@ namespace BlackCore void CWeatherManager::requestWeatherGrid(const CWeatherGrid &initialWeatherGrid, const CSlot &callback) { - BLACK_VERIFY_X(callback, Q_FUNC_INFO, "Missing callback"); - if (!callback) { return; } + if (!callback || initialWeatherGrid.isEmpty() || initialWeatherGrid.frontOrDefault().getPosition().isNull()) + { + if (CBuildConfig::isLocalDeveloperDebugBuild()) + { + BLACK_VERIFY_X(callback, Q_FUNC_INFO, "Missing callback"); + BLACK_VERIFY_X(!initialWeatherGrid.isEmpty(), Q_FUNC_INFO, "Empty grid, need position"); + BLACK_VERIFY_X(!initialWeatherGrid.frontOrDefault().getPosition().isNull(), Q_FUNC_INFO, "NULL position"); + } + return; + } if (m_isWeatherClear) { diff --git a/src/plugins/weatherdata/gfs/gfs.pro b/src/plugins/weatherdata/gfs/gfs.pro index a81cb17f2..a3bae7e44 100644 --- a/src/plugins/weatherdata/gfs/gfs.pro +++ b/src/plugins/weatherdata/gfs/gfs.pro @@ -6,7 +6,7 @@ TARGET = weatherdatagfs TEMPLATE = lib CONFIG += plugin shared -CONFIG += blackmisc blackcore +CONFIG += blackmisc blackcore blackconfig DEPENDPATH += . $$SourceRoot/src INCLUDEPATH += . $$SourceRoot/src diff --git a/src/plugins/weatherdata/gfs/weatherdatagfs.cpp b/src/plugins/weatherdata/gfs/weatherdatagfs.cpp index 4a0e0f226..f2343e606 100644 --- a/src/plugins/weatherdata/gfs/weatherdatagfs.cpp +++ b/src/plugins/weatherdata/gfs/weatherdatagfs.cpp @@ -8,10 +8,12 @@ #include "weatherdatagfs.h" #include "blackcore/application.h" -#include "blackmisc/logmessage.h" -#include "blackmisc/math/mathutils.h" #include "blackmisc/geo/coordinategeodetic.h" #include "blackmisc/pq/temperature.h" +#include "blackmisc/math/mathutils.h" +#include "blackmisc/verify.h" +#include "blackmisc/logmessage.h" +#include "blackconfig/buildconfig.h" #include #include @@ -19,6 +21,7 @@ #include #include +using namespace BlackConfig; using namespace BlackMisc; using namespace BlackMisc::Aviation; using namespace BlackMisc::Geo; @@ -334,6 +337,9 @@ namespace BlackWxPlugin m_gfsWeatherGrid.clear(); m_weatherGrid.clear(); + // Messages should be 76. This is a combination + // of requested values (e.g. temperature, clouds etc) at specific layers (2 mbar, 10 mbar, surface). + constexpr int maxMessages = 76; int messageNo = 0; g2int iseek = 0; for (;;) @@ -384,9 +390,18 @@ namespace BlackWxPlugin messageNo++; } - CLogMessage(this).debug() << "Parsed" << messageNo << "GRIB messages."; - CLogMessage(this).debug() << "Obtained" << m_gfsWeatherGrid.size() << "grid points."; + // validate + if (messageNo > maxMessages && CBuildConfig::isLocalDeveloperDebugBuild()) + { + // as discussed this means a format change + BLACK_VERIFY_X(false, Q_FUNC_INFO, "Format change in GRIB, too many messages"); + } + const int weatherGridPointsNo = m_gfsWeatherGrid.size(); + CLogMessage(this).debug() << "Parsed" << messageNo << "GRIB messages."; + CLogMessage(this).debug() << "Obtained" << weatherGridPointsNo << "grid points."; + + constexpr int maxPoints = 200; for (const GfsGridPoint &gfsGridPoint : as_const(m_gfsWeatherGrid)) { if (QThread::currentThread()->isInterruptionRequested()) { return false; } @@ -438,11 +453,19 @@ namespace BlackWxPlugin auto pressureAtMsl = PhysicalQuantities::CPressure { gfsGridPoint.pressureAtMsl, PhysicalQuantities::CPressureUnit::Pa() }; - CLatitude latitude(gfsGridPoint.latitude, CAngleUnit::deg()); - CLongitude longitude(gfsGridPoint.longitude, CAngleUnit::deg()); - auto position = CCoordinateGeodetic { latitude, longitude }; + const CLatitude latitude(gfsGridPoint.latitude, CAngleUnit::deg()); + const CLongitude longitude(gfsGridPoint.longitude, CAngleUnit::deg()); + const auto position = CCoordinateGeodetic { latitude, longitude }; const CGridPoint gridPoint({}, position, cloudLayers, temperatureLayers, {}, windLayers, pressureAtMsl); m_weatherGrid.push_back(gridPoint); + if (m_weatherGrid.size() >= maxPoints) + { + // too many points lead to extreme memory consumption and CPU usage + // we stop here, no use case so far in swift where we need that + BLACK_VERIFY_X(!CBuildConfig::isLocalDeveloperDebugBuild(), Q_FUNC_INFO, "Too many grid points"); + CLogMessage(this).warning(u"Too many weather grid points: %1") << m_weatherGrid.size(); + break; + } } return true; @@ -602,12 +625,18 @@ namespace BlackWxPlugin { for (const CGridPoint &fixedGridPoint : as_const(m_grid)) { - const auto distance = calculateGreatCircleDistance(gridPointPosition, fixedGridPoint.getPosition()).value(CLengthUnit::m()); - const auto maxRange = m_maxRange.value(CLengthUnit::m()); - if (distance < maxRange) + const CLength distance = calculateGreatCircleDistance(gridPointPosition, fixedGridPoint.getPosition()); + if (distance.isNull()) { - m_gfsWeatherGrid.append(gridPoint); - break; + BLACK_VERIFY_X(!CBuildConfig::isLocalDeveloperDebugBuild(), Q_FUNC_INFO, "Suspicious value, why is that?"); + } + else + { + if (distance < m_maxRange) + { + m_gfsWeatherGrid.append(gridPoint); + break; + } } } }