aboutsummaryrefslogtreecommitdiffstats
path: root/bin/weather-fetch.sh
diff options
context:
space:
mode:
Diffstat (limited to 'bin/weather-fetch.sh')
-rwxr-xr-xbin/weather-fetch.sh22
1 files changed, 11 insertions, 11 deletions
diff --git a/bin/weather-fetch.sh b/bin/weather-fetch.sh
index 4b37b17..e9f205b 100755
--- a/bin/weather-fetch.sh
+++ b/bin/weather-fetch.sh
@@ -21,10 +21,8 @@ if [ ! -r "$ENV_FILE" ]; then
exit 1
fi
-set -a
# shellcheck source=/dev/null
. "$ENV_FILE"
-set +a
if [ -z "${CITY:-}" ]; then
echo "weather-fetch: CITY is empty in $ENV_FILE" >&2
@@ -32,20 +30,21 @@ if [ -z "${CITY:-}" ]; then
fi
UNITS="${UNITS:-metric}"
-mkdir -p "$CACHE_DIR"
-
# Location data shares a directory with UDT's other generated state, all of
-# which is 600. Set the mode before anything lands, so no file is briefly
+# which is 600. Set the mode before anything lands, the
+# directory included, so no file is briefly
# world-readable.
umask 077
+mkdir -p "$CACHE_DIR"
+
# Temp files sit beside the target, because rename is only atomic within a
# filesystem. The widgets read the cache on their own 2s cadence, so a fetch
# killed mid-write would otherwise hand them half a cache.
TMP="$CACHE.tmp.$$"
FC="$TMP.forecast"
AIR="$TMP.air"
-trap 'rm -f "$TMP" "$FC" "$AIR"' EXIT
+trap 'rm -f "$TMP" "$FC" "$AIR" "$LOC.tmp.$$"' EXIT
# Geocode once per CITY/COUNTRY pair. The cache's first field records which
# pair it answers, so editing weather.env re-geocodes on the next run.
@@ -53,7 +52,7 @@ PAIR="$CITY,${COUNTRY:-}"
lat="" lon="" cached=""
if [ -r "$LOC" ]; then
IFS=$'\t' read -r cached lat lon < "$LOC"
- [ "$cached" = "$PAIR" ] || lat=""
+ [ "$cached" = "$PAIR" ] && [ -n "$lon" ] || lat=""
fi
if [ -z "$lat" ]; then
read -r lat lon < <(curl -fsS --max-time 15 --get \
@@ -66,7 +65,8 @@ if [ -z "$lat" ]; then
echo "weather-fetch: cannot geocode $PAIR" >&2
exit 1
fi
- printf '%s\t%s\t%s\n' "$PAIR" "$lat" "$lon" > "$LOC"
+ printf '%s\t%s\t%s\n' "$PAIR" "$lat" "$lon" > "$LOC.tmp.$$"
+ mv -f "$LOC.tmp.$$" "$LOC"
fi
if [ "$UNITS" = imperial ]; then
@@ -98,13 +98,13 @@ curl -fsS --max-time 15 --get "https://air-quality-api.open-meteo.com/v1/air-qua
# Flatten to the line format lib/weather.lua parses. The 24 hours start at
# the current hour: the first hourly slot later than an hour before now.
-if ! jq -r --arg units "$UNITS" --slurpfile air "$AIR" '
+if ! jq -r --arg units "$UNITS" --rawfile air "$AIR" '
.current.time as $now
| ([.hourly.time | to_entries[] | select(.value > $now - 3600) | .key] | first) as $i
| "units\t\($units)",
(.current | "current\t\(.time)\t\(.temperature_2m)\t\(.apparent_temperature)\t\(.weather_code)\t\(.is_day)\t\(.relative_humidity_2m)\t\(.wind_speed_10m)\t\(.wind_direction_10m)"),
"sun\t\(.daily.sunrise[0])\t\(.daily.sunset[0])",
- ($air[0].current.european_aqi // empty | "air\t\(.)"),
+ (($air | fromjson?) | .current.european_aqi // empty | "air\t\(.)"),
(.hourly as $h | range($i; [$i + 24, ($h.time | length)] | min) as $k
| "hour\t\($h.time[$k])\t\($h.temperature_2m[$k])\t\($h.weather_code[$k])\t\($h.precipitation_probability[$k])\t\($h.is_day[$k])\t\($h.uv_index[$k])"),
(.daily as $d | range(0; $d.time | length) as $k
@@ -115,7 +115,7 @@ if ! jq -r --arg units "$UNITS" --slurpfile air "$AIR" '
fi
# A 200 whose body is not a usable forecast must not replace a good cache.
-if ! grep -q $'^current\t[0-9]*\t-\\?[0-9]' "$TMP"; then
+if ! grep -q $'^current\t[0-9]\+\t-\\?[0-9]' "$TMP"; then
echo "weather-fetch: forecast has no current temperature" >&2
exit 1
fi