RhetTbull / locationator

A simple macOS menubar app that provides access to the macOS Location Services reverse geocoding API via a local web server as well as a command line tool.
MIT License
17 stars 0 forks source link

Any chance to be able to query the current location Lat/Long? Seems like that functionality is not exposed currently? #12

Closed realityexpander closed 2 months ago

realityexpander commented 3 months ago

I have been scouring the web for a solution that allows CLI to access the location info, and surprisingly, this topic seems to be "not a thing" due to increased permissions by Apple OS's lately...

Getting this info in the browser is trivial.

Any hints about this?

RhetTbull commented 3 months ago

It's not possible with the current code but should be easy to add a call to CLLocationManager.requestLocation() to request the current location. I don't have time to look at this this week but I don't think it'll be hard -- will take a look as soon as I can. The trick in Python is that because this method returns immediately (the location request is asynchronous), you need to create a threading event and then call the event's set() in the callback that requestLocation will call.

RhetTbull commented 3 months ago

But of course, you'll have the same limitations as Locationator does -- you can't do this from the command line alone as the app needs to be able to request the proper permissions which can be done only through the GUI. But Locationator could easily provide a REST API endpoint your CLI could call (which is what it does now).

realityexpander commented 3 months ago

But Locationator could easily provide a REST API endpoint your CLI could call (which is what it does now).

I'm looking at the docs and don't see where I can make that API call to the server... am I missing something?

I only see the Geocoding calls.

RhetTbull commented 3 months ago

I took a quick stab at this but it failed with error. Will explore when I have more time (working on my taxes though I'd rather be working on this ;-) ) Requesting the location calls the delegate (which in Locationator is the main Locationator class) but it gives an error. Here's the diff if you want to work on this:

diff --git a/locationator/locationator.py b/locationator/locationator.py
index 4b53ce9..afb1682 100644
--- a/locationator/locationator.py
+++ b/locationator/locationator.py
@@ -129,6 +129,9 @@ class Locationator(rumps.App):
         self.menu_reverse_geocode = rumps.MenuItem(
             "Reverse geocode...", callback=self.on_reverse_geocode
         )
+        self.menu_current_location = rumps.MenuItem(
+            "Current location", callback=self.on_current_location
+        )
         self.menu_about = rumps.MenuItem(f"About {APP_NAME}", callback=self.on_about)
         self.menu_quit = rumps.MenuItem(f"Quit {APP_NAME}", callback=self.on_quit)
         self.menu_start_on_login = rumps.MenuItem(
@@ -141,6 +144,7 @@ class Locationator(rumps.App):
         self.menu = [
             # self.menu_auth_status,
             self.menu_reverse_geocode,
+            self.menu_current_location,
             None,
             self.menu_start_on_login,
             self.menu_install_tools,
@@ -250,6 +254,13 @@ class Locationator(rumps.App):
                 location, _geocode_completion_handler
             )

+    def on_current_location(self, sender):
+        """Request current location from Location Services"""
+        NSLog(str(self.location_manager.authorizationStatus()))
+        self.location_manager.startUpdatingLocation()
+        # self.location_manager.requestLocation()
+        # self.location_manager.stopUpdatingLocation()
+
     def on_install_remove_tools(self, sender):
         """Install or remove the command line tools"""
         if sender.title.startswith("Install"):
@@ -598,6 +609,15 @@ class Locationator(rumps.App):
             open_kwargs["encoding"] = encoding
         return open(*open_args, **open_kwargs)

+    def locationManager_didUpdateLocations_(
+        self, manager: CLLocationManager, locations: list[CLLocation]
+    ):
+        """Called when location is updated"""
+        self.log(f"didUpdateLocations: {manager} {locations}")
+
+    def locationManager_didFailWithError_(self, manager: CLLocationManager, error: Any):
+        """Handle errors from CLLocationManager"""
+        self.log(f"locationManager_didFailWithError_: {manager} {error}")

 def placemark_to_dict(placemark: CLPlacemark) -> dict:
     """Convert a CLPlacemark to a dict
realityexpander commented 2 months ago

Unfortunately, I’m as newbie on iOS. My primary is Android Native and then web dev. I’m new to iOS when I started working the Kotlin Multi-platform, so I have zero experience with Objective-C.

Thanks for the quick update! Chris

On Apr 7, 2024, at 5:12 PM, Rhet Turnbull @.***> wrote:

I took a quick stab at this but it failed with error. Will explore when I have more time (working on my taxes though I'd rather be working on this ;-) ) Requesting the location calls the delegate (which in Locationator is the main Locationator class) but it gives an error. Here's the diff if you want to work on this:

diff --git a/locationator/locationator.py b/locationator/locationator.py index 4b53ce9..afb1682 100644 --- a/locationator/locationator.py +++ b/locationator/locationator.py @@ -129,6 +129,9 @@ class Locationator(rumps.App): self.menu_reverse_geocode = rumps.MenuItem( "Reverse geocode...", callback=self.on_reverse_geocode )

  • self.menu_current_location = rumps.MenuItem(

  • "Current location", callback=self.on_current_location

  • ) self.menu_about = rumps.MenuItem(f"About {APP_NAME}", callback=self.on_about) self.menu_quit = rumps.MenuItem(f"Quit {APP_NAME}", callback=self.on_quit) self.menu_start_on_login = rumps.MenuItem( @@ -141,6 +144,7 @@ class Locationator(rumps.App): self.menu = [

    self.menu_auth_status,

         self.menu_reverse_geocode,
  • self.menu_current_location, None, self.menu_start_on_login, self.menu_install_tools, @@ -250,6 +254,13 @@ class Locationator(rumps.App): location, _geocode_completion_handler )

  • def on_current_location(self, sender):

  • """Request current location from Location Services"""

  • NSLog(str(self.location_manager.authorizationStatus()))

  • self.location_manager.startUpdatingLocation()

  • self.location_manager.requestLocation()

  • self.location_manager.stopUpdatingLocation()

  • def on_install_remove_tools(self, sender): """Install or remove the command line tools""" if sender.title.startswith("Install"): @@ -598,6 +609,15 @@ class Locationator(rumps.App): open_kwargs["encoding"] = encoding return open(*open_args, **open_kwargs)

  • def locationManagerdidUpdateLocations(

  • self, manager: CLLocationManager, locations: list[CLLocation]

  • ):

  • """Called when location is updated"""

  • self.log(f"didUpdateLocations: {manager} {locations}")

  • def locationManagerdidFailWithError(self, manager: CLLocationManager, error: Any):

  • """Handle errors from CLLocationManager"""

  • self.log(f"locationManagerdidFailWithError: {manager} {error}")

    def placemark_to_dict(placemark: CLPlacemark) -> dict: """Convert a CLPlacemark to a dict — Reply to this email directly, view it on GitHub https://github.com/RhetTbull/locationator/issues/12#issuecomment-2041625235, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABHLEYQJHTDS5GPZVEDFY4LY4HAGHAVCNFSM6AAAAABF3S465GVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDANBRGYZDKMRTGU. You are receiving this because you authored the thread.

RhetTbull commented 2 months ago

I figured this out. Working on an update but may be a few days.

realityexpander commented 2 months ago

WOW! That’s amazing to hear!

I went thru at least 6 different approaches to this seemingly simple problem, but after Ventura, this is very locked down.

Anyway, I have no rush on this, and it’s good to hear you are working on this as it seems yours will be the only solution for using the command line to access the current GPS location.

Best, Chris

On Apr 9, 2024, at 2:13 PM, Rhet Turnbull @.***> wrote:

I figured this out. Working on an update but may be a few days.

— Reply to this email directly, view it on GitHub https://github.com/RhetTbull/locationator/issues/12#issuecomment-2045896315, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABHLEYQ7GPDPLL7ALX4NWADY4Q4WNAVCNFSM6AAAAABF3S465GVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDANBVHA4TMMZRGU. You are receiving this because you authored the thread.

RhetTbull commented 2 months ago

I've got this partially working. I can get the location once but subsequent calls produce an error. Once I figure it out, the API will look the following so you can hit the API from any app that can make an HTTP request and get back a JSON object with location:

http GET localhost:8000/current_location
Content-type: text/plain
Date: Fri, 12 Apr 2024 13:11:27 GMT
Server: SimpleHTTP/0.6 Python/3.11.7

{
    "altitude": 0.0,
    "course": -1.0,
    "error": null,
    "horizontal_accuracy": 35.0,
    "latitude": 38.82347632466596,
    "longitude": -104.64334336698116,
    "speed": -1.0,
    "timestamp": "2024-04-12T07:11:27.528566",
    "vertical_accuracy": -1.0
}
realityexpander commented 2 months ago

WOW! Amazing… Returning a cached result and error code would be acceptable, or maybe that should be up to the user’s application (im imagining here)

Thanks for the update and I look forward to using your project!

Chris

On Apr 12, 2024, at 8:13 AM, Rhet Turnbull @.***> wrote:

I've got this partially working. I can get the location once but subsequent calls produce an error. Once I figure it out, the API will look the following so you can hit the API from any app that can make an HTTP request and get back a JSON object with location:

http GET localhost:8000/current_location Content-type: text/plain Date: Fri, 12 Apr 2024 13:11:27 GMT Server: SimpleHTTP/0.6 Python/3.11.7

{ "altitude": 0.0, "course": -1.0, "error": null, "horizontal_accuracy": 35.0, "latitude": 38.82347632466596, "longitude": -104.64334336698116, "speed": -1.0, "timestamp": "2024-04-12T07:11:27.528566", "vertical_accuracy": -1.0 } — Reply to this email directly, view it on GitHub https://github.com/RhetTbull/locationator/issues/12#issuecomment-2051739039, or unsubscribe https://github.com/notifications/unsubscribe-auth/ABHLEYWTBLE4DBU76G7VZNLY47MYFAVCNFSM6AAAAABF3S465GVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMZDANJRG4ZTSMBTHE. You are receiving this because you authored the thread.

RhetTbull commented 2 months ago

Implemented in release 0.2.0. See docs here for new /current_location endpoint.

RhetTbull commented 2 months ago

@all-contributors please add @realityexpander for ideas

allcontributors[bot] commented 2 months ago

@RhetTbull

I've put up a pull request to add @realityexpander! :tada:

realityexpander commented 2 months ago

Thanks again for doing this!