ansiweather

Weather in terminal, with ANSI colors and Unicode symbols
Log | Files | Refs | README | LICENSE

ansiweather (11285B)


      1 #!/bin/sh
      2 
      3 ###############################################################################
      4 #                                                                             #
      5 # AnsiWeather 1.17.0                                                          #
      6 # Copyright (c) 2013-2020, Frederic Cambus                                    #
      7 # https://github.com/fcambus/ansiweather                                      #
      8 #                                                                             #
      9 # Created: 2013-08-29                                                         #
     10 # Last Updated: 2020-06-16                                                    #
     11 #                                                                             #
     12 # AnsiWeather is released under the BSD 2-Clause license.                     #
     13 # See LICENSE file for details.                                               #
     14 #                                                                             #
     15 ###############################################################################
     16 
     17 
     18 
     19 ###[ Configuration options ]###################################################
     20 
     21 LC_ALL=C; export LC_ALL
     22 
     23 if [ -n "$ANSIWEATHERRC" ] ; then
     24 	config_file="$ANSIWEATHERRC"
     25 elif [ -s "$XDG_CONFIG_HOME"/ansiweather/config ] ; then
     26 	config_file="$XDG_CONFIG_HOME"/ansiweather/config
     27 elif [ -s "$HOME"/.config/ansiweather/config ] ; then
     28 	config_file="$HOME"/.config/ansiweather/config
     29 else
     30 	config_file=~/.ansiweatherrc
     31 fi
     32 
     33 get_config() {
     34 	ret=""
     35 	if [ -f "$config_file" ]
     36 	then
     37 		ret=$(grep "^$1:" "$config_file" | cut -d: -f2-)
     38 	fi
     39 
     40 	if [ "X$ret" = "X" ]
     41 	then
     42 		return 1
     43 	else
     44 		echo "$ret"
     45 	fi
     46 }
     47 
     48 fetch_cmd=$(get_config "fetch_cmd" || echo "curl -sf")
     49 
     50 
     51 
     52 ###[ Parse the command line ]##################################################
     53 
     54 # Get config options from command line flags
     55 while getopts l:u:f:Fa:s:k:i:w:h:p:d:v option
     56 do
     57 	case "${option}"
     58 	in
     59 		l) location=${OPTARG};;
     60 		u) units=${OPTARG};;
     61 		f) forecast=${OPTARG};;
     62 		F) forecast="5";;
     63 		a) ansi=${OPTARG};;
     64 		s) symbols=${OPTARG};;
     65 		k) api_key=${OPTARG};;
     66 		i) show_uvi=${OPTARG};;
     67 		w) show_wind=${OPTARG};;
     68 		h) show_humidity=${OPTARG};;
     69 		p) show_pressure=${OPTARG};;
     70 		d) show_daylight=${OPTARG};;
     71 		v) echo "AnsiWeather 1.17.0" && exit 0;;
     72 		\?) exit 64;; # EX_USAGE
     73 	esac
     74 done
     75 
     76 
     77 
     78 ###[ Check if bc and jq are installed ]########################################
     79 
     80 jqpath=$(which jq)
     81 if [ "$jqpath" = "" ]
     82 then
     83 	echo "ERROR: Cannot find jq binary"
     84 	exit 69 # EX_UNAVAILABLE
     85 fi
     86 
     87 bcpath=$(which bc)
     88 if [ "$bcpath" = "" ]
     89 then
     90 	echo "ERROR: Cannot find bc binary"
     91 	exit 69 # EX_UNAVAILABLE
     92 fi
     93 
     94 
     95 
     96 ###[ Set options that are not set from command line ]##########################
     97 
     98 # OpenWeatherMap API key
     99 [ -z "$api_key" ] && api_key=$(get_config "api_key" || echo "85a4e3c55b73909f42c6a23ec35b7147")
    100 
    101 # Location: example "Rzeszow,PL"
    102 [ -z "$location" ] && location=$(get_config "location" || echo "Rzeszow,PL")
    103 
    104 # System of Units: "metric" or "imperial"
    105 [ -z "$units" ] && units=$(get_config "units" || echo "metric")
    106 
    107 # Show forecast: How many days, example "5". "0" is standard output
    108 [ -z "$forecast" ] && forecast=$(get_config "forecast" || echo 0)
    109 
    110 # Display ANSI colors: "true" or "false"
    111 [ -z "$ansi" ] && ansi=$(get_config "ansi" || echo true)
    112 
    113 # Display symbols: "true" or "false" (requires a Unicode capable display)
    114 [ -z "$symbols" ] && symbols=$(get_config "symbols" || echo false)
    115 
    116 # Show UVI: "true" or "false"
    117 [ -z "$show_uvi" ] && show_uvi=$(get_config "show_uvi" || echo true)
    118 
    119 # Show wind: "true" or "false"
    120 [ -z "$show_wind" ] && show_wind=$(get_config "show_wind" || echo true)
    121 
    122 # Show humidity: "true" or "false"
    123 [ -z "$show_humidity" ] && show_humidity=$(get_config "show_humidity" || echo true)
    124 
    125 # Show pressure: "true" or "false"
    126 [ -z "$show_pressure" ] && show_pressure=$(get_config "show_pressure" || echo true)
    127 
    128 # Show daylight: "true" or "false"
    129 [ -z "$show_daylight" ] && show_daylight=$(get_config "show_daylight" || echo false)
    130 
    131 dateformat=$(get_config "dateformat" || echo "%a %b %d")
    132 timeformat=$(get_config "timeformat" || echo "%b %d %r")
    133 
    134 
    135 
    136 ###[ Colors and characters ]###################################################
    137 
    138 background=$(get_config "background" || echo "\033[44m")
    139 text=$(get_config "text" || echo "\033[36;1m")
    140 data=$(get_config "data" || echo "\033[33;1m")
    141 delimiter=$(get_config "delimiter" || echo "\033[35m:")
    142 dashes=$(get_config "dashes" || echo "\033[34m-")
    143 
    144 
    145 
    146 ###[ Text Labels ]#############################################################
    147 
    148 greeting_text=$(get_config "greeting_text" || echo "Weather in")
    149 wind_text=$(get_config "wind_text" || echo "Wind")
    150 humidity_text=$(get_config "humidity_text" || echo "Humidity")
    151 pressure_text=$(get_config "pressure_text" || echo "Pressure")
    152 sunrise_text=$(get_config "sunrise_text" || echo "Sunrise")
    153 sunset_text=$(get_config "sunset_text" || echo "Sunset")
    154 forecast_text=$(get_config "forecast_text" || echo "forecast")
    155 
    156 
    157 
    158 ###[ Unicode Symbols for icons ]###############################################
    159 
    160 sun=$(get_config "sun" || echo "\033[33;1m\xe2\x98\x80")
    161 moon=$(get_config "moon" || echo "\033[36m\xe2\x98\xbd")
    162 clouds=$(get_config "clouds" || echo "\033[37;1m\xe2\x98\x81")
    163 rain=$(get_config "rain" || echo "\033[37;1m\xe2\x98\x94")
    164 fog=$(get_config "fog" || echo "\033[37;1m\xe2\x96\x92")
    165 mist=$(get_config "mist" || echo "\033[34m\xe2\x96\x91")
    166 haze=$(get_config "haze" || echo "\033[33m\xe2\x96\x91")
    167 snow=$(get_config "snow" || echo "\033[37;1m\xe2\x9d\x84")
    168 thunderstorm=$(get_config "thunderstorm" || echo "\033[33;1m\xe2\x9a\xa1")
    169 
    170 
    171 
    172 ###[ Fetch Weather data ]######################################################
    173 
    174 api_cmd=$([ "$forecast" != 0 ] && echo "forecast/daily" || echo "weather")
    175 
    176 if [ "$location" -gt 0 ] 2> /dev/null
    177 then
    178 	# Location is all numeric
    179 	weather=$($fetch_cmd "https://api.openweathermap.org/data/2.5/$api_cmd?id=$location&units=$units&appid=$api_key")
    180 else
    181 	# Location is a string
    182 	location=$(echo "$location" | sed "s/ /%20/g")
    183 	weather=$($fetch_cmd "https://api.openweathermap.org/data/2.5/$api_cmd?q=$location&units=$units&appid=$api_key")
    184 fi
    185 
    186 if [ -z "$weather" ]
    187 then
    188 	echo "ERROR: Cannot fetch weather data"
    189 	exit 75 # EX_TEMPFAIL
    190 fi
    191 
    192 status_code=$(echo "$weather" | jq -r '.cod' 2>/dev/null)
    193 
    194 if [ "$status_code" != 200 ]
    195 then
    196 	echo "ERROR: Cannot fetch weather data for the given location"
    197 	exit 69 # EX_UNAVAILABLE
    198 fi
    199 
    200 
    201 
    202 ###[ Fetch UV data ]###########################################################
    203 
    204 if [ "$show_uvi" = true ] && [ "$forecast" = 0 ]
    205 then
    206 	lat=$(echo "$weather" | jq -r '.coord.lat')
    207 	lon=$(echo "$weather" | jq -r '.coord.lon')
    208 
    209 	uvdata=$($fetch_cmd "https://api.openweathermap.org/data/2.5/uvi?lat=$lat&lon=$lon&appid=$api_key")
    210 	uvi=$(echo "$uvdata" | jq -r '.value')
    211 fi
    212 
    213 
    214 
    215 ###[ Process Weather data ]####################################################
    216 
    217 epoch_to_date() {
    218 	if date -j -r "$1" +"%a %b %d" > /dev/null 2>&1; then
    219 		# BSD
    220 		ret=$(date -j -r "$1" +"$dateformat")
    221 	else
    222 		# GNU
    223 		ret=$(date -d "@$1" +"$dateformat")
    224 	fi
    225 	echo "$ret"
    226 }
    227 
    228 if [ "$forecast" != 0 ]
    229 then
    230 	city=$(echo "$weather" | jq -r '.city.name')
    231 	flength=$(echo "$weather" | jq '.list | length')
    232 	forecast=$([ "$forecast" -gt "$flength" ] && echo "$flength" || echo "$forecast")
    233 else
    234 	city=$(echo "$weather" | jq -r '.name')
    235 	temperature=$(echo "$weather" | jq '.main.temp' | xargs printf "%.0f")
    236 	humidity=$(echo "$weather" | jq '.main.humidity')
    237 	pressure=$(echo "$weather" | jq '.main.pressure')
    238 	sky=$(echo "$weather" | jq -r '.weather[0].main')
    239 	sunrise=$(echo "$weather" | jq '.sys.sunrise')
    240 	sunset=$(echo "$weather" | jq '.sys.sunset')
    241 	wind=$(echo "$weather" | jq '.wind.speed')
    242 	azimuth=$(echo "$weather" | jq '.wind.deg')
    243 fi
    244 
    245 
    246 
    247 ###[ Process Wind data ]#######################################################
    248 
    249 set -- $(get_config "wind_directions" || echo "N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW")
    250 
    251 if [ "$forecast" = 0 ]
    252 then
    253 	shift "$(echo "scale=0; ($azimuth + 11.25)/22.5 % 16" | bc)"
    254 	direction=$1
    255 fi
    256 
    257 
    258 
    259 ###[ Process Sunrise and Sunset data ]#########################################
    260 
    261 epoch_to_time() {
    262 	if date -j -r "$1" +"%r" > /dev/null 2>&1; then
    263 		# BSD
    264 		ret=$(date -j -r "$1" +"$timeformat")
    265 	else
    266 		# GNU
    267 		ret=$(date -d "@$1" +"$timeformat")
    268 	fi
    269 	echo "$ret"
    270 }
    271 
    272 if [ "$forecast" = 0 ]
    273 then
    274 	if [ -n "$sunrise" ]
    275 	then
    276 		sunrise_time=$(epoch_to_time "$sunrise")
    277 	fi
    278 
    279 	if [ -n "$sunset" ]
    280 	then
    281 		sunset_time=$(epoch_to_time "$sunset")
    282 	fi
    283 fi
    284 
    285 
    286 
    287 ###[ Set the period ]##########################################################
    288 
    289 now=$(date +%s)
    290 
    291 if [ "$forecast" != 0 ]
    292 then
    293 	period="none"
    294 else
    295 	if [ -z "$sunset" ] || [ -z "$sunrise" ]
    296 	then
    297 		period="day"
    298 	elif [ "$now" -ge "$sunset" ] || [ "$now" -le "$sunrise" ]
    299 	then
    300 		period="night"
    301 	else
    302 		period="day"
    303 	fi
    304 fi
    305 
    306 
    307 
    308 ###[ Set the scale ]###########################################################
    309 
    310 case $units in
    311 	metric)
    312 		scale="°C"
    313 		speed_unit="m/s"
    314 		pressure_unit="hPa"
    315 		pressure=$(echo "$pressure" | xargs printf "%.0f")
    316 		;;
    317 	imperial)
    318 		scale="°F"
    319 		speed_unit="mph"
    320 		pressure_unit="inHg"
    321 		if [ "$forecast" = 0 ]
    322 		then
    323 			pressure=$(echo "$pressure*0.0295" | bc | xargs printf "%.2f")
    324 		fi
    325 		;;
    326 esac
    327 
    328 
    329 
    330 ###[ Set icons ]###############################################################
    331 
    332 get_icon() {
    333 	case $1 in
    334 		Clear)
    335 			if [ $period = "night" ]
    336 			then
    337 				echo "$moon "
    338 			else
    339 				echo "$sun "
    340 			fi
    341 			;;
    342 		Clouds)
    343 			echo "$clouds "
    344 			;;
    345 		Rain)
    346 			echo "$rain "
    347 			;;
    348 		Fog)
    349 			echo "$fog "
    350 			;;
    351 		Mist)
    352 			echo "$mist "
    353 			;;
    354 		Haze)
    355 			echo "$haze "
    356 			;;
    357 		Snow)
    358 			echo "$snow "
    359 			;;
    360 		Thunderstorm)
    361 			echo "$thunderstorm "
    362 			;;
    363 	esac
    364 }
    365 
    366 
    367 
    368 ###[ Display current Weather ]#################################################
    369 
    370 if [ "$forecast" != 0 ]
    371 then
    372 	output="$background$text $city $forecast_text$text$delimiter "
    373 
    374 	i=0
    375 	while [ $i -lt "$forecast" ]
    376 	do
    377 		day=$(echo "$weather" | jq ".list[$i]")
    378 		date=$(epoch_to_date "$(echo "$day" | jq -r '.dt')")
    379 		low=$(echo "$day" | jq -r '.temp.min' | xargs printf "%.0f")
    380 		high=$(echo "$day" | jq -r '.temp.max' | xargs printf "%.0f")
    381 
    382 		icon=""
    383 		if [ "$symbols" = true ]
    384 		then
    385 			sky=$(echo "$day" | jq -r '.weather[0].main')
    386 			icon=$(get_icon "$sky")
    387 		fi
    388 
    389 		output="$output$text$date$delimiter $data$high$text/$data$low $scale $icon"
    390 		if [ $i -lt $((forecast-1)) ]
    391 		then
    392 			output="$output$dashes "
    393 		fi
    394 
    395 		i=$((i + 1))
    396 	done
    397 else
    398 	if [ "$symbols" = true ]
    399 	then
    400 		icon="$(get_icon "$sky")"
    401 	fi
    402 	output="$background$text $greeting_text $city$delimiter$data $temperature $scale $icon"
    403 
    404 	if [ "$show_uvi" = true ]
    405 	then
    406 		output="$output$dashes$text UVI$delimiter$data $uvi "
    407 	fi
    408 
    409 	if [ "$show_wind" = true ]
    410 	then
    411 		output="$output$dashes$text $wind_text$delimiter$data $wind $speed_unit $direction "
    412 	fi
    413 
    414 	if [ "$show_humidity" = true ]
    415 	then
    416 		output="$output$dashes$text $humidity_text$delimiter$data $humidity%% "
    417 	fi
    418 
    419 	if [ "$show_pressure" = true ]
    420 	then
    421 		output="$output$dashes$text $pressure_text$delimiter$data $pressure $pressure_unit "
    422 	fi
    423 
    424 	if [ "$show_daylight" = true ]
    425 	then
    426 		output="$output$dashes$text $sunrise_text$delimiter$data $sunrise_time $dashes$text $sunset_text$delimiter$data $sunset_time "
    427 	fi
    428 fi
    429 
    430 if [ "$ansi" = true ]
    431 then
    432 	env printf "$output\033[0m\n"
    433 else
    434 	env printf "$output\n" | sed "s/$(printf '\033')\[[0-9;]*m//g"
    435 fi