Use QtPositioning for location lookup
Description
Discussed in #4216
Our IP-based location lookup was a nice feature in 2014, but Qt has introduced some while ago the QtPositioning library. This can utilize the OS services for location lookup and may deliver more accurate results.
Operating systems may limit access to these services and require permissions that must be granted or can be denied.
The current implementation first tries to get permission for a high-precision lookup, if that is not granted, a low-precision lookup. If this is not granted, the previous IP-based lookup is executed.
Note that the permission system was only introduced in Qt6.5 or 6.6, so the first versions here will likely not compile in our CI.
For discussion:
- [ ] Shall we remove the previous IP-based lookup fallback?
- [ ] We have a contribution that uses its own QGeoPositionInfoSource for recurring position updates as alternative to GPS, but is #ifdeffed to Windows only. It may be also useful on Linux.
- [ ] If this is difficult on Qt5, we could just exclude it there.
Screenshots (if appropriate):
Type of change
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing functionality to change)
- [x] This change requires a documentation update
- [ ] Housekeeping
How Has This Been Tested?
Test Configuration:
- Operating system: Win11 23H2
- Graphics Card: irrelevant
- Qt:
- [x] 6.8.2
- [x] 6.5
- [x] 5.15.2 Attn, fallback lookup fails with "TLS initialization failed"! So, our old IP lookup fails with Qt5.
Checklist:
- [x] My code follows the code style of this project.
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation (header file)
- [ ] I have updated the respective chapter in the Stellarium User Guide
- [ ] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules
Hello @gzotti!
Thank you for the suggested improvement.
Great PR! Please pay attention to the following items before merging:
Files matching src/**/*.cpp:
- [ ] Are possibly unused includes removed?
This is an automatically generated QA checklist based on modified files.
Given that this did not need new buttons or labels, if it works on your platforms, it could maybe even still go into 25.1.
I do not getting coordinates/location in linux and he switches to use custom time zone when feature is disabled
I do not getting coordinates/location in linux and he switches to use custom time zone when feature is disabled
The logfile should contain a line "Position received from OS query:...". What does it say? If the location is invalid, this should then fallback to the old version. (TODO, I assumed the reply is meaningful.)
Not sure what you mean by custom timezone. This lookup does not provide place name or timezone. I initialize the location from the current location and change a few data entries. I have left TODO notes where the timezone and light pollution could be put in. The timezone could come from the system clock (Assuming you travel somewhere far away, adjust PC to local time zone and then call this).
Maybe the logic should be changed: Retrieve both, QtPosition (long/lat/altitude?) and old IP lookup (long/lat/0, timezone, placename, country, ...). Process data like with old solution, just replace long/lat/alt with the new data, This would retrieve at least timezone from IP lookup. The place name retrieved from IP lookup does not make sense when the actual position is tens of km away, so placename from coordinates seems OK to me.
If you then know where to get LP values for coordinates, this can be inserted where indicated by TODO.
The logfile should contain a line "Position received from OS query:...". What does it say? If the location is invalid, this should then fallback to the old version. (TODO, I assumed the reply is meaningful.)
Nothing...
Not sure what you mean by custom timezone. This lookup does not provide place name or timezone. I initialize the location from the current location and change a few data entries. I have left TODO notes where the timezone and light pollution could be put in. The timezone could come from the system clock (Assuming you travel somewhere far away, adjust PC to local time zone and then call this).
Stellarium after startup:
OK, click "Get location from network":
In the log I see:
[ 156.295][DBG ] Doing OS service lookup for location...
[ 156.296][DBG ] Doing OS service lookup for location... postRequest
nothing else :(
OK, click "Get location from network" again, to disable using this feature:
WTF???
The request is handled asynchronously. The "postRequest" comment indicates request was sent off to the OS, and is expected to trigger positionUpdatedFromOS(). Hm, if the line "Position received from OS query:..." does not appear, something must be wrong with the OS location retrieval.
Effect switching to using custom time zone can be reproduced in master too :(
This may be caused by LocationDialog::ipQueryLocation(bool state). Not sure why it has
updateTimeZoneControls(!state); -- Since 2019.
This pull request has conflicts, please resolve those before we can evaluate the pull request.
Conflicts have been resolved. A maintainer will review the pull request shortly.
Shall we remove the previous IP-based lookup fallback?
Definitely no
I see a problem in that there are two asynchronous methods called. We could call the old IP method if QtPositioning result is bad. But when the QtPositioning message reply does not even appear, should we add some wait timer that fires in this case?
Debug messages should be more informative for users IMHO
The big deal: how it need test for all cases of potential troubles?
I have worked earlier this week on a desktop PC and experienced failures in StelLocationMgr::positionUpdatedFromOS(const QGeoPositionInfo &info), when a serial port was found, but no NMEA device. Now back on my notebook, pressing "Get location from GPS or system device" works again as the NMEA stuff quickly fails with port not found, then QtPositioning takes over. For debugging, we had activated extended debugging with CLI option --verbose.
The QtPositioning addon was contributed on Windows only but should actually work on all platforms where QtPositioning is working properly. I have read there may be separate plugins that may have to be activated in code first on the U*X platforms. I am not there yet.
In the last days I have modified StelLocation in this branch so that it is default-invalid (role='!'), and solved an ultimative lastResortLocation (Paris, unconditional). This alone should help avoiding #4266, you could test that on a fresh install on Linux and Mac please.
Earlier in March I tried to extend the "location from IP" button. You said it does nothing on Linux. I now tried to remove the Windows-only limit of uwes-ufo QtPositioning extension.
A few more diagnostics show:
[ 16.556][DBG ] Neither GPSD nor NMEAhelper. Try OS positionSource, one of
[ 16.556][DBG ] QList("nmea", "winrt")
[ 16.556][DBG ] Our QGeoPositionInfoSource is : "winrt"
[ 16.556][DBG ] Setting up new positionSource...
[ 16.572][DBG ] QFlags(0x1|0x2|0x4|0x8|0x10|0x20|0x40|0x80|0x100|0x200|0x400|0x800|0x1000|0x2000|0x4000|0x8000|0x10000|0x20000|0x40000|0x80000|0x100000|0x200000|0x400000|0x800000|0x1000000|0x2000000|0x4000000|0x8000000|0x10000000|0x20000000|0x40000000|0x80000000)
[ 16.611][DBG ] Setting up new positionSource...done
[ 16.899][DBG ] Location in progress: Long= 16.2599 Lat= 48.1814 Alt 0
[ 16.899][DBG ] New location named "GPS N48 E16"
[ 16.899][DBG ] queryOK, resetting GUI
Building on WSL, I get:
[ 25.627][DBG ] Neither GPSD nor NMEAhelper. Try OS positionSource, one of
[ 25.627][DBG ] QList("geoclue2", "nmea")
[ 25.627][DBG ] Our QGeoPositionInfoSource is: "geoclue2"
[ 25.627][DBG ] Setting up new positionSource...
[ 25.627][DBG ] QFlags()
[ 25.627][DBG ] Setting up new positionSource...done
So, it seems the geoclue2 plugin on Ubuntu (WSL) does not behave like the winrt plugin on Windows, which may have been why the location from IP extension did not work on Linux.
(Note that the nmea is Qt's own version, not the NMEALookupHelper Florian had made with me in 2017.)
According to https://doc.qt.io/qt-6/position-plugin-geoclue2.html, the geoclue2 plugin requires installation of
sudo apt install libgeoclue-2-0
and required dbus communication. I installed this and libgeoclue-2-dev but it changed nothing.
I am not familiar enough with dbus. How to check if if dbus is even running on WSL?
The situation is quite stupid, admittedly. The minimal solution would probably be to fix, in master, just the fallback to lastResortLocation to hit Paris, just to find ourselves in a useful location if all else fails. The "get location from GPS or OS" button may not work on all systems. Or an ifdef OS_WIN orgy in this branch tomorrow. :-(
Hmm... what about geoclue-2-demo and geoclue-2.0 packages to check on WSL?
Can you please share any information what to do after installing those? I see /etc/geoclue/geoclue.conf and added an entry for stellarium similar to the firefox entry. Changed nothing.
Hmpf...
sudo systemctl start geoclue.service
System has not been booted with systemd as init system (PID 1). Can't operate.
Failed to connect to bus: Host is down
And according to https://wiki.ubuntuusers.de/geoclue/, Mozilla has shut down their WiFi location service. But what to do to start dbus on WSL?
Can you please share any information what to do after installing those? I see /etc/geoclue/geoclue.conf and added an entry for stellarium similar to the firefox entry. Changed nothing.
I'm not familiar with geoclue and I don't have hardware with incorporated GPS/GLONASS/GALILEO/BAIDU device. I'll try use GPS/GLONASS dongle.
Ah, then probably the nmea plugin will kick in. It may work, but only for those with GPS/GLONASS hardware. But we already support operation with GPS hardware since 2017...
Alright, sorry, I think I better today deactivate again all new things around QtPositioning for non-Windows for 25.2 and open up further experiments in August, maybe on a fresh Kubuntu installed on a then-ex-Win10 workhorse. My idea was simply to provide a more accurate location when asking for a network location, But for an all-platform solution around QtPositioning, we need a workflow that incorporates the geoclue2 plugin, or that properly detects if something does not work.
Is it working on Windows?
P.S. Technically I can test it in Linux, macOS and Haiku platforms currently
Qt on Windows uses the "winrt" QGeoPositionInfoSource and just works. And of course whatever I did in February/March just worked. I have not tested recently what happens if I actively disallow geolocation (no tracking in system settings). But of course it is wise to test capabilities first before querying. Actually, I think the GPS button is now safe for Linux, it just doesn't provide data when geoclue isn't running. I still need to secure the "location from network" checkbox action.
Why is all this magic with WSL needed? If you need to test on Linux, you can just use a real VM booting real Linux (e.g. a Live CD).
I just have no time to set up everything again today, sorry. Stellarium builds and runs perfectly on WSL, just an optional system service is not available. And there may be other reasons (privacy, firewalls, ...) for QGeoPositionInfoSource not delivering data. So, I will just test whether the QGeoPositionInfoSource delivers data (without test we had the fallback to not even Paris but zero), and catch and fall back to the old path if not.
Is it fixed issue #4266 in Windows?
I never had the problem... But I am just restricting the IP lookup to valid- tested sources, and will test with disabled network later to see if I land in Paris or in null island.
OK, in system panel I can disallow location access to Stellarium. However, I still get a permission. Then the service doesn't deliver. Weird, but I can catch this. So be it...