11using namespace std::chrono_literals;
14 :
GPSProtocolRuntime(family, family.create ? family.create() :
nullptr, std::move(io), std::move(observer))
21 , _observer(std::move(observer))
22 , _demux(family.stream)
23 , _protocol(std::move(protocol))
38 const auto stopped = [&token] {
return token.isCancelled(); };
39 const auto until = std::chrono::steady_clock::now() + duration;
40 while (!stopped() && std::chrono::steady_clock::now() < until) {
41 std::this_thread::sleep_for(
42 std::min<std::chrono::steady_clock::duration>(until - std::chrono::steady_clock::now(), 20ms));
48 qCWarning(
logCategory()) <<
"No protocol for receiver family" << _family.
type;
61 _channel._resetError();
65 _channel._detectedBaud =
config.detectedBaud;
66 const bool configured = _protocol->configure(_channel,
config, baud);
72 _channel._describeFailure();
80 _channel._resetError();
84 bool answered =
false;
87 answered = _protocol->probe(_channel);
98 return _protocol->receive(_channel, timeout);
106 return _protocol->armDecodeOnly(
config, _context);
111 return _protocol && _protocol->armNavigationDecode(
decode, _context);
119 _protocol->flush(_context);
120 for (
const uint8_t
byte : bytes) {
121 _demux.
push(
byte, *
this);
123 _channel._offerRaw(bytes);
124 return _context._takeBatch();
129 return _deliver(
decode(bytes));
137 GPSProtocolRuntime::frame(frame);
138 return _deliver(_context._takeBatch());
141GPSReceiveUpdates GPSProtocolRuntime::_deliver(
GPSEventBatch batch)
147 _context._recycle(std::move(batch.
events));
153 return _protocol && !_context.
failed() && _protocol->receiverReady();
158 return _protocol ? _protocol->identity().trimmed() : QString();
161void GPSProtocolRuntime::frame(
const GPSFrame& frame)
163 _context.
markUpdates(_protocol->onFrame(frame, _context));
164 _channel._offerFrame(frame);
176 return _channel.
nowUs();
186 return _channel._replyPending();
191 _channel._resolveReply(outcome);
196 _channel._offerText(reply);
211 const GPSReceiveUpdates updates = channel.
receiveCycle(timeout);
static std::atomic< jobject > _context
const QLoggingCategory &(*)() GPSLogCategory
A family's logging category function, as declared by Q_DECLARE_LOGGING_CATEGORY; usable as qCWarning(...
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void serviceControls()
Runs the family's streaming services once under SERVICE_TIMEOUT, then flushes. Nested calls do nothin...
GPSReceiveUpdates receiveCycle(std::chrono::milliseconds timeout)
void failControl(GPSProtocolError failure=GPSProtocolError::Protocol)
GPSDeadlineScope deadlineScope(std::chrono::milliseconds timeout)
const QString & errorDetail() const
GPSStreamDemux & stream()
void finishCommand(GPSCommandOutcome outcome)
void markUpdates(GPSReceiveUpdates updates)
Adds updates a decoder reports for a frame without publishing an event, such as protocol activity.
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 failControl(const QString &detail)
Records a protocol failure described by detail unless a failure is already recorded,...
GPSStreamDemux & stream()
bool replyPending() const
True while a transact() reply is outstanding and unresolved.
virtual void serviceStreaming(GPSCommandChannel &channel)
virtual GPSReceiveUpdates receive(GPSCommandChannel &channel, std::chrono::milliseconds timeout)
One streaming receive. The default runs GPSCommandChannel::receiveCycle() and then the streaming serv...
GPSEventBatch decode(std::span< const uint8_t > bytes)
Decodes bytes without I/O or observer callbacks.
bool armDecodeOnly(const GPSConfig &config)
GPSReceiveUpdates consume(std::span< const uint8_t > bytes)
Decodes bytes and delivers their batch to the observer. An empty span flushes.
bool receiverReady() const
GPSReceiveUpdates receive(std::chrono::milliseconds timeout)
bool armNavigationDecode(GPSNavigationDecode decode={})
GPSReceiveUpdates consumeFrame(const GPSFrame &frame)
Decodes one frame another stream framed and delivers its batch to the observer, without flushing.
QString identity() const
Model and firmware reported during configuration, trimmed; empty when unknown.
bool probe(std::chrono::milliseconds budget)
GPSLogCategory logCategory() const
The family's logging category, or the runtime's when the family has none.
GPSProtocolRuntime(const GPSReceiverFamily &family, GPSRuntimeIO io, GPSRuntimeObserver observer={})
Creates the family's protocol with its factory.
bool configure(const GPSConfig &config, unsigned &baud)
void push(uint8_t byte, Handler &handler)
std::function< bool(std::chrono::microseconds)> wait
Waits duration on this clock; false when the wait was cancelled. Empty means a real wait.
The receiver configuration requested for one configure() attempt.
Evidence from one configuration command, not a claim of physical receiver operation.
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...
GPSLogCategory logCategory
std::function< GPSReadResult(std::span< uint8_t >, GPSDeadline)> read
GPSCancelToken cancelToken
Checked before each write and baud change; reads observe it in the transport.
std::function< GPSWriteResult(std::span< const uint8_t >, GPSDeadline)> write
GPSClock clock
Without a wait, the runtime sleeps in short slices until the duration elapses or cancelToken is cance...
std::function< GPSBaudStatus(unsigned)> setBaudrate
Observers of runtime output, invoked synchronously on the runtime thread.
std::function< void(const GPSConfigurationEvidence &)> commandFinished
Every completed command, during configuration and streaming alike.
std::function< void(const GPSEventBatch &)> decoded
Borrowed for the callback; it may decode nested input through GPSProtocolRuntime::consume().