Use Google-Geocode API to get location string from coordinates

Hi all,

a small rule example - maybe useful to someone on how to get a human readable location string from a location item:

Item

String PatrikLocationString "Patrik [%s]" <place>

Rule

/// ...
val String GoogleAPIKey = "<your google API key>" // not sure if mandatory
/// ...
rule LocationStringPatrik
  when
    Item PatrikLocation changed
  then
    val PointType locationPatrik = (PatrikLocation.state) as PointType
    val patrikLatitude = locationPatrik.latitude
    val patrikLongitude = locationPatrik.longitude
    
    val geocodeURL = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" + patrikLatitude + "," + patrikLongitude + "&sensor=true&key=" + GoogleAPIKey
    
    val String gecodeResponse = sendHttpGetRequest(geocodeURL)
    val String formattedAddress = transform("JSONPATH", "$.results[0].formatted_address", gecodeResponse)
    
    PatrikLocationString.postUpdate(formattedAddress)
  end

with kind regards,
Patrik

11 Likes

Thank you, Patrik! I’ve been wondering how to do this. Very helpful!

Hi, i am trying to get this figured out. I have my location (item= DeviceID1_coords; it is lat,long together) plotted on a Map taken from your great GoogleMap V3 API html. So now i would like to show address on there. I assume that is what this can do? My rule looks like this

/// ...
val String GoogleAPIKey = "Number HERE" // not sure if mandatory
/// ...
rule GeoMap_address
  when
    Item DeviceID1_coords changed
  then
    val PointType location_DeviceID1 = (DeviceID1_coords.state) as PointType
    //val patrikLatitude = locationPatrik.latitude
    //val patrikLongitude = locationPatrik.longitude
    
    val geocodeURL = "https://maps.googleapis.com/maps/api/geocode/json?latlng=" DeviceID1_coords "&sensor=true&key=" + GoogleAPIKey
    
    val String gecodeResponse = sendHttpGetRequest(geocodeURL)
    val String formattedAddress = transform("JSONPATH", "$.results[0].formatted_address", gecodeResponse)
    
    DeviceID1_coordsString.postUpdate(formattedAddress)
  end
  

i // out long and lat b/c they should already be combined in the first val (?). I can run the geocode URL manually putting in the item value (ie, long / lat) and it gives the proper page of outputs it seems. But wondering what I need to do to put it on top of my location map – and it does not seem to work unless i add the coordinates manually at the end of the URL in browser. I am certain to have messed some things up.
Thanks

Hi,

try to add “+” to concat the string:
https://maps.googleapis.com/maps/api/geocode/json?latlng=" + DeviceID1_coords + “&sensor=true&key=” + GoogleAPIKey

let me know if this does not work.
with kind regards,
Patrik

Thank you Patrik,
I made the change, but do not see any address applied to the map. Let me know what else i could provide (i may not be able to reply for several days).

Best,
Tim

Can you add “println” statements in your rule to print out the url and the response to the console?

Do you use “Designer” to create your rules? If not I strongly recommend this to validate syntax.

with kind regards,
Patrik

Thank you Patrik,

I have in the past but not this time. Just put it through that, and says the value of location_DeviceID1 is not used. Also “DeviceID1_coordsString” is underfined.

When I get back, I will put printIn into the rule.

Thank you.

Do you use item files, or paper UI to create the items?

I mostly use items files.

This is the one to grab the locations.

Switch DeviceID1_presence
Number DeviceID1_distance 
Switch DeviceID2_presence
Number DeviceID2_distance

String PollRate
String NextPollTime
String ErrorStatus

String DeviceID1_coords
Number DeviceID1_accuracy 
String DeviceID2_coords
Number DeviceID2_accuracy 

I also added

Location location_DeviceID1

But not really sure how this one works or where needed.

Thank you

… here my current code - hope it helps:

Items:

String ItemMQTT { mqtt="<[broker:owntracks/jkmtnngq/android:state:default]" }
String ItemPatrikLocationHistory
String PatrikLocationString "Patrik [%s]" <place>

Location ItemPatrikLocation "Patrik" <location>

Number ItemPatrikLocationAccuracy
Number ItemPatrikNatelBattery "Natel Patrik [%d %%]" <battery> (GroupPersistrrd4jMinute,GroupBattery)

DateTime ItemPatrikLastPositionUpdate "Patrik - letztes Update [%1$tH:%1$tM, %1$td.%1$tm.%1$ty]" <location>

Switch ItemPatrikAtHome "Patrik" <home>

Rule:

rule "LocationPatrikChanged"
    when
        Item ItemPatrikLocation changed    
    then
        val _apiKey = ItemGoogleMapAPIKey.state
        val _position = ItemPatrikLocation.state as PointType
        val _url =  "https://maps.googleapis.com/maps/api/geocode/json?latlng=" 
                    + _position.latitude  + "," 
                    + _position.longitude 
                    + "&sensor=true&key=" + _apiKey

        val _geocodeJSON = sendHttpGetRequest(_url)
        val _address = transform("JSONPATH", "$.results[0].formatted_address", _geocodeJSON)

        PatrikLocationString.postUpdate(_address)
    end

Thank you Patrik! I will test this out today.

Patrik, I am almost there. My rule is below - note: since DeviceID1_coords has lat,long combined, i only use “_position” in url.

This now does get me to a url with a whole bunch of unformatted data - and i can see the address in some parts (ie, under formatted address of the url page).

rule "GeoMap_address"
    when
        Item DeviceID1_coords changed    
    then
        val _apiKey = "<myAPIkey>"
        val _position = DeviceID1_coords.state as PointType
        val _url =  "https://maps.googleapis.com/maps/api/geocode/json?latlng=" 
                    + _position
                    + "&sensor=true&key=" + _apiKey

        val _geocodeJSON = sendHttpGetRequest(_url)
        val _address = transform("JSONPATH", "$.results[0].formatted_address", _geocodeJSON)

        DeviceID1_LocationString.postUpdate(_address)
    end

The problem is, I am not getting a clean address in my ‘DeviceID1_LocationString’ – it is pulling in all the information from that url, in the unformatted form. I put 'String DeviceID1_LocationString “DeviceID1 [%s]” in my items.

[In the end, I would just want to pull the address and the town. ]

Any idea where I am off? Thanks again.

@Sabre66 -

Try this…it works for me:

 rule "GeoMap_address"
 when
 	Item DeviceID1_coords changed
 then
 	val _url = "http://maps.googleapis.com/maps/api/geocode/json?latlng=" + DeviceID1_coords.state.toString + "&language=english&sensor=false"
 	val _geocodeJSON = sendHttpGetRequest(_url)
    val _address = transform("JSONPATH", "$.results[0].formatted_address", _geocodeJSON)
    DeviceID1_LocationString.postUpdate(_address)
 end

[Edit:] I guess you’ll probably want to add your API key back in. I just didn’t have one for testing.

Thanks Peter,

But even with that i am still getting all the non-parsed data, not just the formatted_address.

could my “JSONPATH” be wrong?

Did you verify that the JSONPATH transform is installed? There are nice online tools where you can check your path, e.g. http://jsonpath.com/.

sorry, I did not have JSONPath transformation installed.

Ok, got it to work. Also needed .toString to be added, and included language as per Peter.

I get the proper results in Habpanel and rest, but my sitemap does not yet show the address – will have to play with it.

Thanks guys!

Same here, log show the updated information but not being displayed in sitemap. Did you find a way to display it in sitemap?

Hi,

can you post the log and possible related error(s)?
I’ll extend the 1st post with an example on how to display the info on the sitemap … but if you have it stored in an item you basically just add it to a/the sitemap.

That’s what I’ve done, just adding to the sitemap whereas the Group get’s named, not a text item
Group item=giPhone
Mapview item=iPhone_Coordinates_M height=5
Mapview item=iPhone_Coordinates_A height=5

So the item gets updated. the item is of type string:
String Location_String "Ort " <place_2> (giPhone)
Logfile: (can’t see any error in there)

2017-08-02 16:45:01.257 [ItemStateChangedEvent ] - iPhone_Location_Timestamp_A changed from 2017-08-02T16:35:23.942+0200 to 2017-08-02T16:40:09.594+0200
2017-08-02 16:45:01.285 [ItemStateChangedEvent ] - iPhone_Coordinates_A changed from 48.1234…,8.12345… to 48.3456…4,8.3456…
2017-08-02 16:45:01.601 [ItemStateChangedEvent ] - Location_String changed from Street 123, 12345 City, Germany to Street 456, 45678 City, Germany

So the item gets updated. the item is of type string:
String Location_String "Ort " <place_2> (giPhone)

–> Will try the text item as next

Change "Ort" to "Ort [%s]"