Skip to content

Conversation

edgecase14
Copy link
Contributor

Blindly stuffs TCP packets received over Bluetooth. RTCM or SPARTN. TCP message fragments aren't reassembled.

Tested on Linux, with PointPerfect(thingstream) and SparkFun RTK Surveyor firmware on custom harware. RTK Fixed is achieved.

See #5387. Comments requested. Android testing encouraged.

@nirvn
Copy link
Member

nirvn commented Aug 15, 2025

@edgecase14 , first and foremost, this is a super nice contribution, you're making a very nice entry into the QField community this month :)

I'll review the PR in a second. One big structural we'll need to change here is where the NTRIP communication is happening. We'll want this sitting at the NmeaGnssReceiver class instead of within the BluetoothReceiver class. One reason for that is that on Windows, Bluetooth connectivity often goes through virtual serial port where QField uses the serial port receiver to communicate with the GNSS device.

That shouldn't be a huge change here, just a bit of code reshuffling around.

Comment on lines +33 to +47
if ( firstByte == 0xD3 )
{
qDebug() << "RTCM chunk:";
}
else if ( firstByte == 0x73 )
{
qDebug() << "SPARTN chunk:";
}
else
{
qDebug() << "UNKNOWN chunk:";
}

qDebug() << data.size() << "bytes";
// send to your GNSS device
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's clean some of that debug prior to merging so we don't get too verbose when running QField in debug mode.

Comment on lines +72 to +75
//connect(mReply, &QNetworkReply::readyRead, this, &NtripClient::onReadyRead);
//connect(mReply, &QNetworkReply::finished, this, &NtripClient::onFinished);
//connect(mReply, xxxQOverload<QNetworkReply::NetworkError>::of(&QNetworkReply::errorOccurred),
// this, &NtripClient::onError);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leftover?

{
if ( mReply )
{
disconnect( mReply, nullptr, this, nullptr ); // ✅ Disconnect all signals
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No emojis in source file please :)


if ( mReply->isRunning() )
{
mReply->abort(); // ✅ Cancel the request
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See above.

Comment on lines +93 to +100
/*
void NtripClient::onReadyRead()
{
QByteArray data = mReply->readAll();
qInfo() << data + "\n";
emit correctionDataReceived(data);
}
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To be removed?

Comment on lines +82 to +87
else
{
// Wait for more data
return;
}
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When you read all the data here, the buffer will be gone, meaning that as your waiting for more data, you'll lose the data that came before, is there a need to preserve the data to append it to the next frame until the \r\n\r\n bit arrives?

Comment on lines +96 to +97
connect( mPositioningSourceReplica.data(), SIGNAL( ntripBytesSentChanged() ), this, SIGNAL( ntripBytesSentChanged() ) );
connect( mPositioningSourceReplica.data(), SIGNAL( ntripBytesReceivedChanged() ), this, SIGNAL( ntripBytesReceivedChanged() ) );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think we'll need those exposed here. Is that an important part to you, and if so, how would this be used?

@@ -66,6 +66,15 @@ class Positioning : public QObject
Q_PROPERTY( QString loggingPath READ loggingPath WRITE setLoggingPath NOTIFY loggingPathChanged )

Q_PROPERTY( bool backgroundMode READ backgroundMode WRITE setBackgroundMode NOTIFY backgroundModeChanged )
Q_PROPERTY( bool enableNtripClient READ enableNtripClient WRITE setEnableNtripClient NOTIFY enableNtripClientChanged )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To fit with other property names here, I'd rename that to:

bool ntripCorrection READ ntripCorrection WRITE setNtripCorrection NOTIFY ntripCorrectionChanged )

signals:
void correctionDataReceived( const QByteArray &data );
void errorOccurred( const QString &message );
void streamConnected();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should have a streamDisconnected signal to allow for the code to react to a server-induced disconnection.

Q_PROPERTY( QString ntripMountpoint READ ntripMountpoint WRITE setNtripMountpoint NOTIFY ntripMountpointChanged )
Q_PROPERTY( QString ntripUsername READ ntripUsername WRITE setNtripUsername NOTIFY ntripUsernameChanged )
Q_PROPERTY( QString ntripPassword READ ntripPassword WRITE setNtripPassword NOTIFY ntripPasswordChanged )
Q_PROPERTY( QString ntripStatus READ ntripStatus NOTIFY ntripStatusChanged )
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use an enum here, and rename it to state (Connected, Disconnected for now?). This will allow us to then more easily localize the state is we want it reflected in the UI itself.

For error messsages, I'd adopt a QString ntripLastError property (to match preexisting deviceLastError property).

@nirvn
Copy link
Member

nirvn commented Aug 29, 2025

@edgecase14 , following up on this, are you planning to push this exciting PR further? :)

@edgecase14
Copy link
Contributor Author

Yes, just other work came up. I am new to github PR reviews if there's a quickstart guide you can point me to great otherwise I'll muddle my way through.

@nirvn
Copy link
Member

nirvn commented Aug 31, 2025

@edgecase14 , happy to hear you are forging ahead! :) Let me know if anything I said in my individual review comments was not clear.

You should insure that the pre-commit hook is installed locally (should just be a matter of typing pre-commit install in your terminal provided you have the pre-commit python package already installed on your system).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants