#!/bin/sh # # geo-code: Convert a street address into a latitude/longitude # # Requires: curl; gpsbabel; bash or ksh; # mysql (if using the gpsdrive.sql output option) # # Donated to the public domain by Rick Richardson # http://home.mn.rr.com/richardsons/sw/geo-code # # Use at your own risk. Not suitable for any purpose. Not legal tender. # # PROGNAME="$0" usage() { cat <Long. plus "map" to display a map. -n name The waypoint name, e.g. Bob's House. The default is the street address. -s Output shortened names (a gpsbabel option) -t type The waypoint type, e.g. house, cache, bar [$CODETYPE] -q Quiet. Do not output address confirmation on stderr. -S Alias for -o gpsdrive.sql -a For SQL, delete existing record only if it matches all fields. Otherwise, delete it if it matches just the name and the type. -D level Debug level -U Retrieve latest version of this script Countries: us, ca, fr, de, it, es, uk Examples: \$ geo-code "123 AnyStreet" 12345 123AnyStreet 42.81020 -73.95070 new \$ geo-code -t house "123 AnyStreet" 12345 123AnyStreet 42.81020 -73.95070 house \$ geo-code -n "Bob's House" -t house "123 AnyStreet" 12345 BobsHouse 42.81020 -73.95070 house \$ geo-code -S -n "Bob" -t house "123 AnyStreet" 12345 [waypoint is added to GpsDrive MySQL database] \$ geo-code 901-555-1212 123AnyStreet 42.81020 -73.95070 new See Also: geo-nearest http://home.mn.rr.com/richardsons/sw/geo-nearest geo-pg http://home.mn.rr.com/richardsons/sw/geo-pg EOF exit 1 } # # Report an error and exit # error() { echo "`basename $PROGNAME`: $1" >&2 exit 1 } # # Set default options, can be overriden on command line or in rc file # DEBUG=0 OUTFMT=gpsdrive COUNTRY=us # us, ca, fr, de, it,es, uk SQLUSER=gast # For -o gpsdrive.sql SQLPASS=gast # For -o gpsdrive.sql SQLDB=geoinfo # For -o gpsdrive.sql CODETYPE=new UPDATEcodeURL=http://home.mn.rr.com/richardsons/sw/geo-code UPDATEcodeFILE=geo-code.new # # Read RC file, if there is one # if [ -f $HOME/.georc ]; then . $HOME/.georc fi # # Process the options # ADDRESS= CSZ= MODE=babel SQL=0 NAME= GURL= QUIET=0 SQLMATCH=type_name unset OPTIND while getopts "an:o:qSs:t:D:Uh?" opt do case $opt in n) NAME="$OPTARG";; o) OUTFMT="$OPTARG";; s) BABELFLAGS="$BABELFLAGS -s";; S) OUTFMT="gpsdrive.sql";; t) CODETYPE="$OPTARG";; q) QUIET=1;; a) SQLMATCH=all;; D) DEBUG="$OPTARG";; U) echo "Getting latest version of this script..." curl -o$UPDATEcodeFILE "$UPDATEcodeURL" echo "Latest version is in $UPDATEcodeFILE" exit ;; h|\?) usage;; esac done shift `expr $OPTIND - 1` case "$OUTFMT" in map) MODE=map ;; latlon) MODE=latlon ;; gpsdrive) BABELFLAGS=-s ;; gpsdrive.sql) BABELFLAGS=-s OUTFMT=gpsdrive MODE=sql # DEBUG=1 ;; \?) gpsbabel -? | sed '1,/File Types/d' echo " gpsdrive.sql " \ "GpsDrive direct MySQL database insertion" echo " latlon " \ "Just latitude and longitude, thank you" exit ;; esac case "$#" in 3) # # street_address citystate_or_zip country # ADDRESS=$1 CSZ=$2 COUNTRY=$3 address=`echo $ADDRESS | tr ' ' '+'` csz=`echo $CSZ | tr ' ' '+'` country=`echo $COUNTRY | tr '[A-Z]' '[a-z]'` case "$country" in us|usa) country=us;; ca) country=ca;; fr) country=fr;; de) country=de;; it) country=it;; es) country=es;; uk) country=uk;; *) error "Unknown country '$3'";; esac ;; 2) # # street-address citystate_or_zip # ADDRESS=$1 CSZ=$2 address=`echo $ADDRESS | tr ' ' '+'` csz=`echo $CSZ | tr ' ' '+'` country=$COUNTRY ;; 1) # # Google-able_phone_or_name # # first name (or first initial), last name, city (state is optional) # first name (or first initial), last name, state # first name (or first initial), last name, area code # first name (or first initial), last name, zip code # phone number, including area code # last name, city, state # last name, zip code # ADDRESS=$1 GURL="http://www.google.com/search?q=$1" ;; *) usage esac if [ "$NAME" = "" ]; then NAME="$ADDRESS" fi # # procedure to make a gpsbabel style file # make_style() { cat <]*\)>.*#\1#p' \ | head -n1 \ ` if [ "$URL" = "" ]; then cp $COORDS /tmp/geo.google error "Unable to lookup telephone number or name with Google" else URL="http://maps.yahoo.com/$URL" fi else # # Fetch a web page which geocode's the lat/lon # # # # URL="http://maps.yahoo.com/py/maps.py" URL="$URL?BFCat=" URL="$URL&Pyt=Tmap" URL="$URL&addr=$address" URL="$URL&csz=$csz" URL="$URL&country=$country" # us, ca, fr, de, it,es, uk URL="$URL&Get Map=Get+Map" fi if [ $DEBUG -gt 0 ]; then echo "curl $URL" fi if [ $DEBUG -gt 0 ]; then filter="tee /tmp/geo.yahoo" else filter=cat fi curl -L -s -A "$UA" "$URL" \ | $filter \ | sed -n \ -e 's/Yahoo! Maps - \([^<]*\)<.*/\1/p' \ -e 's/.*slt=\([^%]*\).*sln=\([^%]*\).*Create.*/\1 \2/p' \ > $COORDS if [ $DEBUG -gt 0 ]; then cp $COORDS /tmp/geo.coords fi # # Convert the coords, address, and type to the desired # output format. # get_latlon() { read title read lat lon } get_latlon < $COORDS; if [ "$title" != "" -a "$QUIET" != 1 ]; then echo "$title" >&2 fi if [ "$lat" = "" -o "$lon" = "" ]; then error "Cannot determine coordinates of that address" remove_cruft exit fi case "$MODE" in map) echo "$lat $lon" scale=10000 URL="http://www.vicinity.com/gif" URL="$URL?&CT=$lat:$lon:$scale&IC=&W=1280&H=1024&FAM=myblast&LB=" curl -L -s -A "$UA" "$URL" > $MAP xv $MAP remove_cruft exit ;; latlon) echo "$lat $lon" remove_cruft exit ;; esac make_style > $STYLE echo "$lat $lon $NAME $CODETYPE" \ | gpsbabel $BABELFLAGS -i xcsv,style=$STYLE -f /dev/fd/0 -o $OUTFMT -F $OUTWAY # # Output the data or add it to the MySQL database # gpsdrive_add() { delcmd="delete from waypoints" addcmd="insert into waypoints (name,lat,lon,type,comment)" read _name _lat _lon _type COMMENT="$ADDRESS" if [ "$CSZ" != "" ]; then COMMENT="$COMMENT, $CSZ" fi echo "use $SQLDB;" case "$SQLMATCH" in all) # Must be a complete match to delete existing record echo "$delcmd where name='$_name' and type='$_type'" echo "and lat='$_lat' and lon='$_lon';" ;; *) # Must match only name and type echo "$delcmd where name='$_name' and type='$_type';" ;; esac echo "$addcmd values ('$_name','$_lat','$_lon','$_type'," echo "'$COMMENT');" } if [ -f $OUTWAY ]; then case "$MODE" in sql) # # add it via mysql # if [ $QUIET != 1 ]; then echo "$NAME $lat $lon $CODETYPE" >&2 fi if [ $DEBUG -gt 0 ]; then gpsdrive_add <$OUTWAY else gpsdrive_add <$OUTWAY | mysql -u$SQLUSER -p$SQLPASS fi ;; *) # # output to stdout # cat $OUTWAY ;; esac fi remove_cruft