93 lines
2.0 KiB
Go
93 lines
2.0 KiB
Go
package service
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io/ioutil"
|
|
"log"
|
|
"net/http"
|
|
"time"
|
|
)
|
|
|
|
type GeocodingService interface {
|
|
GetAddressFromCoordinates(latitude, longitude float64) (string, error)
|
|
}
|
|
|
|
type nominatimGeocoder struct {
|
|
client *http.Client
|
|
}
|
|
|
|
|
|
func NewGeocodingService() GeocodingService {
|
|
client := &http.Client{
|
|
Timeout: 10 * time.Second,
|
|
}
|
|
return &nominatimGeocoder{
|
|
client: client,
|
|
}
|
|
}
|
|
|
|
type NominatimResponse struct {
|
|
DisplayName string `json:"display_name"`
|
|
Error string `json:"error"`
|
|
}
|
|
|
|
|
|
func (g *nominatimGeocoder) GetAddressFromCoordinates(latitude, longitude float64) (string, error) {
|
|
|
|
|
|
if latitude < -90 || latitude > 90 || longitude < -180 || longitude > 180 {
|
|
errMsg := fmt.Sprintf("Invalid coordinates: lat=%f, lon=%f", latitude, longitude)
|
|
return "", fmt.Errorf(errMsg)
|
|
}
|
|
|
|
url := fmt.Sprintf(
|
|
"https://nominatim.openstreetmap.org/reverse?format=json&lat=%f&lon=%f&zoom=18&addressdetails=1",
|
|
latitude, longitude,
|
|
)
|
|
|
|
|
|
req, err := http.NewRequest("GET", url, nil)
|
|
if err != nil {
|
|
log.Printf("Request creation error: %v", err)
|
|
return "", err
|
|
}
|
|
req.Header.Set("User-Agent", "AssetManagementApp")
|
|
|
|
resp, err := g.client.Do(req)
|
|
if err != nil {
|
|
log.Printf("HTTP request error: %v", err)
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
|
|
// Read full response body
|
|
bodyBytes, err := ioutil.ReadAll(resp.Body)
|
|
if err != nil {
|
|
log.Printf("Error reading response body: %v", err)
|
|
return "", err
|
|
}
|
|
|
|
|
|
var result NominatimResponse
|
|
if err := json.Unmarshal(bodyBytes, &result); err != nil {
|
|
log.Printf("JSON unmarshal error: %v", err)
|
|
return "", err
|
|
}
|
|
|
|
// Detailed error checking
|
|
if result.Error != "" {
|
|
log.Printf("Nominatim API Error: %s", result.Error)
|
|
return "", fmt.Errorf("geocoding error: %s", result.Error)
|
|
}
|
|
|
|
// Check for empty display name
|
|
if result.DisplayName == "" {
|
|
log.Printf("No address found for coordinates: %f, %f", latitude, longitude)
|
|
return "", fmt.Errorf("no address found for these coordinates")
|
|
}
|
|
|
|
return result.DisplayName, nil
|
|
}
|
|
|