Skip to content
Open

Wxv2 #14

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 36 additions & 59 deletions .bin/wx
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#!/bin/bash

## wx: a METAR parser written in Bash
# (c) 2021 Allyson Bowles
# (c) 2023 Al Bowles

## Usage:
# wx [[ temp [ f|F | c|C | k|K ]] | humidity | wind | altimeter | visibility | rvr | condition | phenomena | metar | remarks | refresh ]
# wx [[ temp [ f|F | c|C | k|K ]] | humidity | wind | altimeter | visibility | rvr | condition | phenomena | metar | remarks | feelslike ]

## References:
# http://www.met.tamu.edu/class/metar/quick-metar.html
Expand All @@ -21,60 +21,19 @@ STATION=KRYV
#STATION=KHNB
DATA_URI="data/observations/metar/stations/$STATION.TXT"
DATA_URL="https://tgftp.nws.noaa.gov/$DATA_URI"
CACHE="$HOME/.cache/wx/metar"
TIMEOUT=10
PLATFORM=$(uname)

[[ ! -d "$(dirname $CACHE)" ]] && mkdir -p "$(dirname $CACHE)"
[[ ! -f "$CACHE" ]] && touch $CACHE

# TODO uuoc
metar=`cat $CACHE`

_check_last_modified() {
last_modified=$(curl -I -s $DATA_URL | grep Last\-Modified | awk -F': ' '{ print $2 }')
[[ "$last_modified" == "" ]] && return 1

case $PLATFORM in
Linux)
src=$(date --date="$last_modified" +'%s')
# FIXME are we handling the case where $CACHE is empty?
cache=$(date -r $CACHE +'%s')
;;
Darwin)
src=$(date -j -f "%a, %e %b %Y %T %Z" "$last_modified" "+%s" 2&> /dev/null)
cache=$(stat -f "%m" -q $CACHE)
;;
esac
[[ "$src" > "$cache" ]] && return 1 || return 0
}

_check_md5sum() {
case $PLATFORM in
Linux)
md5sum $1 | awk '{print $1}'
;;
Darwin)
md5 $1 | awk '{print $4}'
;;
esac
}

refresh() {
data=$(curl --connect-timeout $TIMEOUT --create-dirs -s $DATA_URL | tr "\n" " ")
[[ "$data" != "" && $(_check_md5sum <<< $data) != $(_check_md5sum $CACHE) ]] && echo $data > $CACHE
}
metar=$(curl --connect-timeout 2 -s $DATA_URL)

metar() {
echo $metar
echo "$metar"
}

remarks() {
awk -F 'RMK' '{print $2}' $CACHE
awk -F 'RMK' '{print $2}' <<< $metar
}

rvr() {
awk '$0 ~ /\(R\[0-9\]\+\/\[0-9\]\+V?\(M\|P\)\[0-9\]\+FT\)/' $CACHE
awk '$0 ~ /\(R\[0-9\]\+\/\[0-9\]\+V?\(M\|P\)\[0-9\]\+FT\)/' <<< $metar
}

phenomena() {
Expand Down Expand Up @@ -122,7 +81,6 @@ phenomena() {

case ${phen[0]} in
*SQ*) other="squall" ;;
*FC*) other="funnel cloud" ;;
*SS*) other="sandstorm" ;;
*FC*) other="tornado" ;;
*DS*) other="dust storm" ;;
Expand All @@ -132,14 +90,14 @@ phenomena() {
if [[ -n "$qual" || -n "$desc" || -n "$precip" || -n "$obsc" || -n "$other" ]]
then
printf " %s" $qual $desc $precip $obsc $other
exit 0
return 0
else
exit 1
return 1
fi
}

condition() {
cond=$(grep -o '\(\(CLR\|SKC\|FEW\|SCT\|BKN\|OVC\|VV\)\([0-9]\+\)\?\(\|TCU\|CB\)\?\)\+' $CACHE)
cond=$(grep -o '\(\(CLR\|SKC\|FEW\|SCT\|BKN\|OVC\|VV\)\([0-9]\+\)\?\(\|TCU\|CB\)\?\)\+' <<< $metar)
case ${cond[${#cond[@]} - 1]} in
CLR*|SKC*) condition="clear" ;;
FEW*) condition="partly cloudy" ;;
Expand All @@ -150,15 +108,15 @@ condition() {
**) condition="" ;;
esac

printf " %s" $condition
printf " $condition"
}

visibility() {
grep -o '\([0-9]\+SM\)' $CACHE
grep -o '\([0-9]\+SM\)' <<< $metar
}

altimeter() {
grep -o 'A[0-9]\{4\}' $CACHE
grep -o 'A[0-9]\{4\}' <<< $metar
}

_wind_speed_conversion() {
Expand All @@ -172,11 +130,11 @@ _wind_speed_conversion() {
}

_wind_speed(){
read wind_speed gusting <<< $(grep -o '\([0-9]\{2\}G\)\?[0-9]\{2\}KT' $CACHE | awk -F 'G' '{ printf "%d %d", $1, $2 }')
read wind_speed gusting <<< $(grep -o '\([0-9]\{2\}G\)\?[0-9]\{2\}KT' <<< $metar | awk -F 'G' '{ printf "%d %d", $1, $2 }')
}

_wind_direction() {
wd=$(printf "%.3s" $(grep -o '\(VRB\|[0-9]\{3\}\)\([0-9]\{2\}G\)\?[0-9]\{2\}KT' $CACHE))
wd=$(printf "%.3s" $(grep -o '\(VRB\|[0-9]\{3\}\)\([0-9]\{2\}G\)\?[0-9]\{2\}KT' <<< $metar))

if [[ "$wd" == "VRB" ]]
then
Expand Down Expand Up @@ -226,7 +184,7 @@ wind() {
}

_temperature_dewpoint() {
temperature_dewpoint=$(grep -o '\s\(M\)\?\([0-9]\{2\}\/\(M\)\?[0-9]\{2\}\)\s' $CACHE)
temperature_dewpoint=$(grep -o '\s\(M\)\?\([0-9]\{2\}\/\(M\)\?[0-9]\{2\}\)\s' <<< $metar)
read temp dp <<< $(awk -F '/' '{ printf "%d %d", $1, $2 }' <<< $(echo $temperature_dewpoint | sed 's/M/-/g'))
}

Expand Down Expand Up @@ -254,16 +212,24 @@ temp() {
}

wind_chill() {
# Wind chill is only a useful metric at or below 10C /and/
# when wind speeds exceed 4.8 kph.
_temperature_dewpoint
[[ $(bc <<< "$temp <= 10") == 1 ]] || return 1
_wind_speed
x=$(_wind_speed_conversion "$wind_speed" kph)
[[ $(bc <<< "$x > 4.8") == 1 ]] || return 1

# bc does not support floating point exponents
y=$(awk -v "wc=$wind_speed" 'BEGIN {print wc**0.16}')
y=$(awk -v "wc=$x" 'BEGIN {print wc**0.16}')
wind_chill=$(bc <<< "13.12 + (0.6215 * $temp) - (11.37 * $y) + (0.3965 * $temp * $y)")
_temperature_conversion $wind_chill $1
}

heat_index() {
# heat index is only a useful metric at or above 26C
_temperature_dewpoint
[[ $(bc <<< "$temp > 26") == 1 ]] || return 1
_relative_humidity
c1="-8.78469475556"
c2="1.61139411"
Expand All @@ -278,4 +244,15 @@ heat_index() {
_temperature_conversion $heat_index $1
}

$@ && _check_last_modified || refresh
feelslike() {
wind_chill $1 || heat_index $1 || return 1
}

summary() {
temp f
# TODO don't print if feelslike returns 1
printf " (%s)" "$(feelslike f)"
phenomena || condition
}

$@
10 changes: 8 additions & 2 deletions .vimrc
Original file line number Diff line number Diff line change
Expand Up @@ -93,20 +93,26 @@ let g:ale_fix_on_save = 1
let g:ale_echo_msg_error_str = 'E'
let g:ale_echo_msg_warning_str = 'W'
let g:ale_echo_msg_format = '[%linter%] %s [%severity%]'
let g:ale_list_window_size = 5
let g:ale_fixers = {
\ '*': ['remove_trailing_lines', 'trim_whitespace'],
\ 'javascript': ['prettier'],
\ 'json': ['jq'],
\ 'terraform': ['terraform'],
\ 'yaml': ['yamlfix']
\ 'yaml': ['yamlfix'],
\}

let g:ale_linters = {
\ 'go': ['gofmt', 'golint', 'go vet', 'gopls'],
\ 'go': ['gofmt', 'golint', 'go vet', 'gopls', 'golangci-lint'],
\ 'ansible': ['ansible-lint'],
\ 'perl': ['perlcritic'],
\ 'terraform': ['terraform'],
\ 'ruby': ['rubocop'],
\ 'javascript': ['eslint'],
\}
" TODO markdown linter

"let b:ale_ruby_rubocop_executable = './vendor/bundle/ruby/2.6.0/bin/rubocop'
" TODO j2-lint integration
" TODO new panes bottom / right
" TODO middle click = set paste/insert/set nopaste
Expand Down