6#include <QtCore/QCoreApplication>
7#include <QtCore/QDeadlineTimer>
8#include <QtCore/QFileInfo>
12#include <QtSerialPort/QSerialPort>
22QString openFailure(
const QSerialPort& serial,
const QString& device)
24 switch (serial.
error()) {
27 return QCoreApplication::translate(
"SerialGPSTransport",
"%1 was not found").arg(device);
31 if (
const QFileInfo file(device); file.exists() && !(file.isReadable() && file.isWritable())) {
33 return QCoreApplication::translate(
"SerialGPSTransport",
"permission denied for %1").arg(device);
37 return QCoreApplication::translate(
"SerialGPSTransport",
"%1 is in use by another program").arg(device);
39 return serial.errorString();
46 std::chrono::milliseconds openTimeout)
48 , _device(std::move(device))
49 , _openTimeout(openTimeout)
59 _serial = std::make_unique<QSerialPort>();
60 _inputOverflow =
false;
63 _serial.get(), &QSerialPort::readyRead, _serial.get(),
67 _inputOverflow = _inputOverflow || _serial->bytesAvailable() >= READ_BUFFER_BYTES;
69 Qt::DirectConnection);
73 _serial.get(), &QSerialPort::bytesWritten, _serial.get(), [
this](qint64 count) { _writtenTotal += count; },
74 Qt::DirectConnection);
75 _serial->setPortName(_device);
76 const QDeadlineTimer openDeadline(_openTimeout);
77 while (!_serial->open(QIODevice::ReadWrite)) {
83 qCWarning(SerialGPSTransportLog)
84 <<
"GPS: Failed to open Serial Device" << _device << _serial->errorString();
86 openFailure(*_serial, _device)};
88 qCDebug(SerialGPSTransportLog) <<
"Cannot open device... retrying";
89 const QDeadlineTimer retryDeadline(
90 (std::min) (std::chrono::milliseconds(openDeadline.remainingTime()), OPEN_RETRY));
91 (void)
waitUntil([]() {
return false; }, retryDeadline);
96 _serial->clearError();
103 _serial->errorString()};
112 return _inputBudgetExhausted() || !_serial || !_serial->isOpen() ||
118 return _serial.get();
137bool SerialGPSTransport::_inputBudgetExhausted()
const
139 return _inputOverflow || (_serial && _serial->bytesAvailable() >=
READ_BUFFER_BYTES);
142QString SerialGPSTransport::_errorDetail()
const
144 return _inputBudgetExhausted()
145 ? QStringLiteral(
"Serial GPS input buffer exhausted; reconnect required to restore stream continuity")
147 : QStringLiteral(
"Serial GPS connection is closed");
152 _serial->waitForBytesWritten(
static_cast<int>(
153 (deadline.isForever() ? CANCELLATION_POLL
154 : (std::min) (std::chrono::milliseconds(deadline.remainingTime()), CANCELLATION_POLL))
161 const qint64 previousAccepted = _acceptedTotal;
162 _acceptedTotal += accepted;
164 const qint64 confirmed =
165 !
fatalError() ? (std::max) (_writtenTotal, _acceptedTotal - _serial->bytesToWrite()) : _writtenTotal;
166 return confirmed - previousAccepted;
174 if (_serial->setBaudRate(
static_cast<qint32
>(baudrate))) {
179 qCDebug(SerialGPSTransportLog) <<
"Link refused" << baudrate <<
"baud:" << _serial->errorString();
180 _serial->clearError();
#define QGC_LOGGING_CATEGORY(name, categoryStr)
bool waitUntil(const std::function< bool()> &done, QDeadlineTimer deadline)
virtual bool waitReadable(QDeadlineTimer deadline)
Waits until input is buffered. Input reported buffered is delivered even after the link fails.
static constexpr qint64 READ_BUFFER_BYTES
Provides functions to access serial ports.
SerialPortError error() const
the error status of the serial port
bool setBaudrate(unsigned baudrate) override
void waitWritten(QDeadlineTimer &deadline) override
Waits for queued bytes to drain. May expire deadline to end the write.
bool fatalError() const override
True once the port hits an error the receive loop should stop retrying past.
GPSOpenResult open() override
SerialGPSTransport(QString device, GPSCancelToken cancelToken, std::chrono::milliseconds openTimeout=OPEN_TIMEOUT)
GPSReadResult readFailure() const override
Describes a failed link; by default, a closed connection with the device's error.
qint64 confirmedWritten(int accepted, qint64 drained) override
~SerialGPSTransport() override
bool waitReadable(QDeadlineTimer deadline) override
Waits until input is buffered. Input reported buffered is delivered even after the link fails.
bool readUnavailable() const override
Whether read() fails without waiting; by default, when there is no device.
QIODevice * device() const override
The open device, or null before open().