mirror of
https://github.com/ciphervance/supercell-wx.git
synced 2025-11-01 14:50:05 +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