Using libgps instead of libQgpsmm within a Qt application
I was in need of creating a Qt application using current Debian stable (Stretch) and gpsd. I could have used libQgpsmm which creates a QTcpSocket for stablishing the connection to the gpsd daemon. But then I hit an issue: libQgpsmm was switched to Qt 5 after the Strech release, namely in gpsd 3.17-4. And I'm using Qt 5.
So the next thing to do is to use libgps itself, which is written in C. In this case one needs to call gps_open()]{style="font-family: \"Courier New\", Courier, monospace;"} to open a connection, [gps_stream()]{style="font-family: \"Courier New\", Courier, monospace;"} to ask for the needed stream... and use [gps_waiting() to poll the socket for data.
[
]{style="font-family: \"Courier New\", Courier, monospace;"}gps_waiting() checks for data for a maximum of time specified in it's parameters. That means I would need to create a QTimer and poll it to get the data. Poll it fast enough for the application to be responsive, but not too excessively to avoid useless CPU cycles.
I did not like this idea, so I started digging gpsd's code until I found that it exposes the socket it uses in it's base struct, struct gps_data_t]{style="font-family: \"Courier New\", Courier, monospace;"}'s [gps_fd]{style="font-family: \"Courier New\", Courier, monospace;"}. So the next step was to set up a QSocketNotifier around it, and use it's [activated() signal.
So (very) basically:
// Class private:
struct gps_data_t mGpsData;
QSocketNotifier * mNotifier;
[
]{style="font-family: \"Courier New\", Courier, monospace;"}// In the implementation:
result = gps_open("localhost", DEFAULT_GPSD_PORT, &mGpsData);
// [...check result status...]
result = gps_stream(&mGPSData,WATCH_ENABLE|WATCH_JSON, NULL);
// [...check result status...]
// Set up the QSocketNotifier instance.
mNotifier = new QSocketNotifier(mGpsData.gps_fd, QSocketNotifier::Read, this);
connect(mNotifier, &QSocketNotifier::activated, this, &MyGps::readData);
And of course, calling gps_read(&mGpsData)]{style="font-family: \"Courier New\", Courier, monospace;"} in [MyGps::readData(). With this every time there is activity on the socket readData() will be called, an no need to set up a timer anymore.
Comments
There are no comments yet.