Does anyone know an easy way in OH3 to reverse geocode the location channel of a GPStracker Thing?
The channel returns GPS coordinates, but I’d need the address corresponding to that location.
You can try to use the exec binding or the http binding.
A request with wget would look like:
wget "https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/reverseGeocode?f=pjson&featureTypes=&location=-0.1249710976555222,51.526172028215704" -O result.txt
Result would be:
{
"address": {
"Match_addr": "37 Tavistock Place, London, England, WC1H 9",
"LongLabel": "37 Tavistock Place, London, England, WC1H 9, GBR",
"ShortLabel": "37 Tavistock Place",
"Addr_type": "PointAddress",
"Type": "",
"PlaceName": "",
"AddNum": "37",
"Address": "37 Tavistock Place",
"Block": "",
"Sector": "",
"Neighborhood": "",
"District": "",
"City": "London",
"MetroArea": "",
"Subregion": "London",
"Region": "England",
"Territory": "",
"Postal": "WC1H 9",
"PostalExt": "",
"CountryCode": "GBR"
},
"location": {
"x": -0.1249710976555222,
"y": 51.526172028215704,
"spatialReference": {
"wkid": 4326,
"latestWkid": 4326
}
}
}
The GPS coordinates are dynamic and stored in an item.
I do not know how I can use the value of an item in the exec command of another thing.
Item = GPSTracker_Address
Channel/item containing the GPS coordinates is GPSTracker_Location
You can use the API-Explorer ( in the administration area ) to construct the curl command that can be used to get the value from the item. That curl command then can be used in the exec binding.
Command looks like:
curl -X GET "http://pi:8080/rest/items/YourItemNameHere/state" -H "accept: text/plain"
In case access is denied you have to set and use an Authorization Bearer token.
I create a rule in OH3 web frontend with trigger GPSTracker_Location changed
then I run a python script
> # importing modules
> from geopy.geocoders import Nominatim
>
> # calling the nominatim tool
> geoLoc = Nominatim(user_agent="GetLoc")
>
> # passing the coordinates
> latlon = ir.getItem("GPSTracker_location").state
> locname = geoLoc.reverse(latlon,language="nl",addressdetails=True)
>
> # printing the address/location name
> parts = locname.address.split(", ")
> #print(parts[0] + " " + parts[6] + " " + parts[2] + " " + parts[7])
> #print(locname.address)
>
> events.postUpdate("GPSTrackerSB_Address", parts[0] + " " + parts[6] + " " + parts[2] + " " + parts[7])
This gives below error:
Script execution of rule with UID ‘fb61159892’ failed: ImportError: No module named geopy in at line number 2
While geopy has been installed under current user and openhab user
Who can help
This is python from the helper libraries ?
See Reference — openHAB Helper Libraries documentation resp. Reference — openHAB Helper Libraries documentation about the location where to put additional modules.
Specifying the geopy path does resolve the error.
Only error remaining now:
2021-09-17 11:59:46.567 [ERROR] [internal.handler.ScriptActionHandler] - Script execution of rule with UID ‘fb61159892’ failed: org.python.antlr.ParseException: org.python.antlr.ParseException: encoding declaration in Unicode string
My script so far
#!/usr/bin/python
# encoding: utf-8
#importing modules
import os, sys
sys.path.append("/usr/local/lib/python3.7/dist-packages")
from geopy.geocoders import Nominatim
# calling the nominatim tool
geoLoc = Nominatim(user_agent="GetLoc")
# passing the coordinates
lalo = ir.getItem("GPSTracker_location").state
# location item returns "4.13°N 52.23°E 0m” thus converting it to 4.13,52.23
lat = lalo.split("°N ")
lon = lat[1].split("°E ")
latlon = str(lat[0]) + "," + str(lon[0])
locname = geoLoc.reverse(latlon,language="nl",addressdetails=True)
# printing the address/location name
parts = locname.address.split(", ")
events.postUpdate("GPSTrackerSB_Address", str(parts[0]) + " " + str(parts[6]) + " " + str(parts[2]) + " " + str(parts[7]))
Does it have to be
or
# -*- coding: utf-8 -*-
Is the problem in the lines with the degree symbol ?
I guess so.
changing encoding to your proposal gives the same error
Would it work to split on space and cut of the last two characters ?
Chanbging to
# passing the coordinates
lalo = ir.getItem("GPSTrackerSB_locatie").state
# ir.getItem("GPSTrackerSB_locatie").state returns "4.13°N 52.23°E 0m” => converting it to 4.13,52.23
lat = lalo.split(" ")
la = str(lat[0])[:-2]
lon = lat[1].split(" ")
lo = str(lon[0])[:-2]
latlon = la + "," + lo
# latlon is now a string in format 4.13,52.23
locname = geoLoc.reverse(latlon,language="nl",addressdetails=True)
gives the same error
When running the same py script from terminal it does work
Must have something to do with the Jython implementation
you may have a look to this thread/post ( No international characters (Unicode) with jsr223 / Jython? - #12 by cris ). There are a few more suggestions.
Already did, but can’t get the issue solved. A pity since the geopy library is easy and practical. Will have to look for another means
geopy looks to be Python3. Jython is Python2.7 only, unfortunately.
Indeed that seems to be the problem. Abandoning the python path
You can use your script and execute it via the exec binding. The python part should work what is missing would be getting the item stateof your GPS tracker and returning the result.
Problem solved with ECMAScript rule
var Transformation = Java.type("org.openhab.core.transform.actions.Transformation")
var lalo = itemRegistry.getItem(“GPSTracker_Location").getState().toString();
var lat = lalo.split(",")[0].toString();
var lon = lalo.split(",")[1].toString();
var url = "https://nominatim.openstreetmap.org/reverse?format=json&lat=" + parseFloat(lat) + "&lon=" + parseFloat(lon) + "&accept-language=nl&addressdetails=1";
var HttpUtil = Java.type("org.openhab.core.io.net.http.HttpUtil");
var response = HttpUtil.executeUrl("GET", url, 2000);
var straat = Transformation.transform("JSONPATH", "$.address.road", response);
var postcode = Transformation.transform("JSONPATH", "$.address.postcode", response);
var gemeente = Transformation.transform("JSONPATH", "$.address.town", response);
var land = Transformation.transform("JSONPATH", "$.address.country", response);
if(land == "België") {
land = "";
}
var address = straat + " " + postcode + " " + gemeente + " " + land;
events.postUpdate("GPSTracker_Address", address.toString());