data/
+bin/khatus_bar
+bin/khatus_actuate_alert_to_notify_send
+bin/khatus_actuate_device_add_to_automount
+bin/khatus_actuate_status_bar_to_xsetroot_name
+bin/khatus_monitor_devices
+bin/khatus_monitor_energy
+bin/khatus_monitor_errors
+bin/khatus_parse_bluetoothctl_show
+bin/khatus_parse_df_pcent
+bin/khatus_parse_fan_file
+bin/khatus_parse_free
+bin/khatus_parse_ip_addr
+bin/khatus_parse_iwconfig
+bin/khatus_parse_loadavg_file
+bin/khatus_parse_metar_d_output
+bin/khatus_parse_mpd_status_currentsong
+bin/khatus_parse_pactl_list_sinks
+bin/khatus_parse_ps
+bin/khatus_parse_sys_block_stat
+bin/khatus_parse_udevadm_monitor_block
+bin/khatus_parse_upower
--- /dev/null
+PATH_TO_AWK := /usr/bin/awk
+AWK_EXECUTABLES := \
+ bin/khatus_bar \
+ bin/khatus_actuate_alert_to_notify_send \
+ bin/khatus_actuate_device_add_to_automount \
+ bin/khatus_actuate_status_bar_to_xsetroot_name \
+ bin/khatus_monitor_devices \
+ bin/khatus_monitor_energy \
+ bin/khatus_monitor_errors \
+ bin/khatus_parse_bluetoothctl_show \
+ bin/khatus_parse_df_pcent \
+ bin/khatus_parse_fan_file \
+ bin/khatus_parse_free \
+ bin/khatus_parse_ip_addr \
+ bin/khatus_parse_iwconfig \
+ bin/khatus_parse_loadavg_file \
+ bin/khatus_parse_metar_d_output \
+ bin/khatus_parse_mpd_status_currentsong \
+ bin/khatus_parse_pactl_list_sinks \
+ bin/khatus_parse_ps \
+ bin/khatus_parse_sys_block_stat \
+ bin/khatus_parse_udevadm_monitor_block \
+ bin/khatus_parse_upower
+
+.PHONY: \
+ build \
+ clean
+
+
+build: $(AWK_EXECUTABLES)
+
+clean:
+ rm $(AWK_EXECUTABLES)
+
+
+bin/khatus_bar: \
+ src/awk/exe/bar.awk \
+ src/awk/lib/cache.awk \
+ src/awk/lib/msg_in.awk \
+ src/awk/lib/msg_out.awk \
+ src/awk/lib/util.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_actuate_alert_to_notify_send: \
+ src/awk/exe/actuate_alert_to_notify_send.awk \
+ src/awk/lib/msg_in.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_actuate_device_add_to_automount: \
+ src/awk/exe/actuate_device_add_to_automount.awk \
+ src/awk/lib/msg_in.awk \
+ src/awk/lib/msg_out.awk \
+ src/awk/lib/alert.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_actuate_status_bar_to_xsetroot_name: \
+ src/awk/exe/actuate_status_bar_to_xsetroot_name.awk \
+ src/awk/lib/msg_in.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_monitor_devices: \
+ src/awk/exe/monitor_devices.awk \
+ src/awk/lib/msg_in.awk \
+ src/awk/lib/msg_out.awk \
+ src/awk/lib/alert.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_monitor_energy: \
+ src/awk/exe/monitor_energy.awk \
+ src/awk/lib/msg_in.awk \
+ src/awk/lib/msg_out.awk \
+ src/awk/lib/alert.awk \
+ src/awk/lib/util.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_monitor_errors: \
+ src/awk/exe/monitor_errors.awk \
+ src/awk/lib/msg_in.awk \
+ src/awk/lib/msg_out.awk \
+ src/awk/lib/alert.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_bluetoothctl_show: \
+ src/awk/exe/parse_bluetoothctl_show.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_df_pcent: \
+ src/awk/exe/parse_df_pcent.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_fan_file: \
+ src/awk/exe/parse_fan_file.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_free: \
+ src/awk/exe/parse_free.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_ip_addr: \
+ src/awk/exe/parse_ip_addr.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_iwconfig: \
+ src/awk/exe/parse_iwconfig.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_loadavg_file: \
+ src/awk/exe/parse_loadavg_file.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_metar_d_output: \
+ src/awk/exe/parse_metar_d_output.awk \
+ src/awk/lib/msg_out.awk \
+ src/awk/lib/util.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_mpd_status_currentsong: \
+ src/awk/exe/parse_mpd_status_currentsong.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_pactl_list_sinks: \
+ src/awk/exe/parse_pactl_list_sinks.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_ps: \
+ src/awk/exe/parse_ps.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_sys_block_stat: \
+ src/awk/exe/parse_sys_block_stat.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_udevadm_monitor_block: \
+ src/awk/exe/parse_udevadm_monitor_block.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
+
+bin/khatus_parse_upower: \
+ src/awk/exe/parse_upower.awk \
+ src/awk/lib/msg_out.awk
+ echo '#! $(PATH_TO_AWK) -f' > $@
+ cat $^ >> $@
+ chmod +x $@
--- /dev/null
+#! /usr/bin/awk -f
+
+BEGIN {
+ aliases["@energy"] = "bar_make_status_energy()"
+ aliases["@memory"] = "bar_make_status_mem()"
+ aliases["@processes"] = "bar_make_status_procs()"
+ aliases["@cpu"] = "bar_make_status_cpu()"
+ aliases["@disk"] = "bar_make_status_disk()"
+ aliases["@net"] = "bar_make_status_net()"
+ aliases["@bluetooth"] = "bar_make_status_bluetooth()"
+ aliases["@backlight"] = "bar_make_status_screen_brightness()"
+ aliases["@volume"] = "bar_make_status_volume()"
+ aliases["@mpd"] = "bar_make_status_mpd()"
+ aliases["@weather"] = "bar_make_status_weather()"
+ aliases["@datetime"] = "bar_make_status_datetime()"
+ out = "function bar_make_status( position, bar, sep, i, j) {\n"
+ n = split(Status_Bar, s, ",")
+ for (i=1; i<=n; i++) {
+ alias = s[i]
+ function_call = aliases[alias]
+ if (function_call) {
+ out = out " position[++i] = " function_call ";\n"
+ } else {
+ printf("Unexpected status bar component alias: \"%s\"\n", alias) \
+ > "/dev/stderr"
+ exit(1)
+ }
+ }
+ out = out "\
+ bar = \"\";\
+ sep = \"\";\
+ for (j = 1; j <= i; j++) {\
+ bar = bar sep position[j];\
+ sep = \" \";\
+ }\
+ return bar;\
+ }";
+ print out
+}
+++ /dev/null
-#! /usr/bin/awk -f
-
-BEGIN {
- aliases["@energy"] = "make_status_energy()"
- aliases["@memory"] = "make_status_mem()"
- aliases["@processes"] = "make_status_procs()"
- aliases["@cpu"] = "make_status_cpu()"
- aliases["@disk"] = "make_status_disk()"
- aliases["@net"] = "make_status_net()"
- aliases["@bluetooth"] = "make_status_bluetooth()"
- aliases["@backlight"] = "make_status_screen_brightness()"
- aliases["@volume"] = "make_status_volume()"
- aliases["@mpd"] = "make_status_mpd()"
- aliases["@weather"] = "make_status_weather()"
- aliases["@datetime"] = "make_status_datetime()"
- out = "function make_status_bar( position, bar, sep, i, j) {\n"
- n = split(Status_Bar, s, ",")
- for (i=1; i<=n; i++) {
- alias = s[i]
- function_call = aliases[alias]
- if (function_call) {
- out = out " position[++i] = " function_call ";\n"
- } else {
- printf("Unexpected status bar component alias: \"%s\"\n", alias) \
- > "/dev/stderr"
- exit(1)
- }
- }
- out = out "\
- bar = \"\";\
- sep = \"\";\
- for (j = 1; j <= i; j++) {\
- bar = bar sep position[j];\
- sep = \" \";\
- }\
- return bar;\
- }";
- print out
-}
+++ /dev/null
-#! /usr/bin/awk -f
-
-BEGIN {
- FS = msg_fs ? msg_fs : "|"
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
-$1 == "OK" && \
-$2 == "khatus_sensor_devices" \
-{
- alert("low", "BlockDeviceEvent", $3 " " $4)
-}
-
-function alert(priority, subject, body) {
- # priority : "low" | "med" | "hi"
- # subject : no spaces
- # body : anything
- print("OK", "khatus_monitor_devices", "alert", priority, subject, body)
-}
+++ /dev/null
-#! /usr/bin/awk -f
-
-BEGIN {
- FS = msg_fs ? msg_fs : "|"
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-
- # TODO: Read spec from a file
- bat_alert_spec[100] = "low|Energy_Bellow_Full|Must have perfection!"
- bat_alert_spec[50] = "low|Energy_Bellow_Half|Where is the charger?"
- bat_alert_spec[20] = "med|Energy_Low|Get the charger."
- bat_alert_spec[15] = "med|Energy_Low|Get the charger!"
- bat_alert_spec[10] = "hi|Energy_Low|Plug it in, ASAP!"
- bat_alert_spec[5] = "hi|Energy_CRITICALLY_Low|CHARGE NOW!!! GO GO GO!!!"
-}
-
-$1 == "OK" && \
-$2 == "khatus_sensor_energy" && \
-$3 == "line_power" {
- line_power_prev = line_power_curr
- line_power_curr = $4
- if (line_power_curr == "no" && line_power_prev != "no") {
- alert("low", "PowerUnplugged", "")
- }
-}
-
-$1 == "OK" && \
-$2 == "khatus_sensor_energy" && \
-$3 == "battery_state" {
- battery_state_prev = battery_state_curr
- battery_state_curr = $4
-}
-
-$1 == "OK" && \
-$2 == "khatus_sensor_energy" && \
-$3 == "battery_percentage" {
- # TODO: Re-think the spec - can't rely on order of keys
- battery_percentage = ensure_numeric($4)
- if (battery_state_curr == "discharging") {
- for (threshold in bat_alert_spec) {
- threshold = ensure_numeric(threshold)
- if (battery_percentage <= threshold && !alerted[threshold]) {
- split(bat_alert_spec[threshold], msg, "|")
- priority = msg[1]
- subject = msg[2]
- body = sprintf("%d%% %s", battery_percentage, msg[3])
- alert(priority, subject, body)
- alerted[threshold]++
- }
- }
- } else {
- delete alerted
- }
-}
-
-function alert(priority, subject, body) {
- # priority : "low" | "med" | "hi"
- # subject : no spaces
- # body : anything
- print("OK", "khatus_monitor_energy", "alert", priority, subject, body)
-}
-
-function ensure_numeric(n) {
- return n + 0
-}
-
-#-------------------------------
-# Why do we need ensure_numeric?
-#-------------------------------
-# awk appears to be guessing the type of an inputted scalar based on usage, so
-# if we read-in a number, but did not use it in any numeric operations, but did
-# use as a string (even in just a format string!) - it will be treated as a
-# string and can lead to REALLY SURPRISING behavior in conditional statements,
-# where smaller number may compare as greater than the bigger ones, such as.
-#
-# Demo:
-#
-# $ awk 'BEGIN {x = "75"; y = "100"; sprintf("x: %d, y: %d\n", x, y); if (x > y) {print "75 > 100"} else if (x < y) {print "75 < 100"}}'
-# 75 < 100
-# $ awk 'BEGIN {x = "75"; y = "100"; sprintf("x: %s, y: %d\n", x, y); if (x > y) {print "75 > 100"} else if (x < y) {print "75 < 100"}}'
-# 75 > 100
-
-# However, once used as a number, seems to stay that way even after being
-# used as string:
-#
-# $ awk 'BEGIN {x = "75"; y = "100"; x + y; sprintf("x: %s, y: %d\n", x, y); if (x > y) {print "75 > 100"} else if (x < y) {print "75 < 100"}}'
-# 75 < 100
-#
-# $ awk 'BEGIN {x = "75"; y = "100"; x + y; sprintf("x: %s, y: %d\n", x, y); z = x y; if (x > y) {print "75 > 100"} else if (x < y) {print "75 < 100"}}'
-# 75 < 100
-#
-# $ awk 'BEGIN {x = "75"; y = "100"; x + y; z = x y; if (x > y) {print "75 > 100"} else if (x < y) {print "75 < 100"}}'
-# 75 < 100
-# $ awk 'BEGIN {x = "75"; y = "100"; z = x y; if (x > y) {print "75 > 100"} else if (x < y) {print "75 < 100"}}'
-# 75 > 100
+++ /dev/null
-#! /usr/bin/awk -f
-
-BEGIN {
- FS = msg_fs ? msg_fs : "|"
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
-/^ERROR/ {
- src = $2
- # Not just using $6 for body - because body might contain a character
- # identical to FS
- len_line = length($0)
- len_head = length($1 FS $2 FS)
- len_body = len_line - len_head
- body = substr($0, len_head + 1, len_body)
- alert("hi", "Error_in_" src, body)
-}
-
-function alert(priority, subject, body) {
- # priority : "low" | "med" | "hi"
- # subject : no spaces
- # body : anything
- print("OK", "khatus_monitor_errors", "alert", priority, subject, body)
-}
+++ /dev/null
-#! /usr/bin/awk -f
-
-BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
-{
- key = $1
- sub(":$", "", key)
- val = $2
- print(key, val)
-}
+++ /dev/null
-#! /usr/bin/awk -f
-
-BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
-$1 == "Mem:" {
- print("total", $2)
- print("used" , $3)
-}
+++ /dev/null
-#! /usr/bin/awk -f
-
-BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
-{
- print("sectors_read" , $3)
- print("sectors_written", $7)
-}
-v Opt_Net_Interfaces_To_Show=wlp3s0 \
-v Opt_Pulseaudio_Sink=0 \
-v GC_Interval=300 \
- -f <(./bin/khatus_gen_make_status_bar \
+ -f <(./bin/khatus_gen_bar_make_status \
-v Status_Bar='@energy,@memory,@processes,@cpu,@disk,@net,@bluetooth,@backlight,@volume,@mpd,@weather,@datetime' \
) \
) \
-#! /usr/bin/awk -f
-
BEGIN {
# Set the correct value as any other AWK variable:
#
- # khatus_actuate_alert_to_notify_send -v display="$CORRECT_DISPLAY"
+ # khatus_actuate_alert_to_notify_send -v Display="$CORRECT_DISPLAY"
#
- display = ":0"
- FS = msg_fs ? msg_fs : "|"
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
+ Display = Display ? Display : ":0"
}
$1 == "OK" && \
-$3 == "alert" {
- src = $2
- priority = $4
- subject = $5
+$2 == "alert" {
+ priority = $3
+ subject = $4
- # Not just using $6 for body - because body might contain a character
+ # Not just using $5 for body - because body might contain a character
# identical to FS
len_line = length($0)
len_head = length($1 FS $2 FS $3 FS $4 FS $5 FS)
len_body = len_line - len_head
body = substr($0, len_head + 1, len_body)
- sep = body ? "\n" : ""
- body = body sep "--" src
urgency = priority
sub("hi" , "critical", urgency)
sub("med", "normal" , urgency)
cmd = \
sprintf(\
"DISPLAY=%s notify-send -u %s %s \" %s\"",
- display, urgency, subject, body \
+ Display, urgency, subject, body \
)
system(cmd)
next
-#! /usr/bin/awk -f
-
BEGIN {
- FS = msg_fs ? msg_fs : "|"
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
- Module = "khatus_actuate_device_add_to_automount"
# Typically some file manager (thunar, pcmanfm, etc.), but can be whatever.
Execute_On_Mount = Execute_On_Mount ? Execute_On_Mount : ""
}
alert("hi", "failed-to-mount-device", path)
}
}
-
-function alert(priority, subject, body) {
- # priority : "low" | "med" | "hi"
- # subject : no spaces
- # body : anything
- print("OK", Module, "alert", priority, subject, body)
-}
-#! /usr/bin/awk -f
-
-BEGIN {
- FS = msg_fs ? msg_fs : "|"
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
$1 == "OK" && \
$2 == "khatus_bar" && \
$3 == "status_bar" {
-#! /usr/bin/awk -f
-
# Naming convention:
# Variables:
# - global, builtin : ALLCAPS
# Functions:
# - global, public : snake_case
-BEGIN {
- FS = msg_fs ? msg_fs : "|"
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
- GC_Interval = GC_Interval ? GC_Interval : 3600 # seconds
-
- _total_to_diff["khatus_sensor_net_addr_io", "bytes_read" ] = 1
- _total_to_diff["khatus_sensor_net_addr_io", "bytes_written" ] = 1
- _total_to_diff["khatus_sensor_disk_io" , "sectors_read" ] = 1
- _total_to_diff["khatus_sensor_disk_io" , "sectors_written"] = 1
-
- # (x * y) / z = x * w
- # ==> w = y / z
- # (x * bytes_per_sector) / bytes_per_mb = x * scaling_factor
- # ==> scaling_factor = bytes_per_sector / bytes_per_mb
- _bytes_per_sector = 512
- _bytes_per_mb = 1024 * 1024
- _scale["khatus_sensor_disk_io", "sectors_written"] = _bytes_per_sector / _bytes_per_mb
- _scale["khatus_sensor_disk_io", "sectors_read" ] = _bytes_per_sector / _bytes_per_mb
- # (x / y) = x * z
- # ==> z = 1 / y
- # x / bytes_per_mb = x * scaling_factor
- # ==> scaling_factor = 1 / bytes_per_mb
- _scale["khatus_sensor_net_addr_io", "bytes_written"] = 1 / _bytes_per_mb
- _scale["khatus_sensor_net_addr_io", "bytes_read" ] = 1 / _bytes_per_mb
-}
-
# -----------------------------------------------------------------------------
# Input
# -----------------------------------------------------------------------------
$1 == "OK" && \
$2 == "khatus_sensor_datetime" {
- # Code for make_status_bar definition is expected to be passed as an
+ # Code for bar_make_status is expected to be passed as an
# additional source file, using -f flag.
- print_msg_ok("status_bar", make_status_bar())
-}
-
-# -----------------------------------------------------------------------------
-# Cache
-# -----------------------------------------------------------------------------
-
-function cache_update( src, key, val, len_line, len_head, len_val, time) {
- src = $2
- key = $3
- # Not just using $4 for val - because an unstructured value (like name of a
- # song) might contain a character identical to FS
- len_line = length($0)
- len_head = length($1 FS $2 FS $3 FS)
- len_val = len_line - len_head
- val = substr($0, len_head + 1, len_val)
- val = cache_maybe_total_to_diff(src, key, val)
- val = cache_maybe_scale(src, key, val)
- _cache[src, key] = val
- time = cache_get_time()
- _cache_mtime[src, key] = time
- if (time % GC_Interval == 0) {
- cache_gc()
- }
-}
-
-function cache_get(result, src, key, ttl, time, age, is_expired) {
- time = cache_get_time()
- _cache_atime[src, key] = time
- age = time - _cache_mtime[src, key]
- result["is_expired"] = ttl && age > ttl # ttl = 0 => forever
- result["value"] = _cache[src, key]
-}
-
-function cache_res_fmt_or_def(result, format, default) {
- return result["is_expired"] ? default : sprintf(format, result["value"])
-}
-
-function cache_get_fmt_def(src, key, ttl, format, default, result) {
- default = default ? default : "--"
- cache_get(result, src, key, ttl)
- return cache_res_fmt_or_def(result, format, default)
-}
-
-function cache_get_time( src, key, time) {
- src = "khatus_sensor_datetime"
- key = "epoch"
- time = _cache[src, key]
- _cache_atime[src, key] = time
- return time
+ msg_out_ok("status_bar", bar_make_status())
}
-function cache_gc( src_and_key, parts, src, key, unused_for) {
- for (src_and_key in _cache) {
- split(src_and_key, parts, SUBSEP)
- src = parts[1]
- key = parts[2]
- val = _cache[src, key]
- unused_for = cache_get_time() - _cache_atime[src, key]
- if (unused_for > GC_Interval) {
- print_msg_info(\
- "cache_gc",
- sprintf(\
- "Deleting unused data SRC=%s KEY=%s VAL=%s",
- src, key, val\
- ) \
- )
- delete _cache[src, key]
- }
- }
-}
-
-function cache_maybe_total_to_diff(src, key, val, key_parts) {
- split(key, key_parts, Kfs)
- if (_total_to_diff[src, key_parts[1]]) {
- _prev[src, key] = _curr[src, key]
- _curr[src, key] = val
- return (_curr[src, key] - _prev[src, key])
- } else {
- return val
- }
-}
-
-function cache_maybe_scale(src, key, val, key_parts) {
- split(key, key_parts, Kfs)
- if ((src SUBSEP key_parts[1]) in _scale) {
- return val * _scale[src, key_parts[1]]
- } else {
- return val
- }
-}
# -----------------------------------------------------------------------------
# Status bar
# -----------------------------------------------------------------------------
-function make_status_energy( state, charge, direction_of_change) {
+function bar_make_status_energy( state, charge, direction_of_change) {
cache_get(state , "khatus_sensor_energy", "battery_state" , 0)
cache_get(charge, "khatus_sensor_energy", "battery_percentage", 0)
return sprintf("E%s%d%%", direction_of_change, charge["value"])
}
-function make_status_mem( total, used, percent, status) {
+function bar_make_status_mem( total, used, percent, status) {
cache_get(total, "khatus_sensor_memory", "total", 5)
cache_get(used , "khatus_sensor_memory", "used" , 5)
# Checking total["value"] to avoid division by zero when data is missing
!used["is_expired"] && \
total["value"] \
) {
- percent = round((used["value"] / total["value"]) * 100)
+ percent = util_round((used["value"] / total["value"]) * 100)
status = sprintf("%d%%", percent)
} else {
status = "__"
return sprintf("M=%s", status)
}
-function make_status_procs() {
+function bar_make_status_procs() {
# From man ps:
# D uninterruptible sleep (usually IO)
# R running or runnable (on run queue)
return sprintf("P=[%s %sr %sd %st %si %sz]", all, r, d, t, i, z)
}
-function make_status_cpu( l, t, f) {
+function bar_make_status_cpu( l, t, f) {
l_src = "khatus_sensor_loadavg"
t_src = "khatus_sensor_temperature"
f_src = "khatus_sensor_fan"
return sprintf("C=[%s %s°C %srpm]", l, t, f)
}
-function make_status_disk( u, w, r, src_u, src_io) {
+function bar_make_status_disk( u, w, r, src_u, src_io) {
src_u = "khatus_sensor_disk_space"
src_io = "khatus_sensor_disk_io"
u = cache_get_fmt_def(src_u , "disk_usage_percentage", 10, "%s")
return sprintf("D=[%s%% %s▲ %s▼]", u, w, r)
}
-function make_status_net( \
+function bar_make_status_net( \
number_of_net_interfaces_to_show, \
net_interfaces_to_show, \
io, \
return sprintf("N[%s]", out)
}
-function make_status_bluetooth( src, key) {
+function bar_make_status_bluetooth( src, key) {
src = "khatus_sensor_bluetooth_power"
key = "power_status"
return sprintf("B=%s", cache_get_fmt_def(src, key, 10, "%s"))
}
-function make_status_screen_brightness( src, key) {
+function bar_make_status_screen_brightness( src, key) {
src = "khatus_sensor_screen_brightness"
key = "percentage"
return sprintf("*%s%%", cache_get_fmt_def(src, key, 5, "%d"))
}
-function make_status_volume( sink, mu, vl, vr, show) {
+function bar_make_status_volume( sink, mu, vl, vr, show) {
sink = Opt_Pulseaudio_Sink
cache_get(mu, "khatus_sensor_volume", "mute" Kfs sink, 5)
cache_get(vl, "khatus_sensor_volume", "vol_left" Kfs sink, 5)
if (mu["value"] == "yes") {show = "X"}
else if (mu["value"] == "no") {show = vl["value"] " " vr["value"]}
else {
- print_msg_error(\
- "make_status_volume", \
+ msg_out_error(\
+ "bar_make_status_volume", \
"Unexpected value for 'mute' field: " mu["value"] \
)
}
return sprintf("(%s)", show)
}
-function make_status_mpd( state, status) {
+function bar_make_status_mpd( state, status) {
cache_get(state, "khatus_sensor_mpd", "state", 5)
if (!state["is_expired"] && state["value"]) {
if (state["value"] == "play") {
- status = make_status_mpd_state_known("▶")
+ status = bar_make_status_mpd_state_known("▶")
} else if (state["value"] == "pause") {
- status = make_status_mpd_state_known("❚❚")
+ status = bar_make_status_mpd_state_known("❚❚")
} else if (state["value"] == "stop") {
- status = make_status_mpd_state_known("⬛")
+ status = bar_make_status_mpd_state_known("⬛")
} else {
- print_msg_error(\
- "make_status_mpd", \
+ msg_out_error(\
+ "bar_make_status_mpd", \
"Unexpected value for 'state' field: " state["value"] \
)
status = "--"
return sprintf("[%s]", status)
}
-function make_status_mpd_state_known(symbol, s, song, time, percentage) {
+function bar_make_status_mpd_state_known(symbol, s, song, time, percentage) {
s = "khatus_sensor_mpd"
song = cache_get_fmt_def(s, "song" , 5, "%s", "?")
time = cache_get_fmt_def(s, "play_time_minimal_units", 5, "%s", "?")
return sprintf("%s %s %s %s", symbol, time, percent, song)
}
-function make_status_weather( src, hour, t_f) {
+function bar_make_status_weather( src, hour, t_f) {
src = "khatus_sensor_weather"
hour = 60 * 60
t_f = cache_get_fmt_def(src, "temperature_f", 3 * hour, "%d")
return sprintf("%s°F", t_f)
}
-function make_status_datetime( dt) {
+function bar_make_status_datetime( dt) {
return cache_get_fmt_def("khatus_sensor_datetime", "datetime", 5, "%s")
}
-
-# -----------------------------------------------------------------------------
-# Output
-# -----------------------------------------------------------------------------
-
-function print_msg_ok(key, val) {
- print_msg("OK", key, val, "/dev/stdout")
-}
-
-function print_msg_info(location, msg) {
- print_msg("INFO", location, msg, "/dev/stderr")
-}
-
-function print_msg_error(location, msg) {
- print_msg("ERROR", location, msg, "/dev/stderr")
-}
-
-function print_msg(status, key, val, channel) {
- print(status, "khatus_bar", key, val) > channel
-}
-
-# -----------------------------------------------------------------------------
-# Numbers
-# -----------------------------------------------------------------------------
-
-function round(n) {
- return int(n + 0.5)
-}
--- /dev/null
+$1 == "OK" && \
+$2 == "khatus_sensor_devices" \
+{
+ alert("low", "BlockDeviceEvent", $3 " " $4)
+}
--- /dev/null
+BEGIN {
+ # TODO: Read spec from a file
+ bat_alert_spec[100] = "low|Energy_Bellow_Full|Must have perfection!"
+ bat_alert_spec[50] = "low|Energy_Bellow_Half|Where is the charger?"
+ bat_alert_spec[20] = "med|Energy_Low|Get the charger."
+ bat_alert_spec[15] = "med|Energy_Low|Get the charger!"
+ bat_alert_spec[10] = "hi|Energy_Low|Plug it in, ASAP!"
+ bat_alert_spec[5] = "hi|Energy_CRITICALLY_Low|CHARGE NOW!!! GO GO GO!!!"
+}
+
+$1 == "OK" && \
+$2 == "khatus_sensor_energy" && \
+$3 == "line_power" {
+ line_power_prev = line_power_curr
+ line_power_curr = $4
+ if (line_power_curr == "no" && line_power_prev != "no") {
+ alert("low", "PowerUnplugged", "")
+ }
+}
+
+$1 == "OK" && \
+$2 == "khatus_sensor_energy" && \
+$3 == "battery_state" {
+ battery_state_prev = battery_state_curr
+ battery_state_curr = $4
+}
+
+$1 == "OK" && \
+$2 == "khatus_sensor_energy" && \
+$3 == "battery_percentage" {
+ # TODO: Re-think the spec - can't rely on order of keys
+ battery_percentage = util_ensure_numeric($4)
+ if (battery_state_curr == "discharging") {
+ for (threshold in bat_alert_spec) {
+ threshold = util_ensure_numeric(threshold)
+ if (battery_percentage <= threshold && !_alerted[threshold]) {
+ split(bat_alert_spec[threshold], msg, "|")
+ priority = msg[1]
+ subject = msg[2]
+ body = sprintf("%d%% %s", battery_percentage, msg[3])
+ alert(priority, subject, body)
+ _alerted[threshold]++
+ }
+ }
+ } else {
+ delete _alerted
+ }
+}
--- /dev/null
+/^ERROR/ {
+ src = $2
+ # Not just using $3 for body - because body might contain a character
+ # identical to FS
+ len_line = length($0)
+ len_head = length($1 FS $2 FS)
+ len_body = len_line - len_head
+ body = substr($0, len_head + 1, len_body)
+ alert("hi", "ERROR_IN_" src, body)
+}
-#! /usr/bin/awk -f
-
-BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
/^Controller / {
controller = $2
controllers[++ctrl_count] = controller
-#! /usr/bin/awk -f
-
-BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
NR == 2 {
percentage = $1
sub("%$", "", percentage)
--- /dev/null
+{
+ key = $1
+ sub(":$", "", key)
+ val = $2
+ print(key, val)
+}
--- /dev/null
+$1 == "Mem:" {
+ print("total", $2)
+ print("used" , $3)
+}
-#! /usr/bin/awk -f
-
-BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
/^[0-9]+:/ {
sub(":$", "", $1)
sub(":$", "", $2)
-#! /usr/bin/awk -f
-#
# Example iwconfig output:
# -----------------------
# $ iwconfig wlp3s0
#
# USAGE: khatus_parse_iwconfig -v requested_interface="$wifi_interface"
-BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
/^[a-z0-9]+ +IEEE 802\.11 +ESSID:/ {
interface = $1
split($4, essid_parts, ":")
-#! /usr/bin/awk -f
-
-BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
# 0.71 1.04 1.12 1/325 2409
{
split($4, sched, "/")
-#! /usr/bin/awk -f
-#
# Qualifying the name as "_d_output" lest it be mistaken for parser of actual
# metar format.
-BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
/METAR pattern not found in NOAA data/ {
failures++
exit
/[A-z][a-z]+ *: / {
split($0, line, ":")
- key = strip(line[1])
- val = strip(line[2])
+ key = util_strip(line[1])
+ val = util_strip(line[2])
values[NR] = val
first[key] = NR
last[key] = NR
}
/^ +/ {
- values[NR] = strip($0)
+ values[NR] = util_strip($0)
last[key] = NR
}
}
}
}
-
-function strip(s) {
- sub("^ *", "", s)
- sub(" *$", "", s)
- return s
-}
-#! /usr/bin/awk -f
-
-BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
# Msg separator
/^OK/ {msg_count++; next}
-#! /usr/bin/awk -f
-
-BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
/^Sink \#[0-9]+$/ {
sub("^#", "", $2)
sink = $2
-#! /usr/bin/awk -f
-
-BEGIN {
- OFS = "|"
- Kfs = ":"
-}
-
{
pid = $1
state = $2
--- /dev/null
+{
+ print("sectors_read" , $3)
+ print("sectors_written", $7)
+}
-#! /usr/bin/awk -f
-
BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-
Re_Begin = "^UDEV + \[ *[0-9]+\.[0-9]+\] +"
}
-#! /usr/bin/awk -f
-
-BEGIN {
- OFS = msg_fs ? msg_fs : "|"
- Kfs = key_fs ? key_fs : ":"
-}
-
# When parsing 'upower --dump'
/^Device:[ \t]+/ {
device["path"] = $2
--- /dev/null
+function alert(priority, subject, body) {
+ # priority : "low" | "med" | "hi"
+ # subject : string without spaces
+ # body : anything
+ print("OK", "alert", priority, subject, body)
+}
--- /dev/null
+# Naming convention:
+# Variables:
+# - global, builtin : ALLCAPS
+# - global, public : Camel_Snake_Man_Bear_Pig
+# - global, private : _snake_case_prefixed_underscore
+# - local : snake_case
+# Functions:
+# - global, public : snake_case
+
+BEGIN {
+ GC_Interval = GC_Interval ? GC_Interval : 3600 # seconds
+
+ _total_to_diff["khatus_sensor_net_addr_io", "bytes_read" ] = 1
+ _total_to_diff["khatus_sensor_net_addr_io", "bytes_written" ] = 1
+ _total_to_diff["khatus_sensor_disk_io" , "sectors_read" ] = 1
+ _total_to_diff["khatus_sensor_disk_io" , "sectors_written"] = 1
+
+ # (x * y) / z = x * w
+ # ==> w = y / z
+ # (x * bytes_per_sector) / bytes_per_mb = x * scaling_factor
+ # ==> scaling_factor = bytes_per_sector / bytes_per_mb
+ _bytes_per_sector = 512
+ _bytes_per_mb = 1024 * 1024
+ _scale["khatus_sensor_disk_io", "sectors_written"] = _bytes_per_sector / _bytes_per_mb
+ _scale["khatus_sensor_disk_io", "sectors_read" ] = _bytes_per_sector / _bytes_per_mb
+ # (x / y) = x * z
+ # ==> z = 1 / y
+ # x / bytes_per_mb = x * scaling_factor
+ # ==> scaling_factor = 1 / bytes_per_mb
+ _scale["khatus_sensor_net_addr_io", "bytes_written"] = 1 / _bytes_per_mb
+ _scale["khatus_sensor_net_addr_io", "bytes_read" ] = 1 / _bytes_per_mb
+}
+
+function cache_update( src, key, val, len_line, len_head, len_val, time) {
+ src = $2
+ key = $3
+ # Not just using $4 for val - because an unstructured value (like name of a
+ # song) might contain a character identical to FS
+ len_line = length($0)
+ len_head = length($1 FS $2 FS $3 FS)
+ len_val = len_line - len_head
+ val = substr($0, len_head + 1, len_val)
+ val = cache_maybe_total_to_diff(src, key, val)
+ val = cache_maybe_scale(src, key, val)
+ _cache[src, key] = val
+ time = cache_get_time()
+ _cache_mtime[src, key] = time
+ if (time % GC_Interval == 0) {
+ cache_gc()
+ }
+}
+
+function cache_get(result, src, key, ttl, time, age, is_expired) {
+ time = cache_get_time()
+ _cache_atime[src, key] = time
+ age = time - _cache_mtime[src, key]
+ result["is_expired"] = ttl && age > ttl # ttl = 0 => forever
+ result["value"] = _cache[src, key]
+}
+
+function cache_res_fmt_or_def(result, format, default) {
+ return result["is_expired"] ? default : sprintf(format, result["value"])
+}
+
+function cache_get_fmt_def(src, key, ttl, format, default, result) {
+ default = default ? default : "--"
+ cache_get(result, src, key, ttl)
+ return cache_res_fmt_or_def(result, format, default)
+}
+
+function cache_get_time( src, key, time) {
+ src = "khatus_sensor_datetime"
+ key = "epoch"
+ time = _cache[src, key]
+ _cache_atime[src, key] = time
+ return time
+}
+
+function cache_gc( src_and_key, parts, src, key, unused_for) {
+ for (src_and_key in _cache) {
+ split(src_and_key, parts, SUBSEP)
+ src = parts[1]
+ key = parts[2]
+ val = _cache[src, key]
+ unused_for = cache_get_time() - _cache_atime[src, key]
+ if (unused_for > GC_Interval) {
+ msg_out_info(\
+ "cache_gc",
+ sprintf(\
+ "Deleting unused data SRC=%s KEY=%s VAL=%s",
+ src, key, val\
+ ) \
+ )
+ delete _cache[src, key]
+ }
+ }
+}
+
+function cache_maybe_total_to_diff(src, key, val, key_parts) {
+ split(key, key_parts, Kfs)
+ if (_total_to_diff[src, key_parts[1]]) {
+ _prev[src, key] = _curr[src, key]
+ _curr[src, key] = val
+ return (_curr[src, key] - _prev[src, key])
+ } else {
+ return val
+ }
+}
+
+function cache_maybe_scale(src, key, val, key_parts) {
+ split(key, key_parts, Kfs)
+ if ((src SUBSEP key_parts[1]) in _scale) {
+ return val * _scale[src, key_parts[1]]
+ } else {
+ return val
+ }
+}
--- /dev/null
+BEGIN {
+ FS = Msg_fs ? Msg_fs : "|"
+ Kfs = Key_fs ? Key_fs : ":"
+}
--- /dev/null
+BEGIN {
+ OFS = Msg_fs ? Msg_fs : "|"
+ Kfs = Key_fs ? Key_fs : ":"
+}
+
+function msg_out_ok(key, val) {
+ msg_out("OK", key, val, "/dev/stdout")
+}
+
+function msg_out_info(location, msg) {
+ msg_out("INFO", location, msg, "/dev/stderr")
+}
+
+function msg_out_error(location, msg) {
+ msg_out("ERROR", location, msg, "/dev/stderr")
+}
+
+function msg_out(status, key, val, channel) {
+ print(status, key, val) > channel
+}
--- /dev/null
+function util_strip(s) {
+ sub("^ *", "", s)
+ sub(" *$", "", s)
+ return s
+}
+
+function util_round(n) {
+ return int(n + 0.5)
+}
+
+function util_ensure_numeric(n) {
+ return n + 0
+}
+
+#------------------------------------
+# Why do we need util_ensure_numeric?
+#------------------------------------
+# awk appears to be guessing the type of an inputted scalar based on usage, so
+# if we read-in a number, but did not use it in any numeric operations, but did
+# use as a string (even in just a format string!) - it will be treated as a
+# string and can lead to REALLY SURPRISING behavior in conditional statements,
+# where smaller number may compare as greater than the bigger ones, such as.
+#
+# Demo:
+#
+# $ awk 'BEGIN {x = "75"; y = "100"; sprintf("x: %d, y: %d\n", x, y); if (x > y) {print "75 > 100"} else if (x < y) {print "75 < 100"}}'
+# 75 < 100
+# $ awk 'BEGIN {x = "75"; y = "100"; sprintf("x: %s, y: %d\n", x, y); if (x > y) {print "75 > 100"} else if (x < y) {print "75 < 100"}}'
+# 75 > 100
+
+# However, once used as a number, seems to stay that way even after being
+# used as string:
+#
+# $ awk 'BEGIN {x = "75"; y = "100"; x + y; sprintf("x: %s, y: %d\n", x, y); if (x > y) {print "75 > 100"} else if (x < y) {print "75 < 100"}}'
+# 75 < 100
+#
+# $ awk 'BEGIN {x = "75"; y = "100"; x + y; sprintf("x: %s, y: %d\n", x, y); z = x y; if (x > y) {print "75 > 100"} else if (x < y) {print "75 < 100"}}'
+# 75 < 100
+#
+# $ awk 'BEGIN {x = "75"; y = "100"; x + y; z = x y; if (x > y) {print "75 > 100"} else if (x < y) {print "75 < 100"}}'
+# 75 < 100
+# $ awk 'BEGIN {x = "75"; y = "100"; z = x y; if (x > y) {print "75 > 100"} else if (x < y) {print "75 < 100"}}'
+# 75 > 100