QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
RTCMUdpInput.cc
Go to the documentation of this file.
1#include "RTCMUdpInput.h"
2
3#include <QtNetwork/QNetworkDatagram>
4#include <QtNetwork/QUdpSocket>
5
7
8QGC_LOGGING_CATEGORY(RTCMUdpInputLog, "GPS.RTCMUdpInput")
9
10RTCMUdpInput::RTCMUdpInput(quint16 port, QObject* parent) : QObject(parent), _port(port) {}
11
16
18{
19 stop();
20 _rtcmParser.reset();
21
22 _socket = new QUdpSocket(this);
23 if (!_socket->bind(QHostAddress::AnyIPv4, _port)) {
24 qCWarning(RTCMUdpInputLog) << "Failed to bind UDP socket on port" << _port << ":" << _socket->errorString();
25 _socket->deleteLater();
26 _socket = nullptr;
27 return false;
28 }
29 connect(_socket, &QUdpSocket::readyRead, this, &RTCMUdpInput::_readDatagrams);
30
31 _running = true;
32 emit runningChanged();
33 qCDebug(RTCMUdpInputLog) << "Listening for RTCM data on UDP port" << _port;
34 return true;
35}
36
38{
39 if (!_running) {
40 return;
41 }
42
43 if (_socket) {
44 _socket->close();
45 _socket->deleteLater();
46 _socket = nullptr;
47 }
48 _running = false;
49 emit runningChanged();
50 qCDebug(RTCMUdpInputLog) << "Stopped listening on UDP port" << _port;
51}
52
53void RTCMUdpInput::setPort(quint16 port)
54{
55 if (_port == port) {
56 return;
57 }
58
59 _port = port;
60 emit portChanged();
61
62 if (_running) {
63 start();
64 }
65}
66
67void RTCMUdpInput::_readDatagrams()
68{
69 if (!_socket) {
70 return;
71 }
72 while (_socket->hasPendingDatagrams()) {
73 const QNetworkDatagram datagram = _socket->receiveDatagram();
74 const QByteArray data = datagram.data();
75 if (data.isEmpty()) {
76 continue;
77 }
78
79 if (!_validateRtcm) {
80 qCDebug(RTCMUdpInputLog) << "Received RTCM datagram:" << data.size() << "bytes";
81 emit rtcmDataReceived(data);
82 continue;
83 }
84
85 int framesFound = 0;
86 int framesDropped = 0;
87 const QByteArray validData = _rtcmParser.extractValidFrames(data, &framesFound, &framesDropped);
88
89 _validFrames += static_cast<quint64>(framesFound);
90 _invalidFrames += static_cast<quint64>(framesDropped);
91 if (framesDropped > 0) {
92 qCWarning(RTCMUdpInputLog) << "Dropped" << framesDropped << "RTCM frame(s) - CRC mismatch";
93 }
94
95 qCDebug(RTCMUdpInputLog) << "Datagram" << data.size() << "bytes -"
96 << "framesFound:" << framesFound << "framesDropped:" << framesDropped
97 << "validData:" << validData.size() << "bytes";
98
99 if (!validData.isEmpty()) {
100 emit rtcmDataReceived(validData);
101 }
102
103 const quint64 totalFrames = _validFrames + _invalidFrames;
104 if (totalFrames > 0) {
105 const double dropPct = 100.0 * _invalidFrames / totalFrames;
106 qCDebug(RTCMUdpInputLog) << QString("RTCM frame stats: %1 valid, %2 invalid, %3% dropped")
107 .arg(_validFrames)
108 .arg(_invalidFrames)
109 .arg(dropPct, 0, 'f', 1);
110 }
111 }
112}
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void reset()
Definition RTCMParser.cc:8
QByteArray extractValidFrames(const QByteArray &in, int *framesFound=nullptr, int *framesDropped=nullptr)
Listens on a UDP port for raw RTCM3 correction data and emits it for forwarding to connected vehicles...
void stop()
Unbind the socket and stop accepting datagrams.
void runningChanged()
void rtcmDataReceived(const QByteArray &data)
~RTCMUdpInput() override
void setPort(quint16 port)
Change the listen port. If already running, restarts automatically.
void portChanged()
quint16 port() const