#!/usr/bin/env rexx /*------------------------------------------------------------------*/ /* Routine to retrieve a latitude/longitude pair from an address */ /* by utilizing the facilities provided by: */ /* */ /* https://nominatim.openstreetmap.org */ /* */ /* @param address - such as 1600 Pennsylvania Avenue */ /* */ /* @returns latlon - latitude longitude in decimal degrees */ /* as 2 words, e.g. 48.456123 3.876345 */ /* or UNKNOWN if not successful */ /* */ /* Can be invoked from the command line: */ /* */ /* "nominatim_latlon_from_address.orx" anAddress */ /* */ /* Or as a subroutine or function: */ /* */ /* call nominatim_latlon_from_address anAddress */ /* */ /* nominatim_latlon_from_address(anAddress) */ /* */ /* The latter two should use a: */ /* */ /* ::requires "nominatim_latlon_from_address.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/06 - Initial version */ /* */ /*------------------------------------------------------------------*/ parse source os how me if how=="COMMAND" then do address = .sysCArgs~toSTring(," ") latlon = nominatim_latlon_from_address(address) say latlon end exit ::routine nominatim_latlon_from_address public use strict arg address -- remove leading and trailing spaces and reduce spaces to a + in the query query = address~strip('B')~space(1)~translate('+',' ') /*------------------------------------------------------------------*/ /* 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/search?" - "q="query"&format=json&zoom=18&addressdetails=1" - "&limit=1&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")) latlon = "" if \(rexx~isA(.Array) & rexx~isEmpty) then do -- Without error if rexx~isA(.Array)then do -- the "search?" query always returns an array if successful latlon = rexx[1]["lat"]~format(,6) rexx[1]["lon"]~format(,6) end -- With error else do latlon = "ERROR: " do e over rexx["error"] latlon ||= rexx["error"][e]" " end end end if latlon=="" then latlon = "UNKNOWN" return latlon ::routine latlon_from_addr public use strict arg address return nominatim_latlon_from_address(address) ::requires "json.cls"