5#include <QtCore/QDateTime>
6#include <QtCore/QMetaEnum>
7#include <QtCore/qnumeric.h>
19 return QString::fromLatin1(
20 QMetaEnum::fromType<NTRIPGgaReporter::PositionSource>().valueToKey(
static_cast<int>(source)));
29 case Quality::Differential:
31 case Quality::RTKFloat:
33 case Quality::RTKFixed:
35 case Quality::Extrapolated:
36 case Quality::Unknown:
45bool reportable(
const std::optional<GPSObservation>& observation)
48 observation->fixQuality == GPSFixQuality::NoFix) {
51 const QGeoCoordinate
coordinate = observation->position.coordinate();
59 , _ggaTask(_scheduler, this)
62QString NTRIPGgaReporter::_sourceLabel(PositionSource source)
66 return tr(
"Vehicle GPS");
68 return tr(
"Vehicle EKF");
70 return tr(
"RTK Receiver");
72 return tr(
"GCS Position");
81 _requestedSource = configuration.
source;
82 const auto previousInterval = _normalInterval;
84 if (!_awaitingFirstGga && previousInterval != _normalInterval && _transport) {
91 _providers[source] = std::move(provider);
97 _transport = transport;
98 _loggedSelection.reset();
103 _awaitingFirstGga =
true;
111 _transport =
nullptr;
115void NTRIPGgaReporter::_scheduleNextGGA()
122 _ggaTask.
schedule(_currentInterval(), [
this]() {
128std::chrono::milliseconds NTRIPGgaReporter::_currentInterval()
const
133void NTRIPGgaReporter::_clearSource()
135 if (_source.isEmpty()) {
142void NTRIPGgaReporter::_sendGGA()
147 const auto requested = _requestedSource;
148 const auto selection = _getBestPosition(requested);
149 _logSelection(requested, selection);
150 if (!selection.position) {
155 _awaitingFirstGga =
false;
166 .quality = ggaQuality(
position.fixQuality),
168 ? std::optional<unsigned>(
static_cast<unsigned>(*
position.satellitesUsed))
172 _transport->sendNMEA(gga);
173 if (
const QString label = _sourceLabel(selection.source); label != _source) {
179NTRIPGgaReporter::SelectedPosition NTRIPGgaReporter::_getBestPosition(
PositionSource requested)
const
182 const auto provider = _providers.value(requested);
183 auto position = provider ? provider() : std::nullopt;
184 return {reportable(position) ? std::move(position) : std::nullopt, requested};
194 if (
const auto provider = _providers.value(source)) {
195 if (
auto position = provider(); reportable(position)) {
196 return {std::move(position), source};
203void NTRIPGgaReporter::_logSelection(
PositionSource requested,
const SelectedPosition& selection)
205 const auto current = std::make_tuple(requested, selection.source, selection.position.has_value());
206 if (std::exchange(_loggedSelection, current) == current) {
209 if (!selection.position) {
210 qCDebug(NTRIPGgaReporterLog).noquote()
211 << QStringLiteral(
"GGA source selection: requested=%1 no eligible source").arg(sourceName(requested));
215 const QString fallbackText = fallback ? QStringLiteral(
"yes") : QStringLiteral(
"no");
216 qCDebug(NTRIPGgaReporterLog).noquote()
217 << QStringLiteral(
"GGA source selection: requested=%1 provider=%2 fallback=%3")
218 .arg(sourceName(requested), sourceName(selection.source), fallbackText);
GPSFixQualities::GPSFixQuality GPSFixQuality
#define QGC_LOGGING_CATEGORY(name, categoryStr)
std::function< std::optional< GPSObservation >()> PositionProvider
void start(NTRIPTransport *transport)
static constexpr std::chrono::milliseconds FAST_RETRY_INTERVAL
void sourceChanged(const QString &source)
NTRIPGgaReporter(QObject *parent=nullptr, RuntimeScheduler *scheduler=nullptr)
static constexpr std::chrono::milliseconds DEFAULT_INTERVAL
Interval of a default configuration, and of one whose interval is not positive.
void setPositionProvider(PositionSource source, PositionProvider provider)
void configure(const Configuration &configuration)
bool schedule(std::chrono::microseconds delay, RuntimeScheduler::Callback callback)
GPSPositionReport position(const GPSDecodedPosition &source, const GPSIntegrityReport &diagnostic, uint64_t nowUs)
QByteArray makeGGA(const NMEA::GGA &fix, const QTime &utc)
constexpr unsigned RTK_FLOAT
constexpr unsigned DIFFERENTIAL
constexpr unsigned ESTIMATED
constexpr unsigned RTK_FIXED
constexpr unsigned INVALID
std::optional< double > coordinate(std::string_view field, std::string_view hemisphere, bool latitude)
std::optional< GGA > gga(const Sentence &input)
Quality zero is a valid fix-loss observation with empty coordinates and optional hemisphere fields.
Receiver-independent data. Unknown metadata remains absent, never a manufactured zero.
std::chrono::milliseconds interval