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() to open a connection, gps_stream() to ask for the needed stream... and use gps_waiting() to poll the socket for data.
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's gps_fd. 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;
// 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) 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.
No hay comentarios:
Publicar un comentario