mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 10:10:05 +00:00 
			
		
		
		
	List NWS text products metadata
This commit is contained in:
		
							parent
							
								
									cd7435a4d5
								
							
						
					
					
						commit
						59a8fdbf56
					
				
					 2 changed files with 129 additions and 0 deletions
				
			
		|  | @ -1,6 +1,7 @@ | |||
| #pragma once | ||||
| 
 | ||||
| #include <memory> | ||||
| #include <string> | ||||
| 
 | ||||
| namespace scwx::provider | ||||
| { | ||||
|  | @ -20,6 +21,11 @@ public: | |||
|    IemWarningsProvider(IemWarningsProvider&&) noexcept; | ||||
|    IemWarningsProvider& operator=(IemWarningsProvider&&) noexcept; | ||||
| 
 | ||||
|    std::vector<std::string> | ||||
|    ListTextProducts(std::chrono::sys_time<std::chrono::days> date, | ||||
|                     std::optional<std::string_view>          cccc = {}, | ||||
|                     std::optional<std::string_view>          pil  = {}); | ||||
| 
 | ||||
| private: | ||||
|    class Impl; | ||||
|    std::unique_ptr<Impl> p; | ||||
|  |  | |||
|  | @ -1,12 +1,23 @@ | |||
| #include <scwx/provider/iem_warnings_provider.hpp> | ||||
| #include <scwx/network/cpr.hpp> | ||||
| #include <scwx/types/iem_types.hpp> | ||||
| #include <scwx/util/json.hpp> | ||||
| #include <scwx/util/logger.hpp> | ||||
| 
 | ||||
| #include <boost/json.hpp> | ||||
| #include <cpr/cpr.h> | ||||
| 
 | ||||
| namespace scwx::provider | ||||
| { | ||||
| 
 | ||||
| static const std::string logPrefix_ = "scwx::provider::iem_warnings_provider"; | ||||
| static const auto        logger_    = util::Logger::Create(logPrefix_); | ||||
| 
 | ||||
| static const std::string kBaseUrl_ = "https://mesonet.agron.iastate.edu/api/1"; | ||||
| 
 | ||||
| static const std::string kListNwsTextProductsEndpoint_ = "/nws/afos/list.json"; | ||||
| static const std::string kNwsTextProductEndpoint_      = "/nwstext/"; | ||||
| 
 | ||||
| class IemWarningsProvider::Impl | ||||
| { | ||||
| public: | ||||
|  | @ -16,6 +27,11 @@ public: | |||
|    Impl& operator=(const Impl&)  = delete; | ||||
|    Impl(const Impl&&)            = delete; | ||||
|    Impl& operator=(const Impl&&) = delete; | ||||
| 
 | ||||
|    std::vector<std::string> | ||||
|    ListTextProducts(std::chrono::sys_time<std::chrono::days> date, | ||||
|                     std::optional<std::string_view>          cccc = {}, | ||||
|                     std::optional<std::string_view>          pil  = {}); | ||||
| }; | ||||
| 
 | ||||
| IemWarningsProvider::IemWarningsProvider() : p(std::make_unique<Impl>()) {} | ||||
|  | @ -26,4 +42,111 @@ IemWarningsProvider::IemWarningsProvider(IemWarningsProvider&&) noexcept = | |||
| IemWarningsProvider& | ||||
| IemWarningsProvider::operator=(IemWarningsProvider&&) noexcept = default; | ||||
| 
 | ||||
| std::vector<std::string> IemWarningsProvider::ListTextProducts( | ||||
|    std::chrono::sys_time<std::chrono::days> date, | ||||
|    std::optional<std::string_view>          cccc, | ||||
|    std::optional<std::string_view>          pil) | ||||
| { | ||||
|    return p->ListTextProducts(date, cccc, pil); | ||||
| } | ||||
| 
 | ||||
| std::vector<std::string> IemWarningsProvider::Impl::ListTextProducts( | ||||
|    std::chrono::sys_time<std::chrono::days> date, | ||||
|    std::optional<std::string_view>          cccc, | ||||
|    std::optional<std::string_view>          pil) | ||||
| { | ||||
|    using namespace std::chrono; | ||||
| 
 | ||||
| #if (__cpp_lib_chrono >= 201907L) | ||||
|    namespace df = std; | ||||
| 
 | ||||
|    static constexpr std::string_view kDateFormat {"{:%Y-%m-%d}"}; | ||||
| #else | ||||
|    using namespace date; | ||||
|    namespace df = date; | ||||
| 
 | ||||
| #   define kDateFormat "%Y-%m-%d" | ||||
| #endif | ||||
| 
 | ||||
|    auto parameters = cpr::Parameters {{"date", df::format(kDateFormat, date)}}; | ||||
| 
 | ||||
|    // WMO Source Code
 | ||||
|    if (cccc.has_value()) | ||||
|    { | ||||
|       parameters.Add({"cccc", std::string {cccc.value()}}); | ||||
|    } | ||||
| 
 | ||||
|    // AFOS / AWIPS ID / 3-6 length identifier
 | ||||
|    if (pil.has_value()) | ||||
|    { | ||||
|       parameters.Add({"pil", std::string {pil.value()}}); | ||||
|    } | ||||
| 
 | ||||
|    auto response = | ||||
|       cpr::Get(cpr::Url {kBaseUrl_ + kListNwsTextProductsEndpoint_}, | ||||
|                network::cpr::GetHeader(), | ||||
|                parameters); | ||||
|    boost::json::value json = util::json::ReadJsonString(response.text); | ||||
| 
 | ||||
|    std::vector<std::string> textProducts {}; | ||||
| 
 | ||||
|    if (response.status_code == cpr::status::HTTP_OK) | ||||
|    { | ||||
|       try | ||||
|       { | ||||
|          // Get AFOS list from response
 | ||||
|          auto entries = boost::json::value_to<types::iem::AfosList>(json); | ||||
| 
 | ||||
|          for (auto& entry : entries.data_) | ||||
|          { | ||||
|             textProducts.push_back(entry.productId_); | ||||
|          } | ||||
| 
 | ||||
|          logger_->trace("Found {} products", entries.data_.size()); | ||||
|       } | ||||
|       catch (const std::exception& ex) | ||||
|       { | ||||
|          // Unexpected bad response
 | ||||
|          logger_->warn("Error parsing JSON: {}", ex.what()); | ||||
|       } | ||||
|    } | ||||
|    else if (response.status_code == cpr::status::HTTP_BAD_REQUEST && | ||||
|             json != nullptr) | ||||
|    { | ||||
|       try | ||||
|       { | ||||
|          // Log bad request details
 | ||||
|          auto badRequest = boost::json::value_to<types::iem::BadRequest>(json); | ||||
|          logger_->warn("ListTextProducts bad request: {}", badRequest.detail_); | ||||
|       } | ||||
|       catch (const std::exception& ex) | ||||
|       { | ||||
|          // Unexpected bad response
 | ||||
|          logger_->warn("Error parsing bad response: {}", ex.what()); | ||||
|       } | ||||
|    } | ||||
|    else if (response.status_code == cpr::status::HTTP_UNPROCESSABLE_ENTITY && | ||||
|             json != nullptr) | ||||
|    { | ||||
|       try | ||||
|       { | ||||
|          // Log validation error details
 | ||||
|          auto error = boost::json::value_to<types::iem::ValidationError>(json); | ||||
|          logger_->warn("ListTextProducts validation error: {}", | ||||
|                        error.detail_.at(0).msg_); | ||||
|       } | ||||
|       catch (const std::exception& ex) | ||||
|       { | ||||
|          // Unexpected bad response
 | ||||
|          logger_->warn("Error parsing validation error: {}", ex.what()); | ||||
|       } | ||||
|    } | ||||
|    else | ||||
|    { | ||||
|       logger_->warn("Could not list text products: {}", response.status_line); | ||||
|    } | ||||
| 
 | ||||
|    return textProducts; | ||||
| } | ||||
| 
 | ||||
| } // namespace scwx::provider
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat