QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
GPSCommand.h
Go to the documentation of this file.
1#pragma once
2
3#include <algorithm>
4#include <array>
5#include <chrono>
6#include <cstddef>
7#include <cstdint>
8#include <functional>
9#include <optional>
10#include <span>
11#include <string_view>
12#include <utility>
13#include <variant>
14#include <vector>
15
16#include <QtCore/QByteArray>
17#include <QtCore/QByteArrayView>
18
19#include "GPSStreamDemux.h"
20
22enum class GPSProtocolError : uint8_t
23{
24 None,
25 Cancelled,
26 Transport,
27 Protocol,
30};
31
32enum class [[nodiscard]] GPSCommandOutcome
33{
34 Pending,
35 Written,
42};
43
45struct [[nodiscard]] GPSConfigurationEvidence
46{
47 QByteArray command;
50 uint64_t startedAtUs = 0;
51 int acceptedBytes = 0;
52 int writtenBytes = 0;
53 bool required = true;
54
55 [[nodiscard]] bool succeeded() const
56 {
58 }
59};
60
62{
63 QByteArray command;
64 std::chrono::milliseconds timeout;
65 bool required = true;
66};
67
69using GPSTextMatcher = std::function<GPSCommandOutcome(std::string_view reply)>;
71using GPSFrameMatcher = std::function<GPSCommandOutcome(const GPSFrame& frame)>;
73using GPSReplyPoll = std::function<GPSCommandOutcome()>;
74
77{
78public:
79 GPSRawAckMatcher(QByteArrayView accepted, QByteArrayView rejected)
80 : _accepted(accepted)
81 , _rejected(rejected)
82 {}
83
84 bool valid() const
85 {
86 return !_accepted.empty() && _accepted.size() <= _window.size() && _rejected.size() <= _window.size();
87 }
88
89 void append(std::span<const uint8_t> bytes)
90 {
91 if (!valid()) {
92 return;
93 }
94 for (const uint8_t byte : bytes) {
95 if (_size == _window.size()) {
96 std::move(_window.begin() + 1, _window.end(), _window.begin());
97 --_size;
98 }
99 _window[_size++] = static_cast<char>(byte);
100 const std::string_view received(_window.data(), _size);
101 if (!_rejected.empty() && received.ends_with(_rejected)) {
103 } else if (_outcome != GPSCommandOutcome::Rejected && received.ends_with(_accepted)) {
105 }
106 }
107 }
108
109 GPSCommandOutcome outcome() const { return _outcome; }
110
111private:
112 std::string_view _accepted;
113 std::string_view _rejected;
114 std::array<char, 256> _window{};
115 size_t _size = 0;
117};
118
122{
124 struct RawReply
125 {
126 QByteArray accepted{};
127 QByteArray rejected{};
128 };
129
130 struct Command
131 {
134 QByteArray wire{};
135 std::variant<GPSTextMatcher, RawReply> reply{};
136 unsigned attempts = 1;
137 };
138
139 struct [[nodiscard]] Result
140 {
142 std::optional<size_t> failedStep = std::nullopt;
143 QByteArray failedLabel{};
146
147 [[nodiscard]] bool succeeded() const { return !failedStep.has_value(); }
148 };
149
150 std::vector<Command> steps{};
151};
152
154{
155 bool required = true;
157 QByteArray label{};
158};
159
163 QByteArray wire, std::chrono::milliseconds timeout,
164 std::variant<GPSTextMatcher, GPSCommandSequence::RawReply> reply, GPSCommandOptions options = {})
165{
166 GPSConfigurationStep step{.command = options.label.isEmpty() ? wire.trimmed() : std::move(options.label),
167 .timeout = timeout,
168 .required = options.required};
169 return {.step = std::move(step), .wire = std::move(wire), .reply = std::move(reply)};
170}
std::function< GPSCommandOutcome(const GPSFrame &frame)> GPSFrameMatcher
Resolves the outstanding command from each dispatched frame, after the family decoded it; Pending kee...
Definition GPSCommand.h:71
std::function< GPSCommandOutcome()> GPSReplyPoll
Polled after each decoded chunk, for replies a family tracks in its own decoder state; Pending keeps ...
Definition GPSCommand.h:73
GPSCommandOutcome
Definition GPSCommand.h:33
GPSProtocolError
Sticky failure of the current receiver session; I/O and control stop until the next configure().
Definition GPSCommand.h:23
@ InvalidArgument
The driver requested an invalid write, or received before configuring.
@ Protocol
The receiver violated or rejected the control protocol.
@ Cancelled
A stop was requested; not a receiver or link fault.
@ ConsentRequired
Configuration needs a persistent receiver change the caller did not allow.
@ Transport
The link could not read, write, or change its baud rate.
GPSCommandSequence::Command gpsCommand(QByteArray wire, std::chrono::milliseconds timeout, std::variant< GPSTextMatcher, GPSCommandSequence::RawReply > reply, GPSCommandOptions options={})
Definition GPSCommand.h:162
std::function< GPSCommandOutcome(std::string_view reply)> GPSTextMatcher
Resolves the outstanding command from one text reply a decoder offers; Pending keeps waiting.
Definition GPSCommand.h:69
Bounded raw-byte matching for receivers whose replies need not be complete ASCII lines.
Definition GPSCommand.h:77
void append(std::span< const uint8_t > bytes)
Definition GPSCommand.h:89
GPSRawAckMatcher(QByteArrayView accepted, QByteArrayView rejected)
Definition GPSCommand.h:79
GPSCommandOutcome outcome() const
Definition GPSCommand.h:109
bool valid() const
Definition GPSCommand.h:84
QByteArray label
Names the command in evidence instead of its wire text, such as when the text carries base coordinate...
Definition GPSCommand.h:157
GPSConfigurationStep step
Evidence label and per-attempt timeout. A required command that fails ends the sequence.
Definition GPSCommand.h:133
std::variant< GPSTextMatcher, RawReply > reply
Definition GPSCommand.h:135
Matched in the raw received bytes, for replies that need not be complete frames (see GPSRawAckMatcher...
Definition GPSCommand.h:125
std::vector< Command > steps
Definition GPSCommand.h:150
Evidence from one configuration command, not a claim of physical receiver operation.
Definition GPSCommand.h:46
std::chrono::milliseconds timeout
Definition GPSCommand.h:64