Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Windows GPS Location Service in a Python Script

I have been doing some research and can't find any information on the topic. I am running a Windows 10 version that has a GPS feature for apps to use, this can be enabled or disabled by the user. I want to know how to access and use it through a python script, assuming it is even possible.

Note: I don't want any solution to get the location through an IP geolocation service. Much like using the gps service of a mobile device in android apps.

Preferably python3 libs and modules.

like image 971
M.M Avatar asked Jun 06 '17 22:06

M.M


People also ask

How do I import a GPS into Python?

Python code Importing packages and data: To draw geographic coordinates on the image, coordinates must be converted to image pixels. Method scale_to_img(gps_coordinate, (image_height, image_width)) takes the GPS coordinates and converts it to image coordinates (pixels) based on the image width and height.


3 Answers

This may be a late response, but I have recently wanted (mostly out of curiosity) to achieve this same thing b/c my company just purchased GPS-Enabled Microsoft Surface Go tablets (running win10) to take out into the field. I wanted to create a small app that records where you are and gives you relevant data on your surroundings based on information from our own database.

The answer came with a bit of digging, and I really wanted to use pywin32 to access the Location API, but this endeavor fizzled out quickly, as there is no information on the subject and working with .dlls is not my cup of tea. (If anyone has a working example of that, please share!) I am guessing that since hardly any Windows 10 devices are equipped with GPS, there has been little to no reason to accomplish the task, especially using python...

But the answer soon came in this thread about using PowerShell commands to access the Location API. I don't have much experience with PowerShell/shelling commands with another language but I knew this could be the right path. There is a lot of information out there about using the subprocess module of python, and I should mention there are security concerns as well.

Anyways, here is a quick snippet of code that will grab your location (I have verified something very similar to this works with our GPS-Enabled Microsoft Surface Go to get accuracy to 3 meters) - the only thing (as there is always something) is that the CPU tends to be faster than the GPS, and will default to your IP/MAC address or even the wildly inaccurate cellular triangulation to get your position as fast as possible (hmm facepalm from 2016 perhaps?). Therefore there are wait commands, and I implemented an accuracy builder (this can be removed to search for a required accuracy) to make sure it searches for fine accuracy before accepting coarser values because I had issues with it grabbing cellular location too quickly, even when GPS could get me 3-meter accuracy in the same spot! If anyone is interested in this, please test/tinker and let me know if it works or not. There are undoubtedly issues that will arise with a workaround like this, so beware.

Disclaimer: I am not a computer science major nor know as much as most programmers. I am a self-taught engineer, so just know that this was written by one. If you do have insights into my code, lay it on me! I'm always learning.

import subprocess as sp
import re
import time

wt = 5 # Wait time -- I purposefully make it wait before the shell command
accuracy = 3 #Starting desired accuracy is fine and builds at x1.5 per loop

while True:
    time.sleep(wt)
    pshellcomm = ['powershell']
    pshellcomm.append('add-type -assemblyname system.device; '\
                      '$loc = new-object system.device.location.geocoordinatewatcher;'\
                      '$loc.start(); '\
                      'while(($loc.status -ne "Ready") -and ($loc.permission -ne "Denied")) '\
                      '{start-sleep -milliseconds 100}; '\
                      '$acc = %d; '\
                      'while($loc.position.location.horizontalaccuracy -gt $acc) '\
                      '{start-sleep -milliseconds 100; $acc = [math]::Round($acc*1.5)}; '\
                      '$loc.position.location.latitude; '\
                      '$loc.position.location.longitude; '\
                      '$loc.position.location.horizontalaccuracy; '\
                      '$loc.stop()' %(accuracy))

    #Remove >>> $acc = [math]::Round($acc*1.5) <<< to remove accuracy builder
    #Once removed, try setting accuracy = 10, 20, 50, 100, 1000 to see if that affects the results
    #Note: This code will hang if your desired accuracy is too fine for your device
    #Note: This code will hang if you interact with the Command Prompt AT ALL 
    #Try pressing ESC or CTRL-C once if you interacted with the CMD,
    #this might allow the process to continue

    p = sp.Popen(pshellcomm, stdin = sp.PIPE, stdout = sp.PIPE, stderr = sp.STDOUT, text=True)
    (out, err) = p.communicate()
    out = re.split('\n', out)

    lat = float(out[0])
    long = float(out[1])
    radius = int(out[2])

    print(lat, long, radius)
like image 55
J.F-22 Avatar answered Oct 18 '22 00:10

J.F-22


On one hand, from the Microsoft Location API documentation you will find, LocationDisp.DispLatLongReport object which has these properties:

  • Altitude
  • AltitudeError
  • ErrorRadius
  • Latitude
  • Longitude
  • Timestamp

And on the other hand by using Python pywin32 module (or ctype module), you will get access to the Windows API (or any Windows DLL), so finally you could get the Lat & Long as you want.

If you need help, to use the pywin32 module you may take a look here.

like image 37
A STEFANI Avatar answered Oct 18 '22 01:10

A STEFANI


Install winsdk with pip install winsdk

Then use this code (source):

import asyncio
import winsdk.windows.devices.geolocation as wdg


async def getCoords():
    locator = wdg.Geolocator()
    pos = await locator.get_geoposition_async()
    return [pos.coordinate.latitude, pos.coordinate.longitude]


def getLoc():
    try:
        return asyncio.run(getCoords())
    except PermissionError:
        print("ERROR: You need to allow applications to access you location in Windows settings")


print(getLoc())

It makes use of Windows.Devices.Geolocation Namespace.

like image 1
the_redburn Avatar answered Oct 18 '22 02:10

the_redburn