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 if (_port == 0) {
32 _port = _socket->localPort();
33 emit portChanged();
34 }
35
36 _running = true;
37 emit runningChanged();
38 qCDebug(RTCMUdpInputLog) << "Listening for RTCM data on UDP port" << _port;
39 return true;
40}
41
43{
44 if (!_running) {
45 return;
46 }
47
48 if (_socket) {
49 _socket->close();
50 _socket->deleteLater();
51 _socket = nullptr;
52 }
53 _running = false;
54 emit runningChanged();
55 qCDebug(RTCMUdpInputLog) << "Stopped listening on UDP port" << _port;
56}
57
58void RTCMUdpInput::setPort(quint16 port)
59{
60 if (_port == port) {
61 return;
62 }
63
64 _port = port;
65 emit portChanged();
66
67 if (_running) {
68 start();
69 }
70}
71
72void RTCMUdpInput::_readDatagrams()
73{
74 if (!_socket) {
75 return;
76 }
77 while (_socket->hasPendingDatagrams()) {
78 const QNetworkDatagram datagram = _socket->receiveDatagram();
79 const QByteArray data = datagram.data();
80 if (data.isEmpty()) {
81 continue;
82 }
83
84 if (!_validateRtcm) {
85 qCDebug(RTCMUdpInputLog) << "Received RTCM datagram:" << data.size() << "bytes";
86 emit rtcmDataReceived(data);
87 continue;
88 }
89
90 // Emit one complete RTCM3 frame per signal so RTCMMavlink assigns a distinct
91 // GPS_RTCM_DATA sequence per frame (required for correct MAVLink reassembly).
92 int framesFound = 0;
93 int framesDropped = 0;
94 for (const char ch : data) {
95 if (!_rtcmParser.addByte(static_cast<uint8_t>(static_cast<unsigned char>(ch)))) {
96 continue;
97 }
98 if (_rtcmParser.validateCrc()) {
99 ++framesFound;
100 ++_validFrames;
101 emit rtcmDataReceived(_rtcmParser.currentFrame());
102 } else {
103 ++framesDropped;
104 ++_invalidFrames;
105 }
106 _rtcmParser.reset();
107 }
108
109 if (framesDropped > 0) {
110 qCWarning(RTCMUdpInputLog) << "Dropped" << framesDropped << "RTCM frame(s) - CRC mismatch";
111 }
112
113 qCDebug(RTCMUdpInputLog) << "Datagram" << data.size() << "bytes -" << "framesFound:" << framesFound
114 << "framesDropped:" << framesDropped;
115
116 const quint64 totalFrames = _validFrames + _invalidFrames;
117 if (totalFrames > 0) {
118 const double dropPct = 100.0 * _invalidFrames / totalFrames;
119 qCDebug(RTCMUdpInputLog) << QString("RTCM frame stats: %1 valid, %2 invalid, %3% dropped")
120 .arg(_validFrames)
121 .arg(_invalidFrames)
122 .arg(dropPct, 0, 'f', 1);
123 }
124 }
125}
#define QGC_LOGGING_CATEGORY(name, categoryStr)
void reset()
Definition RTCMParser.cc:8
bool validateCrc() const
Definition RTCMParser.cc:91
QByteArray currentFrame() const
bool addByte(uint8_t byte)
Definition RTCMParser.cc:17
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