diff --git a/app.py b/app.py index fbbe5a1..165d4f0 100644 --- a/app.py +++ b/app.py @@ -89,6 +89,23 @@ def trip_route(trip_id): return jsonify(error=f"Trip not found: {trip_id}"), 404 return jsonify(trip) +@app.route('/api/geocode') +def geocode_route(): + try: + lat = float(request.args['lat']) + lon = float(request.args['lon']) + except (KeyError, ValueError): + return jsonify(error="lat and lon required"), 400 + import reverse_geocoder as rg + results = rg.search([(lat, lon)], mode=1, verbose=False) + if results: + r = results[0] + parts = [r.get('name', ''), r.get('admin1', '')] + label = ', '.join(p for p in parts if p) + else: + label = f"{lat:.5f}, {lon:.5f}" + return jsonify(label=label) + @app.route('/api/dash/devices') def dash_devices(): devices = app_dash.list_usb_storage_partitions() diff --git a/requirements.txt b/requirements.txt index 15db4d9..cd4668e 100644 --- a/requirements.txt +++ b/requirements.txt @@ -7,4 +7,4 @@ pyserial RPi.GPIO obd requests -requests-toolbelt \ No newline at end of file +requests-toolbeltreverse_geocoder diff --git a/static/js/history.js b/static/js/history.js index e7c1677..b50c714 100644 --- a/static/js/history.js +++ b/static/js/history.js @@ -32,20 +32,10 @@ if (key === _lastGeoKey) return; _lastGeoKey = key; const fallback = `${lat.toFixed(5)}, ${lon.toFixed(5)}`; - fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${lat}&lon=${lon}`, { - headers: { 'Accept-Language': 'en' }, - signal: AbortSignal.timeout(5000), - }) - .then(r => r.ok ? r.json() : null) - .then(data => { - if (!data) { replayLocation.textContent = fallback; return; } - const a = data.address || {}; - const road = a.road || a.hamlet || a.village || a.suburb || ''; - const city = a.city || a.town || a.village || a.municipality || ''; - replayLocation.textContent = [road, city].filter(Boolean).join(', ') - || data.display_name?.split(',').slice(0, 2).join(',') || fallback; - }) - .catch(() => { replayLocation.textContent = fallback; }); + fetch(`/api/geocode?lat=${lat}&lon=${lon}`, { signal: AbortSignal.timeout(4000) }) + .then(r => r.ok ? r.json() : null) + .then(data => { replayLocation.textContent = (data && data.label) ? data.label : fallback; }) + .catch(() => { replayLocation.textContent = fallback; }); } function scheduleGeocode(lat, lon) { diff --git a/static/js/yaris.js b/static/js/yaris.js index 2459f3c..b24058d 100644 --- a/static/js/yaris.js +++ b/static/js/yaris.js @@ -196,22 +196,12 @@ _recenterBtn.addEventListener('click', function () { }); function reverseGeocode(lat, lon) { - const fallback = `${lat.toFixed(5)}, ${lon.toFixed(5)}`; const el = document.getElementById('gps-location-name'); - fetch(`https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${lat}&lon=${lon}`, { - headers: { 'Accept-Language': 'en' }, - signal: AbortSignal.timeout(5000), - }) - .then(r => r.ok ? r.json() : null) - .then(data => { - if (!data) { el.textContent = fallback; return; } - const a = data.address || {}; - const name = a.road || a.hamlet || a.village || a.suburb || ''; - const city = a.city || a.town || a.village || a.municipality || ''; - const label = [name, city].filter(Boolean).join(', '); - el.textContent = label || data.display_name?.split(',').slice(0, 2).join(',') || fallback; - }) - .catch(() => { el.textContent = fallback; }); + const fallback = `${lat.toFixed(5)}, ${lon.toFixed(5)}`; + fetch(`/api/geocode?lat=${lat}&lon=${lon}`, { signal: AbortSignal.timeout(4000) }) + .then(r => r.ok ? r.json() : null) + .then(data => { el.textContent = (data && data.label) ? data.label : fallback; }) + .catch(() => { el.textContent = fallback; }); } socket.on('gps_location', function(data) {