QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GPSFamilyProtocol.h
Go to the documentation of this file.
1#pragma once
2
3#include <chrono>
4#include <cstdint>
5#include <memory>
6#include <optional>
7#include <span>
8#include <string_view>
9#include <utility>
10#include <vector>
11
12#include <QtCore/QByteArray>
13#include <QtCore/QByteArrayView>
14#include <QtCore/QLatin1StringView>
15#include <QtCore/QString>
16
17#include "GPSCommand.h"
18#include "GPSProtocolEvent.h"
19#include "GPSReceiverConfig.h"
20#include "GPSStreamDemux.h"
21#include "GPSType.h"
22
26class QLoggingCategory;
27
29using GPSLogCategory = const QLoggingCategory& (*)();
30
33using GPSSignatureFunction = QLatin1StringView (*)(const GPSFrame& frame);
34
37{
43 unsigned detectedBaud = 0;
44
46 [[nodiscard]] unsigned linkBaud(unsigned requested, unsigned fallback) const
47 {
48 return requested ? requested : detectedBaud ? detectedBaud : fallback;
49 }
50};
51
56{
57 GPSType type = GPSType::passive;
62 std::span<const unsigned> baudCandidates{};
64 unsigned autoBaudRate = 0;
65 std::unique_ptr<GPSFamilyProtocol> (*create)() = nullptr;
69};
70
74{
75public:
76 Q_DISABLE_COPY(GPSDecodeContext)
77
78 [[nodiscard]] uint64_t nowUs() const;
79
80 [[nodiscard]] GPSStreamDemux& stream();
81
82 // Events of the current decode, in publication order. Events are never coalesced: every position epoch is its own
83 // event, and consumers decide whether to drop superseded ones.
84
86 {
88 _batch.events.emplace_back(report);
89 }
90
92 {
94 _batch.events.emplace_back(report);
95 }
96
97 void publishSatelliteUsage(std::optional<int> count)
98 {
100 _batch.events.emplace_back(GPSDecodedSatelliteUsage{nowUs(), count});
101 }
102
105 {
106 report.timestampUs = nowUs();
107 _batch.events.emplace_back(report);
109 }
110
113 {
114 status.timestampUs = nowUs();
115 _batch.events.emplace_back(status);
116 }
117
119 void publishSurvey(bool active, bool valid, std::chrono::seconds duration,
120 const GPSEllipsoidPosition& position = {})
121 {
122 GPSSurveyReport status{};
123 status.position = position;
124 status.duration = duration;
125 status.valid = valid;
126 status.active = active;
127 publishSurvey(status);
128 }
129
130 void publishRTCM(std::span<const uint8_t> frame)
131 {
132 _batch.events.emplace_back(GPSRTCMFrame{QByteArrayView(frame).toByteArray()});
134 }
135
139 void publishAsReceived(GPSProtocolEvent event) { _batch.events.push_back(std::move(event)); }
140
142 void markUpdates(GPSReceiveUpdates updates) { _batch.updates |= updates; }
143
145 [[nodiscard]] bool replyPending() const;
146
148 void resolveReply(GPSCommandOutcome outcome);
149
151 void offerReply(std::string_view reply);
152
153 [[nodiscard]] bool failed() const;
154
156 void failControl(const QString& detail);
157
158private:
159 friend class GPSProtocolRuntime;
160
161 explicit GPSDecodeContext(GPSCommandChannel& channel)
162 : _channel(channel)
163 {}
164
165 [[nodiscard]] GPSEventBatch _takeBatch() { return std::exchange(_batch, {}); }
166
168 void _recycle(std::vector<GPSProtocolEvent>&& storage)
169 {
170 storage.clear();
171 if (_batch.events.empty() && _batch.events.capacity() < storage.capacity()) {
172 _batch.events.swap(storage);
173 }
174 }
175
176 GPSCommandChannel& _channel;
177 GPSEventBatch _batch;
178};
179
182{
184 bool corrections = false;
185};
186
190{
191public:
192 virtual ~GPSFamilyProtocol() = default;
193
194 Q_DISABLE_COPY(GPSFamilyProtocol)
195
196
200 [[nodiscard]] virtual bool configure(GPSCommandChannel& channel, GPSConfig config, unsigned& baud) = 0;
201
206 [[nodiscard]] virtual bool probe(GPSCommandChannel& channel)
207 {
208 Q_UNUSED(channel)
209 return false;
210 }
211
214 virtual GPSReceiveUpdates onFrame(const GPSFrame& frame, GPSDecodeContext& context) = 0;
215
217 virtual void flush(GPSDecodeContext& context) { Q_UNUSED(context) }
218
221 [[nodiscard]] virtual bool receiverReady() const { return true; }
222
224 [[nodiscard]] virtual QString identity() const { return {}; }
225
229 [[nodiscard]] virtual bool armDecodeOnly(const GPSConfig& config, GPSDecodeContext& context)
230 {
231 Q_UNUSED(config)
232 Q_UNUSED(context)
233 return false;
234 }
235
239 [[nodiscard]] virtual bool armNavigationDecode(GPSNavigationDecode decode, GPSDecodeContext& context)
240 {
241 Q_UNUSED(decode)
242 Q_UNUSED(context)
243 return false;
244 }
245
247 virtual GPSReceiveUpdates receive(GPSCommandChannel& channel, std::chrono::milliseconds timeout);
248
251 virtual bool completeReceiveCycle(GPSReceiveUpdates handled) { return handled != GPSReceiveUpdates{}; }
252
254 [[nodiscard]] virtual std::chrono::milliseconds nextReadSlice(std::chrono::milliseconds timeout) const
255 {
256 return timeout;
257 }
258
261 virtual void serviceStreaming(GPSCommandChannel& channel);
262
263protected:
264 GPSFamilyProtocol() = default;
265};
266
268[[nodiscard]] inline QString gpsReceiverIdentity(const QByteArray& model, const QByteArray& firmware)
269{
270 return QString::fromUtf8(model.isEmpty() || firmware.isEmpty() ? model + firmware : model + ' ' + firmware);
271}
272
274template <typename Protocol>
275std::unique_ptr<GPSFamilyProtocol> gpsCreateProtocol()
276{
277 return std::make_unique<Protocol>();
278}
GPSCommandOutcome
Definition GPSCommand.h:33
QString gpsReceiverIdentity(const QByteArray &model, const QByteArray &firmware)
A receiver identity as GPSFamilyProtocol::identity() reports it: "<model> <firmware>",...
QLatin1StringView(*)(const GPSFrame &frame) GPSSignatureFunction
const QLoggingCategory &(*)() GPSLogCategory
A family's logging category function, as declared by Q_DECLARE_LOGGING_CATEGORY; usable as qCWarning(...
std::unique_ptr< GPSFamilyProtocol > gpsCreateProtocol()
The create of a family whose protocol is default-constructed: .create = &gpsCreateProtocol<Protocol>.
std::variant< GPSDecodedPosition, GPSIntegrityReport, GPSDecodedSatellites, GPSDecodedSatelliteUsage, GPSSurveyReport, GPSRTCMFrame, GPSInputProtocol > GPSProtocolEvent
Config config
void markUpdates(GPSReceiveUpdates updates)
Adds updates a decoder reports for a frame without publishing an event, such as protocol activity.
void publishSatelliteUsage(std::optional< int > count)
void resolveReply(GPSCommandOutcome outcome)
Resolves the outstanding reply; Pending and later resolutions are ignored.
void offerReply(std::string_view reply)
Passes one decoded text reply to the outstanding text matcher, if any.
void publishAsReceived(GPSProtocolEvent event)
void publishSurvey(bool active, bool valid, std::chrono::seconds duration, const GPSEllipsoidPosition &position={})
Publishes survey-in progress; unknown coordinates remain NaN.
void publishIntegrity(GPSIntegrityReport &report)
Stamps the family's working report with the receipt time and publishes a copy.
void publishPosition(const GPSDecodedPosition &report)
void failControl(const QString &detail)
Records a protocol failure described by detail unless a failure is already recorded,...
void publishRTCM(std::span< const uint8_t > frame)
uint64_t nowUs() const
GPSStreamDemux & stream()
void publishSatellites(const GPSDecodedSatellites &report)
bool replyPending() const
True while a transact() reply is outstanding and unresolved.
void publishSurvey(GPSSurveyReport &status)
Stamps status with the receipt time and publishes a copy. Survey progress is not an update flag.
virtual bool receiverReady() const
virtual void serviceStreaming(GPSCommandChannel &channel)
virtual bool probe(GPSCommandChannel &channel)
virtual GPSReceiveUpdates receive(GPSCommandChannel &channel, std::chrono::milliseconds timeout)
One streaming receive. The default runs GPSCommandChannel::receiveCycle() and then the streaming serv...
virtual bool armNavigationDecode(GPSNavigationDecode decode, GPSDecodeContext &context)
GPSFamilyProtocol()=default
virtual GPSReceiveUpdates onFrame(const GPSFrame &frame, GPSDecodeContext &context)=0
virtual ~GPSFamilyProtocol()=default
virtual bool armDecodeOnly(const GPSConfig &config, GPSDecodeContext &context)
virtual bool configure(GPSCommandChannel &channel, GPSConfig config, unsigned &baud)=0
virtual bool completeReceiveCycle(GPSReceiveUpdates handled)
virtual QString identity() const
Model and firmware reported during configuration; empty when unknown.
virtual std::chrono::milliseconds nextReadSlice(std::chrono::milliseconds timeout) const
The longest single read in a receive cycle of timeout; the cycle deadline still bounds it.
virtual void flush(GPSDecodeContext &context)
Publishes time-driven output before each decode, such as expired epochs.
GPSPositionReport position(const GPSDecodedPosition &source, const GPSIntegrityReport &diagnostic, uint64_t nowUs)
Configuration used only by the RTK base-station role.
The receiver configuration requested for one configure() attempt.
GPSBaseStationConfig base
unsigned detectedBaud
unsigned linkBaud(unsigned requested, unsigned fallback) const
The rate a family without a baud search runs the link at: requested, else detectedBaud,...
bool allowPersistentChanges
Decoded navigation plus whether the producer accepted its velocity solution.
WGS84 geodetic position with ellipsoid height, not mean-sea-level altitude.
Events decoded from one span of received bytes, in publication order.
std::vector< GPSProtocolEvent > events
GPSReceiveUpdates updates
What a decode-only runtime decodes from a receiver configured elsewhere (GPSFamilyProtocol::armNaviga...
bool corrections
RTCM3 frames are published too.
One RTCM3 frame the receiver produced, including its header and CRC.
std::span< const unsigned > baudCandidates
GPSStreamConfig stream
GPSLogCategory logCategory
GPSSignatureFunction signature
std::unique_ptr< GPSFamilyProtocol >(* create)()
unsigned autoBaudRate
Rate passed to configure() when none is selected; zero requests detection.
The framers of one receiver stream and how they share it.
GPSEllipsoidPosition position
uint64_t timestampUs
Receipt of this status; a status a family buffered keeps its original receipt.