18 , _transportFactory(std::move(transportFactory))
21 , _clock(std::move(clock))
23 qCDebug(GPSReceiverWorkerLog) <<
this;
38 _thread.reset(QThread::create([
this] { _runSession(); }));
39 _thread->setObjectName(QStringLiteral(
"GPSReceiverWorker"));
52 _endsWhenIdle = endsWhenIdle;
58 return !_thread || _thread->wait(deadline);
61void GPSReceiverWorker::_runSession()
64 auto transportFactory = std::exchange(_transportFactory, {});
66 if (cancelToken.isCancelled()) {
70 auto transport = transportFactory ? transportFactory(cancelToken) : nullptr;
71 if (cancelToken.isCancelled()) {
76 if (!cancelToken.isCancelled()) {
81 if (cancelToken.isCancelled()) {
86 const auto usefulDataReceived = [
this, &inactiveAt] {
89 const auto inactiveFor = [
this, &inactiveAt] {
return inactiveAt.remaining(_clock.
nowUs()); };
95 sinks.
onRTCM = [
this](
const QByteArray& message) {
99 bool identified =
false;
105 GPSDriver driver(_type, *transport, _config, std::move(sinks), _clock);
107 if (!driver.configure()) {
108 if (!cancelToken.isCancelled()) {
109 emit
connectionError(driver.configurationNeedsConsent() ? GPSConnectionError::ConsentRequired
111 driver.configurationError());
115 if (cancelToken.isCancelled()) {
120 usefulDataReceived();
122 bool cancelled =
false;
124 while (!cancelToken.isCancelled() && !transport->fatalError() &&
125 (!_endsWhenIdle || inactiveFor() > std::chrono::milliseconds::zero())) {
127 auto result = driver.receiveOutcome(timeout);
129 usefulDataReceived();
131 if (result.terminal()) {
132 failure = std::move(result);
139 if (!_endsWhenIdle && inputMonitor.update(result, identified, _clock.
nowUs())) {
143 if (!cancelToken.isCancelled() && !cancelled) {
146 ? GPSConnectionError::ProtocolError
151 qCDebug(GPSReceiverWorkerLog) <<
"Exiting GPS thread";
@ 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.
@ Data
Useful reports, even without a registered sink.
#define QGC_LOGGING_CATEGORY(name, categoryStr)
GPSCancelToken token() const
static constexpr std::chrono::milliseconds RECEIVE_TIMEOUT
Longest wait for one read before the session re-checks cancellation.
void inputProblem(GPSInputProblem problem)
virtual void start()
Starts the session once; later calls are ignored.
void connectionError(GPSConnectionError error, const QString &detail={})
detail is the transport's or the protocol's diagnostic, or empty when it gave none.
bool wait(QDeadlineTimer deadline=QDeadlineTimer(QDeadlineTimer::Forever))
Waits for the worker to exit; returns true at once when the session never started.
void finished()
Delivered on this object's thread once the session thread has finished.
void receiverReady(const QString &identity={})
identity is the receiver model and firmware, or empty when the family does not report them.
void satelliteInfoUpdated(const GPSSatelliteReport &message)
void surveyInStatusUpdated(const GPSSurveyReport &report)
~GPSReceiverWorker() override
void receiverDetected(GPSType type)
void setEndsWhenIdle(bool endsWhenIdle)
std::function< std::unique_ptr< GPSTransport >(GPSCancelToken)> TransportFactory
Consumed on the worker thread, so transport construction, I/O and destruction share that thread.
static constexpr std::chrono::milliseconds USEFUL_DATA_TIMEOUT
void rtcmDataReceived(const QByteArray &message, qint64 receivedAtMs)
RTCM output the receiver sent, stamped with the steady clock when it was read.
void positionUpdated(const GPSPositionReport &report)
@ DeviceError
The connection to the receiver failed or went silent.
The monotonic clock receiver sessions run on: the steady clock unless tests inject a virtual one.
std::function< uint64_t()> nowUs
static GPSDeadline after(uint64_t nowUs, std::chrono::microseconds timeout)
A negative timeout is already due at nowUs.
std::function< void(const GPSSatelliteReport &)> onSatelliteInfo
std::function< void(const GPSPositionReport &)> onPosition
std::function< void(const GPSSurveyReport &)> onSurveyIn
std::function< void(const QByteArray &)> onRTCM
One complete frame; copying it shares the receiver's buffer.
std::function< void(GPSType)> onReceiverDetected