Replace `metar` with custom parser of NOAA XML API
authorSiraaj Khandkar <siraaj@khandkar.net>
Thu, 7 Feb 2019 22:00:21 +0000 (17:00 -0500)
committerSiraaj Khandkar <siraaj@khandkar.net>
Thu, 7 Feb 2019 22:00:21 +0000 (17:00 -0500)
TODO.md
x2/Makefile
x2/src/awk/exe/parse_noaa_api.awk [new file with mode: 0644]
x2/src/awk/lib/parse_hxpipe.awk [new file with mode: 0644]
x2/src/bash/exe/khatus_sensor_weather.sh

diff --git a/TODO.md b/TODO.md
index 90d1ad1..e9cf34f 100644 (file)
--- a/TODO.md
+++ b/TODO.md
@@ -7,7 +7,6 @@ TODO
 - show how many Debian package security-updates are available
 - monitor disk usage rate of change and alert if suspiciously fast
 - bring back CPU usage monitor
 - show how many Debian package security-updates are available
 - monitor disk usage rate of change and alert if suspiciously fast
 - bring back CPU usage monitor
-- actual METAR parser, to replace the flaky `metar` program
 - status bar templating language
 - retry/cache for sensors fetching flaky remote resources (such as weather)
 - throttling of broken sensors (constantly returns errors)
 - status bar templating language
 - retry/cache for sensors fetching flaky remote resources (such as weather)
 - throttling of broken sensors (constantly returns errors)
@@ -42,3 +41,8 @@ TODO
 - monitor battery time remaining
     - monitor accuracy (is percentage change rate on track to meet estimate?)
     - adjust estimate based on observed inaccuracies in past estimates (Kalman?)
 - monitor battery time remaining
     - monitor accuracy (is percentage change rate on track to meet estimate?)
     - adjust estimate based on observed inaccuracies in past estimates (Kalman?)
+
+DONE
+----
+- [x] actual METAR parser, to replace the flaky `metar` program
+    - Replaced it with a parser of NOAA's XML API (piping `curl | hxpipe | awk`)
index c2d3f52..e97b61f 100644 (file)
@@ -18,7 +18,7 @@ AWK_EXECUTABLES := \
        bin/khatus_parse_ip_addr \
        bin/khatus_parse_iwconfig \
        bin/khatus_parse_loadavg_file \
        bin/khatus_parse_ip_addr \
        bin/khatus_parse_iwconfig \
        bin/khatus_parse_loadavg_file \
-       bin/khatus_parse_metar_d_output \
+       bin/khatus_parse_noaa_api \
        bin/khatus_parse_mpd_status_currentsong \
        bin/khatus_parse_pactl_list_sinks \
        bin/khatus_parse_ps \
        bin/khatus_parse_mpd_status_currentsong \
        bin/khatus_parse_pactl_list_sinks \
        bin/khatus_parse_ps \
@@ -174,8 +174,12 @@ bin/khatus_parse_loadavg_file: \
        src/awk/lib/msg.awk
        $(BUILD_AWK_EXE)
 
        src/awk/lib/msg.awk
        $(BUILD_AWK_EXE)
 
-bin/khatus_parse_metar_d_output: \
-       src/awk/exe/parse_metar_d_output.awk \
+# Order of dependencies is important for khatus_parse_noaa_api!
+# parse_hxpipe MUST appear before parse_noaa_api, because the order in
+# which they match lines matters!
+bin/khatus_parse_noaa_api: \
+       src/awk/lib/parse_hxpipe.awk \
+       src/awk/exe/parse_noaa_api.awk \
        src/awk/lib/msg.awk \
        src/awk/lib/str.awk
        $(BUILD_AWK_EXE)
        src/awk/lib/msg.awk \
        src/awk/lib/str.awk
        $(BUILD_AWK_EXE)
diff --git a/x2/src/awk/exe/parse_noaa_api.awk b/x2/src/awk/exe/parse_noaa_api.awk
new file mode 100644 (file)
index 0000000..6c34091
--- /dev/null
@@ -0,0 +1,3 @@
+XmlPath == "/current_observation/temp_f" {
+    print("temperature_f", XmlPayload)  # °F
+}
diff --git a/x2/src/awk/lib/parse_hxpipe.awk b/x2/src/awk/lib/parse_hxpipe.awk
new file mode 100644 (file)
index 0000000..ab07779
--- /dev/null
@@ -0,0 +1,62 @@
+# API:
+#   XmlPath    : string
+#   XmlAttr    : dict : [XmlPath, string] -> string
+#   XmlPayload : string
+
+/^[\(\)]/ {
+    update_node()
+    next
+}
+
+/^A/ && $2 == "CDATA" {
+    update_node_attributes()
+    next
+}
+
+/^-/ {
+    XmlPayload = substr($0, 2, length($0))
+}
+
+function path_to_string(path, depth,    p, i) {
+    p = ""
+    for (i = 1; i <= depth; i++) {
+        p = p "/" path[i]
+    }
+    return p
+}
+
+function update_node(    paren, name, key, val, path, attr) {
+    paren = substr($1, 1, 1)
+    name = substr($1, 2, length($1) - 1)
+    if (paren == "(") {
+        _depth++
+        _path[_depth] = name
+        XmlPath = path_to_string(_path, _depth)
+        for (key in _hxpipe_curr_attrs) {
+            val = _hxpipe_curr_attrs[key]
+            XmlAttr[XmlPath, key] = val
+        }
+    } else if (paren == ")") {
+        delete _hxpipe_curr_attrs
+        XmlPayload = ""
+        for (key in XmlAttr) {
+            split(key, k, SUBSEP)
+            path = k[1]
+            attr = k[2]
+            if (path == XmlPath) delete XmlAttr[key]
+        }
+        _depth--
+        XmlPath = path_to_string(_path, _depth)
+    } else {
+        printf("ERROR in input line %d - not a parenthesis: \"%s\"\n", NR, paren) > "/dev/stderr"
+        exit 1
+    }
+}
+
+function update_node_attributes(    key, val, s) {
+    key = substr($1, 2, length($1))
+    val = $0
+    s = " +"
+    sub("^" $1 s $2 s, "", val)
+    _hxpipe_curr_attrs[key] = val
+}
index 371010f..a41f14a 100644 (file)
@@ -5,4 +5,9 @@ set -e
 dir_bin="$1"
 weather_station_id="$2"
 
 dir_bin="$1"
 weather_station_id="$2"
 
-metar -d "$weather_station_id" 2>&1 | "$dir_bin"/khatus_parse_metar_d_output
+curl \
+    -X GET \
+    -H "accept: application/vnd.noaa.obs+xml" \
+    "https://api.weather.gov/stations/${weather_station_id}/observations/latest?require_qc=false" \
+| hxpipe \
+| "$dir_bin"/khatus_parse_noaa_api
This page took 0.026587 seconds and 4 git commands to generate.