#!/usr/bin/env rexx /*------------------------------------------------------------------*/ /* Routine to retrieve an address from a latitude/longitude pair */ /* by utilizing the facilities provided by: */ /* */ /* https://nominatim.openstreetmap.org */ /* */ /* @param latitude - in decimal degrees */ /* */ /* @param longitude - in deicmal degrees */ /* */ /* @param language - in odes like "en", "de", "nl" etc. see: */ /* */ /* https://wiki.openstreetmap.org/wiki/Nominatim/Country_Codes */ /* */ /* @param level - the level of detail of the result: */ /* */ /* 3 - country */ /* 4 - state */ /* 8 - county */ /* 10 - city */ /* 14 - suburb */ /* 16 - major streets */ /* 17 - major and minor streets */ /* 18 - building */ /* */ /* @returns address - such as 1600 Pennsylvania Avenue Washin.... */ /* */ /* Can be invoked from the command line: */ /* */ /* "nominatim_address_from_latlon.orx" lat lon lvl */ /* */ /* Or as a subroutine or function: */ /* */ /* call nominatim_address_from_latlon lat, lon, lvl */ /* */ /* nominatim_address_from_latlon(lat, lon, lvl) */ /* */ /* The latter two should use a: */ /* */ /* ::requires "nominatim_address_from_latlon.orx" */ /* */ /* For ooRexx 5.0.0 or later only */ /* */ /*------------------------------------------------------------------*/ /* */ /* Originally by Ruurd J. Idenburg */ /* */ /* No copyright, no licence, no guarantees or warrantees, be it */ /* explicit, implicit or whatever. Usage is totally and completely */ /* at the users own risk, the author shall not be liable for any */ /* damages whatsoever, for any reason whatsoever. */ /* */ /* Please keep this comment block intact when modifying this code */ /* and add a note with date and a description. */ /* */ /*------------------------------------------------------------------*/ /* */ /* 2021/05/02 - Initial version */ /* */ /*------------------------------------------------------------------*/ parse source os how me if how=="COMMAND" then do if .sysCArgs[3]==.nil then .sysCArgs[3] = "nl" if .sysCArgs[4]==.nil then .sysCArgs[4] = 16 address = nominatim_address_from_latlon(.sysCArgs[1],- .sysCArgs[2],- .sysCArgs[3],- .sysCArgs[4]) say address end exit ::routine nominatim_address_from_latlon public use strict arg lat, lon, lng="nl", lvl=16 /*------------------------------------------------------------------*/ /* nominatim appreciates a non standard https-header for User_Agent */ /* I have mine stored as an linux environment variable via .profile */ /* but it can be hardcoded as well of course. */ /*------------------------------------------------------------------*/ myAgent = value("USER_AGENT", ,"ENVIRONMENT") /*------------------------------------------------------------------*/ /* nominatim appreciates an e-mail address in case of frequent and */ /* multiple requests. I keep mine as a Linux environment variable, */ /* but it can be hardcoded as well of course. */ /*------------------------------------------------------------------*/ myEmail = value("MY_EMAIL", ,"ENVIRONMENT") /*------------------------------------------------------------------*/ /* nominatim usage guidelines suggest not to issue more than one */ /* request per second, so we'll wait 1 second before issueing the */ /* request for the case we do multiple requests in a short period. */ /*------------------------------------------------------------------*/ call sysSleep(1) /*------------------------------------------------------------------*/ /* We use the (new in ooRexx 5.0.0) "ADDRESS SYSTEM WITH" keyword */ /* instruction to issue the request via "CURL" (https://curl.se/) */ /*------------------------------------------------------------------*/ jsonArray = .array~new -- Direct output from CURL to an array address system with output using (jsonArray) "curl -s -A "myAgent" 'https://nominatim.openstreetmap.org/reverse?"- "format=json&lat="lat"&lon="lon"&zoom="lvl"&addressdetails=1"- "&limit=1&accept-language="lng"&email="myEmail"'" -- Switch output back to normal address system with output normal -- Uncomment to see the whole result from CURL --say jsonArray -- Create the ooRexx (.directory) equivalent of the JSON rexx = .json~new()~fromJSON(jsonArray~toString("C")) address = "" -- Without error if \rexx~hasindex("error")then do address = rexx["display_name"] end -- With error else do address = "ERROR: " do e over rexx["error"] address ||= rexx["error"][e]" " end end if address = "" then address = "UNKNOWN" return address ::routine addr_from_latlon public lng = arg(3) lvl = arg(4) if lng=="" then lng = "en" if lvl=="" then lvl = 16 return nominatim_address_from_latlon(arg(1), arg(2), lng, lvl) ::requires json.cls