3
3
# To configure your location, set TMUX_POWERLINE_SEG_WEATHER_LOCATION in the tmux-powerline config file.
4
4
5
5
TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER_DEFAULT=" yrno"
6
- TMUX_POWERLINE_SEG_WEATHER_JSON_DEFAULT=" jq"
7
6
TMUX_POWERLINE_SEG_WEATHER_UNIT_DEFAULT=" c"
8
7
TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD_DEFAULT=" 600"
9
-
10
- if shell_is_bsd && [ -f /user/local/bin/grep ]; then
11
- TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT=" /usr/local/bin/grep"
12
- else
13
- TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT=" grep"
14
- fi
8
+ TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD_DEFAULT=" 86400" # 24 hours
9
+ TMUX_POWERLINE_SEG_WEATHER_LAT_DEFAULT=" auto"
10
+ TMUX_POWERLINE_SEG_WEATHER_LON_DEFAULT=" auto"
15
11
16
12
generate_segmentrc () {
17
13
read -r -d ' ' rccontents << EORC
18
- # The data provider to use. Currently only "yahoo " is supported.
14
+ # The data provider to use. Currently only "yrno " is supported.
19
15
export TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER="${TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER_DEFAULT} "
20
16
# What unit to use. Can be any of {c,f,k}.
21
17
export TMUX_POWERLINE_SEG_WEATHER_UNIT="${TMUX_POWERLINE_SEG_WEATHER_UNIT_DEFAULT} "
22
18
# How often to update the weather in seconds.
23
19
export TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD_DEFAULT} "
24
- # Name of GNU grep binary if in PATH, or path to it.
25
- export TMUX_POWERLINE_SEG_WEATHER_GREP="${TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT} "
26
- # Location of the JSON parser, jq
27
- export TMUX_POWERLINE_SEG_WEATHER_JSON="${TMUX_POWERLINE_SEG_WEATHER_JSON_DEFAULT} "
20
+ # How often to update the weather location in seconds (this is only used when latitude and longitude settings are set to "auto")
21
+ export TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD="${TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD_DEFAULT} "
28
22
# Your location
29
23
# Latitude and Longtitude for use with yr.no
30
- # Set both to "auto" to detect automatically based on your IP address
31
- TMUX_POWERLINE_SEG_WEATHER_LAT=""
32
- TMUX_POWERLINE_SEG_WEATHER_LON=""
24
+ # Set both to "auto" to detect automatically based on your IP address, or set them manually
25
+ export TMUX_POWERLINE_SEG_WEATHER_LAT="${TMUX_POWERLINE_SEG_WEATHER_LAT_DEFAULT} "
26
+ export TMUX_POWERLINE_SEG_WEATHER_LON="${TMUX_POWERLINE_SEG_WEATHER_LON_DEFAULT} "
33
27
EORC
34
28
echo " $rccontents "
35
29
}
36
30
37
31
run_segment () {
38
- __process_settings
39
- local tmp_file =" ${TMUX_POWERLINE_DIR_TEMPORARY} /temp_weather_file .txt"
40
- local weather
41
- case " $TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER " in
42
- " yrno " ) weather= $( __yrno ) ;;
43
- * )
44
- echo " Unknown weather provider [ $TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER ] "
45
- return 1
46
- ;;
47
- esac
48
- if [ -n " $weather " ] ; then
49
- echo " $weather "
32
+ local cache_weather_file= " ${TMUX_POWERLINE_DIR_TEMPORARY} /weather_cache_data.txt "
33
+ local cache_location_file =" ${TMUX_POWERLINE_DIR_TEMPORARY} /weather_cache_location .txt"
34
+ local weather= " "
35
+
36
+ # Check if the weather data is still a valid cache hit
37
+ if [ -f " $cache_weather_file " ] ; then
38
+ last_update= $( __read_file_last_update " $cache_weather_file " )
39
+ time_now= $( date +%s )
40
+ up_to_date= $( echo " ( ${time_now} - ${last_update} ) < ${TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD} " | bc )
41
+ if [ " $up_to_date " -eq 1 ] ; then
42
+ weather= $( __read_file_content " $cache_weather_file " )
43
+ fi
50
44
fi
45
+
46
+ # Fetch from provider if empty
47
+ # If a new provider is implemented, please set the $weather variable!
48
+ if [ -z " $weather " ]; then
49
+ __process_settings
50
+ case " $TMUX_POWERLINE_SEG_WEATHER_DATA_PROVIDER " in
51
+ " yrno" )
52
+ weather=$( __yrno)
53
+ ;;
54
+ * )
55
+ # Just read the stale cache, default to empty/blank
56
+ # Better not overwriting the previous healthy content
57
+ weather=$( __read_file_content " $cache_weather_file " )
58
+ ;;
59
+ esac
60
+ echo " $weather " > " $cache_weather_file "
61
+ fi
62
+
63
+ echo " $weather "
51
64
}
52
65
53
66
__process_settings () {
@@ -60,66 +73,52 @@ __process_settings() {
60
73
if [ -z " $TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD " ]; then
61
74
export TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD=" ${TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD_DEFAULT} "
62
75
fi
63
- if [ -z " $TMUX_POWERLINE_SEG_WEATHER_GREP " ]; then
64
- export TMUX_POWERLINE_SEG_WEATHER_GREP=" ${TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT} "
65
- fi
66
- if [ -z " $TMUX_POWERLINE_SEG_WEATHER_JSON " ]; then
67
- export TMUX_POWERLINE_SEG_WEATHER_JSON=" ${TMUX_POWERLINE_SEG_WEATHER_JSON_DEFAULT} "
76
+ if [ -z " $TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD " ]; then
77
+ export TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD=" ${TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD_DEFAULT} "
68
78
fi
69
- if [ " $TMUX_POWERLINE_SEG_WEATHER_LAT " = " auto" ] || [ " $TMUX_POWERLINE_SEG_WEATHER_LON " = " auto" ]; then
79
+ if [ " $TMUX_POWERLINE_SEG_WEATHER_LAT " = " auto" ] || [ " $TMUX_POWERLINE_SEG_WEATHER_LON " = " auto" ] || [ -z " $TMUX_POWERLINE_SEG_WEATHER_LON " ] || [ -z " $TMUX_POWERLINE_SEG_WEATHER_LAT " ] ; then
70
80
if ! get_auto_location; then
71
81
exit 8
72
82
fi
73
- elif [ -z " $TMUX_POWERLINE_SEG_WEATHER_LON " ] || [ -z " $TMUX_POWERLINE_SEG_WEATHER_LAT " ]; then
74
- echo " No location defined." >&2
75
- exit 8
76
83
fi
77
84
}
78
85
86
+ # An implementation of a weather provider, just need to echo the result, run_segment() will take care of the rest
79
87
__yrno () {
80
- degree=" "
81
- if [ -f " $tmp_file " ]; then
82
- if shell_is_macos || shell_is_bsd; then
83
- last_update=$( stat -f " %m" " ${tmp_file} " )
84
- elif shell_is_linux; then
85
- last_update=$( stat -c " %Y" " ${tmp_file} " )
86
- fi
87
- time_now=$( date +%s)
88
+ local degree=" "
88
89
89
- up_to_date=$( echo " (${time_now} -${last_update} ) < ${TMUX_POWERLINE_SEG_WEATHER_UPDATE_PERIOD} " | bc)
90
- if [ " $up_to_date " -eq 1 ]; then
91
- __read_tmp_file
90
+ # There's a chance that you will get rate limited or both location APIs are not working
91
+ # Then long and lat will be "null", as literal string
92
+ if [ -z " $TMUX_POWERLINE_SEG_WEATHER_LAT " ] || [ -z " $TMUX_POWERLINE_SEG_WEATHER_LON " ]; then
93
+ echo " Err: Unable to auto-detect your location"
94
+ return 1
95
+ fi
96
+
97
+ if weather_data=$( curl --max-time 4 -s " https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=${TMUX_POWERLINE_SEG_WEATHER_LAT} &lon=${TMUX_POWERLINE_SEG_WEATHER_LON} " ) ; then
98
+ error=$( echo " $weather_data " | grep -i " error" )
99
+ if [ -n " $error " ]; then
100
+ echo " error"
101
+ return 1
92
102
fi
103
+ degree=$( echo " $weather_data " | jq -r ' .properties.timeseries | .[0].data.instant.details.air_temperature' )
104
+ condition=$( echo " $weather_data " | jq -r ' .properties.timeseries | .[0].data.next_1_hours.summary.symbol_code' )
93
105
fi
94
106
95
107
if [ -z " $degree " ]; then
96
- if weather_data=$( curl --max-time 4 -s " https://api.met.no/weatherapi/locationforecast/2.0/compact?lat=${TMUX_POWERLINE_SEG_WEATHER_LAT} &lon=${TMUX_POWERLINE_SEG_WEATHER_LON} " ) ; then
97
- grep=$TMUX_POWERLINE_SEG_WEATHER_GREP_DEFAULT
98
- error=$( echo " $weather_data " | $grep -i " error" )
99
- if [ -n " $error " ]; then
100
- echo " error"
101
- exit 1
102
- fi
103
-
104
- jsonparser=" ${TMUX_POWERLINE_SEG_WEATHER_JSON} "
105
- degree=$( echo " $weather_data " | $jsonparser -r ' .properties.timeseries | .[0].data.instant.details.air_temperature' )
106
- condition=$( echo " $weather_data " | $jsonparser -r ' .properties.timeseries | .[0].data.next_1_hours.summary.symbol_code' )
107
- elif [ -f " ${tmp_file} " ]; then
108
- __read_tmp_file
109
- fi
108
+ echo " yr.no err: unable to fetch weather data"
109
+ return 1
110
110
fi
111
111
112
- if [ -n " $degree " ]; then
113
- if [ " $TMUX_POWERLINE_SEG_WEATHER_UNIT " == " k" ]; then
114
- degree=$( echo " ${degree} + 273.15" | bc)
115
- fi
116
- if [ " $TMUX_POWERLINE_SEG_WEATHER_UNIT " == " f" ]; then
117
- degree=$( echo " ${degree} * 9 / 5 + 32" | bc)
118
- fi
119
- # condition_symbol=$(__get_yrno_condition_symbol "$condition" "$sunrise" "$sunset")
120
- condition_symbol=$( __get_yrno_condition_symbol " $condition " )
121
- echo " ${condition_symbol} ${degree} °$( echo " $TMUX_POWERLINE_SEG_WEATHER_UNIT " | tr ' [:lower:]' ' [:upper:]' ) " | tee " ${tmp_file} "
112
+ if [ " $TMUX_POWERLINE_SEG_WEATHER_UNIT " == " k" ]; then
113
+ degree=$( echo " ${degree} + 273.15" | bc)
122
114
fi
115
+ if [ " $TMUX_POWERLINE_SEG_WEATHER_UNIT " == " f" ]; then
116
+ degree=$( echo " ${degree} * 9 / 5 + 32" | bc)
117
+ fi
118
+ # condition_symbol=$(__get_yrno_condition_symbol "$condition" "$sunrise" "$sunset")
119
+ condition_symbol=$( __get_yrno_condition_symbol " $condition " )
120
+ # Write the <content@date>, separated by a @ character, so we can fetch it later on without having to call 'stat'
121
+ echo " ${condition_symbol} ${degree} °$( echo " $TMUX_POWERLINE_SEG_WEATHER_UNIT " | tr ' [:lower:]' ' [:upper:]' ) @$( date +%s) "
123
122
}
124
123
125
124
# Get symbol for condition. Available symbol names: https://api.met.no/weatherapi/weathericon/2.0/documentation#List_of_symbols
@@ -177,23 +176,43 @@ __get_yrno_condition_symbol() {
177
176
esac
178
177
}
179
178
180
- __read_tmp_file () {
181
- if [ ! -f " $tmp_file " ]; then
179
+ __read_file_split () {
180
+ file_to_read=" $1 "
181
+ lookup_index=" $2 "
182
+ fallback_value=" $3 "
183
+ if [ ! -f " $file_to_read " ]; then
184
+ echo " $fallback_value "
185
+ return
186
+ fi
187
+ local -a file_arr
188
+ IFS=' @' read -ra file_arr <<< " $(cat " $file_to_read " )"
189
+ if [ -z " ${file_arr[$lookup_index]} " ]; then
190
+ echo " $fallback_value "
182
191
return
183
192
fi
184
- cat " ${tmp_file} "
185
- exit
193
+ echo " ${file_arr[$lookup_index]} "
194
+ }
195
+
196
+ # Default to empty/blank
197
+ __read_file_content () {
198
+ __read_file_split " $1 " 0 " "
199
+ }
200
+
201
+ # Default to 0
202
+ __read_file_last_update () {
203
+ __read_file_split " $1 " 1 0
186
204
}
187
205
188
206
get_auto_location () {
189
- local cache_file= " ${TMUX_POWERLINE_DIR_TEMPORARY} /weather_location_cache.txt "
190
- local max_cache_age=86400 # 24 hours
207
+ local max_cache_age= $TMUX_POWERLINE_SEG_WEATHER_LOCATION_UPDATE_PERIOD
208
+ local -a lat_lon_arr
191
209
192
- if [[ -f " $cache_file " ]]; then
193
- local cache_age=$(( $(date +% s) - $(stat - c % Y " $cache_file " 2 >/ dev / null || echo 0 )) )
210
+ if [[ -f " $cache_location_file " ]]; then
211
+ local cache_age=$(( $(date +% s) - $(__read_file_last_update " $cache_location_file " )) )
194
212
if (( cache_age < max_cache_age )) ; then
195
- TMUX_POWERLINE_SEG_WEATHER_LAT=$( grep -oP " (?<=TMUX_POWERLINE_SEG_WEATHER_LAT=')[^']*" " $cache_file " )
196
- TMUX_POWERLINE_SEG_WEATHER_LON=$( grep -oP " (?<=TMUX_POWERLINE_SEG_WEATHER_LON=')[^']*" " $cache_file " )
213
+ IFS=' ' read -ra lat_lon_arr <<< " $(__read_file_content " $cache_location_file " )"
214
+ TMUX_POWERLINE_SEG_WEATHER_LAT=${lat_lon_arr[0]}
215
+ TMUX_POWERLINE_SEG_WEATHER_LON=${lat_lon_arr[1]}
197
216
if [[ -n " $TMUX_POWERLINE_SEG_WEATHER_LAT " && -n " $TMUX_POWERLINE_SEG_WEATHER_LON " ]]; then
198
217
return 0
199
218
fi
@@ -214,18 +233,26 @@ get_auto_location() {
214
233
TMUX_POWERLINE_SEG_WEATHER_LON=" ${loc[1]} "
215
234
;;
216
235
esac
217
- if [[ -n " $TMUX_POWERLINE_SEG_WEATHER_LAT " && -n " $TMUX_POWERLINE_SEG_WEATHER_LON " ]]; then
218
- mkdir -p " $( dirname " $cache_file " ) "
219
- echo " TMUX_POWERLINE_SEG_WEATHER_LAT='$TMUX_POWERLINE_SEG_WEATHER_LAT '" > " $cache_file "
220
- echo " TMUX_POWERLINE_SEG_WEATHER_LON='$TMUX_POWERLINE_SEG_WEATHER_LON '" >> " $cache_file "
221
- return 0
236
+
237
+ # There's no data, move on to the next API, just don't overwrite the previous location
238
+ # Also, there's a case where lat/lon was set to "null" as a string, gotta handle it
239
+ if [[ -z " $TMUX_POWERLINE_SEG_WEATHER_LAT " ||
240
+ -z " $TMUX_POWERLINE_SEG_WEATHER_LON " ||
241
+ " $TMUX_POWERLINE_SEG_WEATHER_LAT " == " null" ||
242
+ " $TMUX_POWERLINE_SEG_WEATHER_LON " == " null" ]]; then
243
+ continue
222
244
fi
245
+
246
+ echo " $TMUX_POWERLINE_SEG_WEATHER_LAT $TMUX_POWERLINE_SEG_WEATHER_LON @$( date +%s) " > " $cache_location_file "
247
+ return 0
223
248
fi
224
249
done
225
- if [[ -f " $cache_file " ]]; then
250
+
251
+ if [[ -f " $cache_location_file " ]]; then
226
252
echo " Warning: Using stale location data (failed to refresh)" >&2
227
- TMUX_POWERLINE_SEG_WEATHER_LAT=$( grep -oP " (?<=TMUX_POWERLINE_SEG_WEATHER_LAT=')[^']*" " $cache_file " )
228
- TMUX_POWERLINE_SEG_WEATHER_LON=$( grep -oP " (?<=TMUX_POWERLINE_SEG_WEATHER_LON=')[^']*" " $cache_file " )
253
+ IFS=' ' read -ra lat_lon_arr <<< " $(__read_file_content " $cache_location_file " )"
254
+ TMUX_POWERLINE_SEG_WEATHER_LAT=${lat_lon_arr[0]}
255
+ TMUX_POWERLINE_SEG_WEATHER_LON=${lat_lon_arr[1]}
229
256
if [[ -n " $TMUX_POWERLINE_SEG_WEATHER_LAT " && -n " $TMUX_POWERLINE_SEG_WEATHER_LON " ]]; then
230
257
return 0
231
258
fi
0 commit comments