New project : Find nearest booze shop.

Last Updated or created 2025-05-14

Or anything else. ( idea from a reddit post )

Combining a GPS module, compass, a LED ring and some code, I want to make a little device which shows you the way to the nearest … something.

To make it completely standalone, I have to use a SIM module. (Same as I have used before) This POC will use my phone as hotspot.

The LED ring will show the direction to go.

Edit: Maybe not a LED ring but a little display.

As previously posted, I was playing with Overpass turbo.
Using an API, I can use code to query this.

  • Arduino sends latitude, longitude to my webserver
  • Webserver queries API for neastest POIs and calculates distance.
  • Send data from webserver to arduino
  • Arduino uses heading data to light up direction LED
    (also on secondary display with distance info?)
    edit: and shop info

Test code for my web server to query the data

import overpy
import math

api = overpy.Overpass()

# This location will be filled with data from GPS module on Arduino.
latitude = 52.2270745        # Center latitude (e.g. Berlin)
longitude = 5.177519      # Center longitude
box_size = 0.05         # Box size in degrees (about ~5 km)

south = latitude - box_size
north = latitude + box_size
west = longitude - box_size
east = longitude + box_size

def haversine(lat1, lon1, lat2, lon2):
    R = 6371  # Earth radius in km
    phi1 = math.radians(lat1)
    phi2 = math.radians(lat2)
    d_phi = math.radians(lat2 - lat1)
    d_lambda = math.radians(lon2 - lon1)

    a = math.sin(d_phi / 2)**2 + math.cos(phi1) * math.cos(phi2) * math.sin(d_lambda / 2)**2
    c = 2 * math.atan2(math.sqrt(a), math.sqrt(1 - a))

    return R * c  # Distance in kilometers

# Calculate bearing in degrees (0-360)
def bearing(lat1, lon1, lat2, lon2):
    phi1 = math.radians(lat1)
    phi2 = math.radians(lat2)
    delta_lon = math.radians(lon2 - lon1)

    x = math.sin(delta_lon) * math.cos(phi2)
    y = math.cos(phi1) * math.sin(phi2) - math.sin(phi1) * math.cos(phi2) * math.cos(delta_lon)

    initial_bearing = math.atan2(x, y)
    compass_bearing = (math.degrees(initial_bearing) + 360) % 360  # Normalize to 0–360

    return compass_bearing

# Overpass QL query
query = f"""
[out:json];
node
  ["shop"="alcohol"]
  ({south}, {west}, {north}, {east});
out body;
>;
out skel qt;
"""

try:
    result = api.query(query)

    # Collect and sort places by distance
    places = []
    for node in result.nodes:
        node_lat = float(node.lat)
        node_lon = float(node.lon)
        distance = haversine(latitude, longitude, node_lat, node_lon)
        direction = bearing(latitude, longitude, node_lat, node_lon)
        name = node.tags.get("name", "Unnamed")
        places.append((distance, direction, name, node_lat, node_lon))

    places.sort()

    print(f"Found {len(places)} alcohol-related places sorted by distance:")
    for dist, dir_deg, name, lat, lon in places:
        print(f"- {name} at ({lat:.5f}, {lon:.5f}) — {dist:.2f} km, {dir_deg:.0f}°")

except Exception as e:
    print(f"Error: {e}")

Output:

Found 10 alcohol-related places sorted by distance:
- The Skiff at (52.22583, 5.17860) — 0.16 km, 152°
- Onzewijnen at (52.22612, 5.17045) — 0.49 km, 258°
- Gall & Gall at (52.23244, 5.19204) — 1.15 km, 59°
- Gall & Gall at (52.21536, 5.16735) — 1.48 km, 208°
- Eric's Beer Craft at (52.21549, 5.16632) — 1.50 km, 211°
- Slijterij at (52.21082, 5.15692) — 2.29 km, 218°
- Gall & Gall at (52.21590, 5.14074) — 2.80 km, 244°
- Gall & Gall at (52.25422, 5.22705) — 4.53 km, 48°
- Gall & Gall at (52.26808, 5.18348) — 4.58 km, 5°
- Il DiVino at (52.27507, 5.16414) — 5.41 km, 350°

Example using Overpass Turbo to find breweries

Spread the love

Leave a Reply

Your email address will not be published. Required fields are marked *