mirror of
				https://github.com/ciphervance/supercell-wx.git
				synced 2025-10-31 13:10:04 +00:00 
			
		
		
		
	Handle received alerts and test against location for playing alert audio
This commit is contained in:
		
							parent
							
								
									dd79f9208d
								
							
						
					
					
						commit
						40fc8ade20
					
				
					 2 changed files with 108 additions and 3 deletions
				
			
		|  | @ -1,10 +1,16 @@ | ||||||
| #include <scwx/qt/manager/alert_manager.hpp> | #include <scwx/qt/manager/alert_manager.hpp> | ||||||
|  | #include <scwx/qt/manager/media_manager.hpp> | ||||||
| #include <scwx/qt/manager/position_manager.hpp> | #include <scwx/qt/manager/position_manager.hpp> | ||||||
|  | #include <scwx/qt/manager/text_event_manager.hpp> | ||||||
| #include <scwx/qt/settings/audio_settings.hpp> | #include <scwx/qt/settings/audio_settings.hpp> | ||||||
| #include <scwx/qt/types/location_types.hpp> | #include <scwx/qt/types/location_types.hpp> | ||||||
|  | #include <scwx/qt/util/geographic_lib.hpp> | ||||||
| #include <scwx/util/logger.hpp> | #include <scwx/util/logger.hpp> | ||||||
| 
 | 
 | ||||||
|  | #include <boost/asio/post.hpp> | ||||||
|  | #include <boost/asio/thread_pool.hpp> | ||||||
| #include <boost/uuid/random_generator.hpp> | #include <boost/uuid/random_generator.hpp> | ||||||
|  | #include <QGeoPositionInfo> | ||||||
| 
 | 
 | ||||||
| namespace scwx | namespace scwx | ||||||
| { | { | ||||||
|  | @ -28,23 +34,119 @@ public: | ||||||
| 
 | 
 | ||||||
|       audioSettings.alert_location_method().RegisterValueChangedCallback( |       audioSettings.alert_location_method().RegisterValueChangedCallback( | ||||||
|          [this](const std::string& value) { UpdateLocationTracking(value); }); |          [this](const std::string& value) { UpdateLocationTracking(value); }); | ||||||
|  | 
 | ||||||
|  |       QObject::connect( | ||||||
|  |          textEventManager_.get(), | ||||||
|  |          &manager::TextEventManager::AlertUpdated, | ||||||
|  |          self_, | ||||||
|  |          [this](const types::TextEventKey& key, size_t messageIndex) | ||||||
|  |          { | ||||||
|  |             boost::asio::post(threadPool_, | ||||||
|  |                               [=, this]() { HandleAlert(key, messageIndex); }); | ||||||
|  |          }); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    ~Impl() {} |    ~Impl() { threadPool_.join(); } | ||||||
| 
 | 
 | ||||||
|  |    common::Coordinate CurrentCoordinate() const; | ||||||
|  |    void HandleAlert(const types::TextEventKey& key, size_t messageIndex) const; | ||||||
|    void UpdateLocationTracking(const std::string& value) const; |    void UpdateLocationTracking(const std::string& value) const; | ||||||
| 
 | 
 | ||||||
|  |    boost::asio::thread_pool threadPool_ {1u}; | ||||||
|  | 
 | ||||||
|    AlertManager* self_; |    AlertManager* self_; | ||||||
| 
 | 
 | ||||||
|    boost::uuids::uuid uuid_ {boost::uuids::random_generator()()}; |    boost::uuids::uuid uuid_ {boost::uuids::random_generator()()}; | ||||||
| 
 | 
 | ||||||
|  |    std::shared_ptr<MediaManager>    mediaManager_ {MediaManager::Instance()}; | ||||||
|    std::shared_ptr<PositionManager> positionManager_ { |    std::shared_ptr<PositionManager> positionManager_ { | ||||||
|       PositionManager::Instance()}; |       PositionManager::Instance()}; | ||||||
|  |    std::shared_ptr<TextEventManager> textEventManager_ { | ||||||
|  |       TextEventManager::Instance()}; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| AlertManager::AlertManager() : p(std::make_unique<Impl>(this)) {} | AlertManager::AlertManager() : p(std::make_unique<Impl>(this)) {} | ||||||
| AlertManager::~AlertManager() = default; | AlertManager::~AlertManager() = default; | ||||||
| 
 | 
 | ||||||
|  | common::Coordinate AlertManager::Impl::CurrentCoordinate() const | ||||||
|  | { | ||||||
|  |    settings::AudioSettings& audioSettings = settings::AudioSettings::Instance(); | ||||||
|  |    common::Coordinate       coordinate {}; | ||||||
|  | 
 | ||||||
|  |    types::LocationMethod locationMethod = types::GetLocationMethod( | ||||||
|  |       audioSettings.alert_location_method().GetValue()); | ||||||
|  | 
 | ||||||
|  |    if (locationMethod == types::LocationMethod::Fixed) | ||||||
|  |    { | ||||||
|  |       coordinate.latitude_  = audioSettings.alert_latitude().GetValue(); | ||||||
|  |       coordinate.longitude_ = audioSettings.alert_longitude().GetValue(); | ||||||
|  |    } | ||||||
|  |    else if (locationMethod == types::LocationMethod::Track) | ||||||
|  |    { | ||||||
|  |       QGeoPositionInfo position = positionManager_->position(); | ||||||
|  |       if (position.isValid()) | ||||||
|  |       { | ||||||
|  |          QGeoCoordinate trackedCoordinate = position.coordinate(); | ||||||
|  |          coordinate.latitude_             = trackedCoordinate.latitude(); | ||||||
|  |          coordinate.longitude_            = trackedCoordinate.longitude(); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    return coordinate; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void AlertManager::Impl::HandleAlert(const types::TextEventKey& key, | ||||||
|  |                                      size_t messageIndex) const | ||||||
|  | { | ||||||
|  |    // Skip alert if there are more messages to be processed
 | ||||||
|  |    if (messageIndex + 1 < textEventManager_->message_count(key)) | ||||||
|  |    { | ||||||
|  |       return; | ||||||
|  |    } | ||||||
|  | 
 | ||||||
|  |    settings::AudioSettings& audioSettings = settings::AudioSettings::Instance(); | ||||||
|  |    common::Coordinate       currentCoordinate = CurrentCoordinate(); | ||||||
|  | 
 | ||||||
|  |    auto message = textEventManager_->message_list(key).at(messageIndex); | ||||||
|  | 
 | ||||||
|  |    for (auto& segment : message->segments()) | ||||||
|  |    { | ||||||
|  |       if (!segment->codedLocation_.has_value()) | ||||||
|  |       { | ||||||
|  |          continue; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       auto&             vtec       = segment->header_->vtecString_.front(); | ||||||
|  |       auto              action     = vtec.pVtec_.action(); | ||||||
|  |       awips::Phenomenon phenomenon = vtec.pVtec_.phenomenon(); | ||||||
|  |       auto              eventEnd   = vtec.pVtec_.event_end(); | ||||||
|  |       bool alertActive             = (action != awips::PVtec::Action::Canceled); | ||||||
|  | 
 | ||||||
|  |       // If the event has ended or is inactive, or if the alert is not enabled,
 | ||||||
|  |       // skip it
 | ||||||
|  |       if (eventEnd < std::chrono::system_clock::now() || !alertActive || | ||||||
|  |           !audioSettings.alert_enabled(phenomenon).GetValue()) | ||||||
|  |       { | ||||||
|  |          continue; | ||||||
|  |       } | ||||||
|  | 
 | ||||||
|  |       // Determine if the alert is active at the current coordinte
 | ||||||
|  |       auto alertCoordinates = segment->codedLocation_->coordinates(); | ||||||
|  | 
 | ||||||
|  |       if (util::GeographicLib::AreaContainsPoint(alertCoordinates, | ||||||
|  |                                                  currentCoordinate)) | ||||||
|  |       { | ||||||
|  |          logger_->info("Alert active at current location: {} {}.{} {}", | ||||||
|  |                        vtec.pVtec_.office_id(), | ||||||
|  |                        awips::GetPhenomenonCode(vtec.pVtec_.phenomenon()), | ||||||
|  |                        awips::PVtec::GetActionCode(vtec.pVtec_.action()), | ||||||
|  |                        vtec.pVtec_.event_tracking_number()); | ||||||
|  | 
 | ||||||
|  |          mediaManager_->Play(types::AudioFile::EasAttentionSignal); | ||||||
|  |       } | ||||||
|  |    } | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void AlertManager::Impl::UpdateLocationTracking( | void AlertManager::Impl::UpdateLocationTracking( | ||||||
|    const std::string& locationMethodName) const |    const std::string& locationMethodName) const | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -17,8 +17,7 @@ namespace settings | ||||||
| static const std::string logPrefix_ = "scwx::qt::settings::audio_settings"; | static const std::string logPrefix_ = "scwx::qt::settings::audio_settings"; | ||||||
| 
 | 
 | ||||||
| static const bool              kDefaultAlertEnabled_ {false}; | static const bool              kDefaultAlertEnabled_ {false}; | ||||||
| static const awips::Phenomenon kDefaultPhenomenon_ { | static const awips::Phenomenon kDefaultPhenomenon_ {awips::Phenomenon::Unknown}; | ||||||
|    awips::Phenomenon::FlashFlood}; |  | ||||||
| 
 | 
 | ||||||
| class AudioSettings::Impl | class AudioSettings::Impl | ||||||
| { | { | ||||||
|  | @ -58,6 +57,10 @@ public: | ||||||
| 
 | 
 | ||||||
|          variables_.push_back(&variable); |          variables_.push_back(&variable); | ||||||
|       } |       } | ||||||
|  | 
 | ||||||
|  |       // Create a default disabled alert, not stored in the settings file
 | ||||||
|  |       alertEnabled_.emplace(kDefaultPhenomenon_, | ||||||
|  |                             SettingsVariable<bool> {"alert_disabled"}); | ||||||
|    } |    } | ||||||
| 
 | 
 | ||||||
|    ~Impl() {} |    ~Impl() {} | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Dan Paulat
						Dan Paulat