aboutsummaryrefslogblamecommitdiffstats
path: root/metar
blob: ed3527de96a1e0f0efe6967bff660311911df5d5 (plain) (tree)
































































































                                                                                                      
#!/bin/sh

usage ()
{
    echo "usage: $0 (get | print | set STATION | list [PREFIX] | closest LATITUDE LONGITUDE [LIST])"
}

get_station ()
{
    icao=""
    if test -f ~/.config/metar; then
	icao="$(cat ~/.config/metar | head -n 1)"
    elif test -f /etc/metar; then
	icao="$(cat /etc/metar | head -n 1)"
    fi
    if test -z "$icao"; then
	echo 'No METAR station has been selected.' >&2
	exit 1
    fi
    echo "$icao"
}

list_stations ()
{
    file="$(mktemp)"
    if test -z "$file"; then
	exit 1
    fi
    if ! curl -s "http://weather.noaa.gov/pub/data/observations/metar/decoded/" > "$file"; then
	unlink "$file"
	exit 1
    fi
    list="$(sed -n 's/^.*<a href="\('"$1"'[A-Za-z0-9]*\)\.TXT">.*$/\1/p' "$file")"
    unlink "$file"
    for icao in $list; do
	curl -s "http://weather.noaa.gov/pub/data/observations/metar/decoded/${icao}.TXT" | head -n 1
    done
}

get_closest ()
{
    best=
    grep ')' | while read line; do
	icao="$(echo "$line" | cut -d ')' -f 1 | cut -d '(' -f 2)"
	location="$(echo "$line" | cut -d ')' -f 2 | cut -d ' ' -f 2,3)"
	latitude="$(echo "$location" | cut -d ' ' -f 1)"
	longitude="$(echo "$location" | cut -d ' ' -f 2)"
	north="$(echo "$latitude" | grep 'S' > /dev/null; echo $?)"
	east="$(echo "$longitude" | grep 'W' > /dev/null; echo $?)"
	latitude="$(echo "$latitude" | tr -d NSEW | sed 's/-/ /g')"
	longitude="$(echo "$longitude" | tr -d NSEW | sed 's/-/ /g')"
	best="$(python3 - $north "$latitude" $east "$longitude" "$1" "$2" "$icao" $best <<EOF
import sys, math
ploc = lambda ps : sum(float(p) / (60 ** i) for i, p in enumerate(ps))
haversin = lambda a : 0.5 - math.cos(a) / 2

lat = (+1 if sys.argv[1] == '1' else -1) * ploc(sys.argv[2].split(' '))
lon = (+1 if sys.argv[3] == '1' else -1) * ploc(sys.argv[4].split(' '))
rlat = float(sys.argv[5])
rlon = float(sys.argv[6])
icao = sys.argv[7]
best = None if len(sys.argv) == 8 else float(sys.argv[9])

ϕ1, λ1 = [c * math.pi / 180 for c in (lat, lon)]
ϕ2, λ2 = [c * math.pi / 180 for c in (rlat, rlon)]

h = haversin(ϕ2 - ϕ1) + math.cos(ϕ1) * math.cos(ϕ2) * haversin(λ2 - λ1)
d = 2 * 6367.5 * math.asin(h ** 0.5)

if best is None or d < best:
    print('%s %f' % (icao, d))
else:
    print(sys.argv[8] + ' ' + sys.argv[9])
EOF
        )"
	echo "$best"
    done | tail -n 1 | cut -d ' ' -f 1
}

if test $# = 1 && test "$1" =  "get"; then
    curl -s "http://weather.noaa.gov/pub/data/observations/metar/decoded/$(get_station).TXT" || exit 1
elif test $# = 1 && test "$1" =  "print"; then
    get-station
elif test $# = 2 && test "$1" =  "set"; then
    echo "$2" > ~/.config/metar
elif test $# = 1 && test "$1" =  "list"; then
    list_stations ""
elif test $# = 2 && test "$1" =  "list"; then
    list_stations "$(echo "$2" | tr [a-z] [A-Z])"
elif test $# = 3 && test "$1" =  "closest"; then
    list_stations "" | get_closest "$2" "$3"
elif test $# = 4 && test "$1" =  "closest"; then
    get_closest "$2" "$3" < "$4"
else
    usage
fi