From 953852e6e984f8a639cf1a5ac4116fff755d538a Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Thu, 7 May 2015 15:39:42 +1200 Subject: Add Gisgraphy reverse geocoder --- src/org/traccar/geocode/AddressFormat.java | 4 ++ .../traccar/geocode/GisgraphyReverseGeocoder.java | 67 ++++++++++++++++++++++ src/org/traccar/geocode/GoogleReverseGeocoder.java | 62 +++++++++++++------- .../traccar/geocode/NominatimReverseGeocoder.java | 49 +++++++++++++--- src/org/traccar/geocode/ReverseGeocoder.java | 2 +- 5 files changed, 153 insertions(+), 31 deletions(-) create mode 100644 src/org/traccar/geocode/GisgraphyReverseGeocoder.java (limited to 'src/org/traccar/geocode') diff --git a/src/org/traccar/geocode/AddressFormat.java b/src/org/traccar/geocode/AddressFormat.java index 972326975..a90de8c5e 100644 --- a/src/org/traccar/geocode/AddressFormat.java +++ b/src/org/traccar/geocode/AddressFormat.java @@ -35,6 +35,10 @@ public class AddressFormat extends Format { private final String format; + public AddressFormat() { + this("%h %r, %t, %s, %c"); + } + public AddressFormat(String format) { this.format = format; } diff --git a/src/org/traccar/geocode/GisgraphyReverseGeocoder.java b/src/org/traccar/geocode/GisgraphyReverseGeocoder.java new file mode 100644 index 000000000..9d513a6f5 --- /dev/null +++ b/src/org/traccar/geocode/GisgraphyReverseGeocoder.java @@ -0,0 +1,67 @@ +/* + * Copyright 2015 Anton Tananaev (anton.tananaev@gmail.com) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.traccar.geocode; + +import org.traccar.helper.Log; + +import javax.json.Json; +import javax.json.JsonObject; +import java.io.InputStreamReader; +import java.net.URL; +import java.net.URLConnection; + +public class GisgraphyReverseGeocoder implements ReverseGeocoder { + + private final String url; + + public GisgraphyReverseGeocoder() { + this("http://services.gisgraphy.com/street/streetsearch"); + } + + public GisgraphyReverseGeocoder(String url) { + this.url = url + "?format=json&lat=%f&lng=%f&from=1&to=1"; + } + + @Override + public String getAddress(AddressFormat format, double latitude, double longitude) { + + try { + Address address = new Address(); + URLConnection conn = new URL(String.format(url, latitude, longitude)).openConnection(); + + JsonObject json = Json.createReader(new InputStreamReader(conn.getInputStream())).readObject(); + JsonObject result = json.getJsonArray("result").getJsonObject(0); + + if (result.containsKey("name")) { + address.setStreet(result.getString("name")); + } + if (result.containsKey("isIn")) { + address.setSettlement(result.getString("isIn")); + } + if (result.containsKey("countryCode")) { + address.setCountry(result.getString("countryCode")); + } + + return format.format(address); + + } catch(Exception error) { + Log.warning(error); + } + + return null; + } + +} diff --git a/src/org/traccar/geocode/GoogleReverseGeocoder.java b/src/org/traccar/geocode/GoogleReverseGeocoder.java index 4ec6e10af..dae9915d8 100644 --- a/src/org/traccar/geocode/GoogleReverseGeocoder.java +++ b/src/org/traccar/geocode/GoogleReverseGeocoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2012 - 2013 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2012 - 2015 Anton Tananaev (anton.tananaev@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,42 +15,62 @@ */ package org.traccar.geocode; -import java.io.BufferedReader; -import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; -import java.nio.charset.Charset; import org.traccar.helper.Log; +import javax.json.*; + public class GoogleReverseGeocoder implements ReverseGeocoder { - private final static String MARKER = "\"formatted_address\" : \""; + private final String url = "http://maps.googleapis.com/maps/api/geocode/json?latlng=%f,%f"; @Override - public String getAddress(double latitude, double longitude) { + public String getAddress(AddressFormat format, double latitude, double longitude) { try { - URL url = new URL("http://maps.googleapis.com/maps/api/geocode/json?latlng=" + latitude + "," + longitude + "&sensor=false"); - URLConnection connection = url.openConnection(); - - connection.setRequestProperty("Content-Type", "application/json;charset=UTF-8"); - - BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(),Charset.forName("UTF-8"))); - - // Find address line - String line; - while ((line = reader.readLine()) != null) { - int index = line.indexOf(MARKER); - if (index != -1) { - return line.substring(index + MARKER.length(), line.length() - 2); + Address address = new Address(); + URLConnection conn = new URL(String.format(url, latitude, longitude)).openConnection(); + + JsonObject json = Json.createReader(new InputStreamReader(conn.getInputStream())).readObject(); + JsonObject result = (JsonObject) json.getJsonArray("results").get(0); + JsonArray components = result.getJsonArray("address_components"); + + for (JsonObject component : components.getValuesAs(JsonObject.class)) { + + String value = component.getString("short_name"); + + for (JsonString type : component.getJsonArray("types").getValuesAs(JsonString.class)) { + if (type.getString().equals("street_number")) { + address.setHouse(value); + break; + } else if (type.getString().equals("route")) { + address.setStreet(value); + break; + } else if (type.getString().equals("locality")) { + address.setSettlement(value); + break; + } else if (type.getString().equals("administrative_area_level_2")) { + address.setDistrict(value); + break; + } else if (type.getString().equals("administrative_area_level_1")) { + address.setState(value); + break; + } else if (type.getString().equals("country")) { + address.setCountry(value); + break; + } else if (type.getString().equals("postal_code")) { + address.setPostcode(value); + break; + } } } - reader.close(); + return format.format(address); - } catch(IOException error) { + } catch(Exception error) { Log.warning(error); } diff --git a/src/org/traccar/geocode/NominatimReverseGeocoder.java b/src/org/traccar/geocode/NominatimReverseGeocoder.java index c9393da42..911e0fa71 100644 --- a/src/org/traccar/geocode/NominatimReverseGeocoder.java +++ b/src/org/traccar/geocode/NominatimReverseGeocoder.java @@ -1,5 +1,5 @@ /* - * Copyright 2014 Anton Tananaev (anton.tananaev@gmail.com) + * Copyright 2014 - 2015 Anton Tananaev (anton.tananaev@gmail.com) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -15,8 +15,12 @@ */ package org.traccar.geocode; +import java.io.InputStreamReader; import java.net.URL; import java.net.URLConnection; +import javax.json.Json; +import javax.json.JsonArray; +import javax.json.JsonObject; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -26,23 +30,50 @@ import org.w3c.dom.Document; public class NominatimReverseGeocoder implements ReverseGeocoder { private final String url; + + public NominatimReverseGeocoder() { + this("http://nominatim.openstreetmap.org/reverse"); + } public NominatimReverseGeocoder(String url) { - this.url = url + "?format=xml&lat=%f&lon=%f&zoom=18&addressdetails=0"; + this.url = url + "?format=json&lat=%f&lon=%f&zoom=18&addressdetails=1"; } @Override - public String getAddress(double latitude, double longitude) { + public String getAddress(AddressFormat format, double latitude, double longitude) { try { - + Address address = new Address(); URLConnection conn = new URL(String.format(url, latitude, longitude)).openConnection(); - DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); - DocumentBuilder builder = factory.newDocumentBuilder(); - Document doc = builder.parse(conn.getInputStream()); - - return doc.getFirstChild().getLastChild().getFirstChild().getNodeValue(); + JsonObject json = Json.createReader(new InputStreamReader(conn.getInputStream())).readObject().getJsonObject("address"); + + if (json.containsKey("house_number")) { + address.setHouse(json.getString("house_number")); + } + if (json.containsKey("road")) { + address.setStreet(json.getString("road")); + } + if (json.containsKey("village")) { + address.setSettlement(json.getString("village")); + } + if (json.containsKey("city")) { + address.setSettlement(json.getString("city")); + } + if (json.containsKey("state_district")) { + address.setDistrict(json.getString("state_district")); + } + if (json.containsKey("state")) { + address.setState(json.getString("state")); + } + if (json.containsKey("country_code")) { + address.setCountry(json.getString("country_code").toUpperCase()); + } + if (json.containsKey("postcode")) { + address.setPostcode(json.getString("postcode")); + } + + return format.format(address); } catch(Exception error) { Log.warning(error); diff --git a/src/org/traccar/geocode/ReverseGeocoder.java b/src/org/traccar/geocode/ReverseGeocoder.java index 67ce68ac2..b19a6b7ce 100644 --- a/src/org/traccar/geocode/ReverseGeocoder.java +++ b/src/org/traccar/geocode/ReverseGeocoder.java @@ -17,6 +17,6 @@ package org.traccar.geocode; public interface ReverseGeocoder { - public String getAddress(double latitude, double longitude); + public String getAddress(AddressFormat format, double latitude, double longitude); } -- cgit v1.2.3