From: Siraaj Khandkar Date: Wed, 29 Aug 2018 18:19:59 +0000 (-0400) Subject: Re-use AWK components X-Git-Url: https://git.xandkar.net/?a=commitdiff_plain;h=03c229bffd594c1facb72e0d042a88c0505c8dbc;p=khatus.git Re-use AWK components --- diff --git a/.gitignore b/.gitignore index 8fce603..f01981c 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,22 @@ 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 diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..9b1553b --- /dev/null +++ b/Makefile @@ -0,0 +1,194 @@ +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 $@ diff --git a/bin/khatus_gen_bar_make_status b/bin/khatus_gen_bar_make_status new file mode 100755 index 0000000..00e5506 --- /dev/null +++ b/bin/khatus_gen_bar_make_status @@ -0,0 +1,39 @@ +#! /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 +} diff --git a/bin/khatus_gen_make_status_bar b/bin/khatus_gen_make_status_bar deleted file mode 100755 index 50e1b03..0000000 --- a/bin/khatus_gen_make_status_bar +++ /dev/null @@ -1,39 +0,0 @@ -#! /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 -} diff --git a/bin/khatus_monitor_devices b/bin/khatus_monitor_devices deleted file mode 100755 index 915933c..0000000 --- a/bin/khatus_monitor_devices +++ /dev/null @@ -1,20 +0,0 @@ -#! /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) -} diff --git a/bin/khatus_monitor_energy b/bin/khatus_monitor_energy deleted file mode 100755 index 24a4b74..0000000 --- a/bin/khatus_monitor_energy +++ /dev/null @@ -1,95 +0,0 @@ -#! /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 diff --git a/bin/khatus_monitor_errors b/bin/khatus_monitor_errors deleted file mode 100755 index 5f3f3b1..0000000 --- a/bin/khatus_monitor_errors +++ /dev/null @@ -1,25 +0,0 @@ -#! /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) -} diff --git a/bin/khatus_parse_fan_file b/bin/khatus_parse_fan_file deleted file mode 100755 index 120e150..0000000 --- a/bin/khatus_parse_fan_file +++ /dev/null @@ -1,13 +0,0 @@ -#! /usr/bin/awk -f - -BEGIN { - OFS = msg_fs ? msg_fs : "|" - Kfs = key_fs ? key_fs : ":" -} - -{ - key = $1 - sub(":$", "", key) - val = $2 - print(key, val) -} diff --git a/bin/khatus_parse_free b/bin/khatus_parse_free deleted file mode 100755 index 452f44d..0000000 --- a/bin/khatus_parse_free +++ /dev/null @@ -1,11 +0,0 @@ -#! /usr/bin/awk -f - -BEGIN { - OFS = msg_fs ? msg_fs : "|" - Kfs = key_fs ? key_fs : ":" -} - -$1 == "Mem:" { - print("total", $2) - print("used" , $3) -} diff --git a/bin/khatus_parse_sys_block_stat b/bin/khatus_parse_sys_block_stat deleted file mode 100755 index 923e3ee..0000000 --- a/bin/khatus_parse_sys_block_stat +++ /dev/null @@ -1,11 +0,0 @@ -#! /usr/bin/awk -f - -BEGIN { - OFS = msg_fs ? msg_fs : "|" - Kfs = key_fs ? key_fs : ":" -} - -{ - print("sectors_read" , $3) - print("sectors_written", $7) -} diff --git a/sanity_check b/sanity_check index b9022a1..ed7f574 100755 --- a/sanity_check +++ b/sanity_check @@ -9,7 +9,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' \ ) \ ) \ diff --git a/bin/khatus_actuate_alert_to_notify_send b/src/awk/exe/actuate_alert_to_notify_send.awk similarity index 54% rename from bin/khatus_actuate_alert_to_notify_send rename to src/awk/exe/actuate_alert_to_notify_send.awk index e383917..eae5cb5 100755 --- a/bin/khatus_actuate_alert_to_notify_send +++ b/src/awk/exe/actuate_alert_to_notify_send.awk @@ -1,31 +1,23 @@ -#! /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) @@ -33,7 +25,7 @@ $3 == "alert" { cmd = \ sprintf(\ "DISPLAY=%s notify-send -u %s %s \" %s\"", - display, urgency, subject, body \ + Display, urgency, subject, body \ ) system(cmd) next diff --git a/bin/khatus_actuate_device_add_to_automount b/src/awk/exe/actuate_device_add_to_automount.awk similarity index 78% rename from bin/khatus_actuate_device_add_to_automount rename to src/awk/exe/actuate_device_add_to_automount.awk index a1e1448..9db7e9e 100755 --- a/bin/khatus_actuate_device_add_to_automount +++ b/src/awk/exe/actuate_device_add_to_automount.awk @@ -1,10 +1,4 @@ -#! /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 : "" } @@ -46,10 +40,3 @@ function mount_device(path, cmd, line, lines, line_count, status, i, 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) -} diff --git a/bin/khatus_actuate_status_bar_to_xsetroot_name b/src/awk/exe/actuate_status_bar_to_xsetroot_name.awk similarity index 73% rename from bin/khatus_actuate_status_bar_to_xsetroot_name rename to src/awk/exe/actuate_status_bar_to_xsetroot_name.awk index f41cbd1..60966c3 100755 --- a/bin/khatus_actuate_status_bar_to_xsetroot_name +++ b/src/awk/exe/actuate_status_bar_to_xsetroot_name.awk @@ -1,11 +1,3 @@ -#! /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" { diff --git a/bin/khatus_bar b/src/awk/exe/bar.awk similarity index 52% rename from bin/khatus_bar rename to src/awk/exe/bar.awk index b8e47e6..6862ee8 100755 --- a/bin/khatus_bar +++ b/src/awk/exe/bar.awk @@ -1,5 +1,3 @@ -#! /usr/bin/awk -f - # Naming convention: # Variables: # - global, builtin : ALLCAPS @@ -9,33 +7,6 @@ # 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 # ----------------------------------------------------------------------------- @@ -45,105 +16,17 @@ $1 == "OK" { $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) @@ -158,7 +41,7 @@ function make_status_energy( state, charge, direction_of_change) { 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 @@ -166,7 +49,7 @@ function make_status_mem( total, used, percent, status) { !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 = "__" @@ -174,7 +57,7 @@ function make_status_mem( total, used, percent, 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) @@ -198,7 +81,7 @@ function make_status_procs() { 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" @@ -208,7 +91,7 @@ function make_status_cpu( l, t, f) { 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") @@ -217,7 +100,7 @@ function make_status_disk( u, w, r, src_u, src_io) { 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, \ @@ -256,19 +139,19 @@ function make_status_net( \ 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) @@ -278,8 +161,8 @@ function make_status_volume( sink, mu, vl, vr, show) { 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"] \ ) } @@ -287,18 +170,18 @@ function make_status_volume( sink, mu, vl, vr, show) { 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 = "--" @@ -310,7 +193,7 @@ function make_status_mpd( state, 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", "?") @@ -319,41 +202,13 @@ function make_status_mpd_state_known(symbol, s, song, time, percentage) { 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) -} diff --git a/src/awk/exe/monitor_devices.awk b/src/awk/exe/monitor_devices.awk new file mode 100755 index 0000000..a37a30c --- /dev/null +++ b/src/awk/exe/monitor_devices.awk @@ -0,0 +1,5 @@ +$1 == "OK" && \ +$2 == "khatus_sensor_devices" \ +{ + alert("low", "BlockDeviceEvent", $3 " " $4) +} diff --git a/src/awk/exe/monitor_energy.awk b/src/awk/exe/monitor_energy.awk new file mode 100755 index 0000000..0730ec7 --- /dev/null +++ b/src/awk/exe/monitor_energy.awk @@ -0,0 +1,48 @@ +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 + } +} diff --git a/src/awk/exe/monitor_errors.awk b/src/awk/exe/monitor_errors.awk new file mode 100755 index 0000000..a096db7 --- /dev/null +++ b/src/awk/exe/monitor_errors.awk @@ -0,0 +1,10 @@ +/^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) +} diff --git a/bin/khatus_parse_bluetoothctl_show b/src/awk/exe/parse_bluetoothctl_show.awk similarity index 88% rename from bin/khatus_parse_bluetoothctl_show rename to src/awk/exe/parse_bluetoothctl_show.awk index 0d56853..3a02897 100755 --- a/bin/khatus_parse_bluetoothctl_show +++ b/src/awk/exe/parse_bluetoothctl_show.awk @@ -1,10 +1,3 @@ -#! /usr/bin/awk -f - -BEGIN { - OFS = msg_fs ? msg_fs : "|" - Kfs = key_fs ? key_fs : ":" -} - /^Controller / { controller = $2 controllers[++ctrl_count] = controller diff --git a/bin/khatus_parse_df_pcent b/src/awk/exe/parse_df_pcent.awk similarity index 52% rename from bin/khatus_parse_df_pcent rename to src/awk/exe/parse_df_pcent.awk index 7e4a534..c0925cf 100755 --- a/bin/khatus_parse_df_pcent +++ b/src/awk/exe/parse_df_pcent.awk @@ -1,10 +1,3 @@ -#! /usr/bin/awk -f - -BEGIN { - OFS = msg_fs ? msg_fs : "|" - Kfs = key_fs ? key_fs : ":" -} - NR == 2 { percentage = $1 sub("%$", "", percentage) diff --git a/src/awk/exe/parse_fan_file.awk b/src/awk/exe/parse_fan_file.awk new file mode 100755 index 0000000..3f86e88 --- /dev/null +++ b/src/awk/exe/parse_fan_file.awk @@ -0,0 +1,6 @@ +{ + key = $1 + sub(":$", "", key) + val = $2 + print(key, val) +} diff --git a/src/awk/exe/parse_free.awk b/src/awk/exe/parse_free.awk new file mode 100755 index 0000000..3f48327 --- /dev/null +++ b/src/awk/exe/parse_free.awk @@ -0,0 +1,4 @@ +$1 == "Mem:" { + print("total", $2) + print("used" , $3) +} diff --git a/bin/khatus_parse_ip_addr b/src/awk/exe/parse_ip_addr.awk similarity index 91% rename from bin/khatus_parse_ip_addr rename to src/awk/exe/parse_ip_addr.awk index b1b2ecd..85333ee 100755 --- a/bin/khatus_parse_ip_addr +++ b/src/awk/exe/parse_ip_addr.awk @@ -1,10 +1,3 @@ -#! /usr/bin/awk -f - -BEGIN { - OFS = msg_fs ? msg_fs : "|" - Kfs = key_fs ? key_fs : ":" -} - /^[0-9]+:/ { sub(":$", "", $1) sub(":$", "", $2) diff --git a/bin/khatus_parse_iwconfig b/src/awk/exe/parse_iwconfig.awk similarity index 92% rename from bin/khatus_parse_iwconfig rename to src/awk/exe/parse_iwconfig.awk index a33b50f..95eedd1 100755 --- a/bin/khatus_parse_iwconfig +++ b/src/awk/exe/parse_iwconfig.awk @@ -1,5 +1,3 @@ -#! /usr/bin/awk -f -# # Example iwconfig output: # ----------------------- # $ iwconfig wlp3s0 @@ -15,11 +13,6 @@ # # 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, ":") diff --git a/bin/khatus_parse_loadavg_file b/src/awk/exe/parse_loadavg_file.awk similarity index 77% rename from bin/khatus_parse_loadavg_file rename to src/awk/exe/parse_loadavg_file.awk index f7665fa..22826ca 100755 --- a/bin/khatus_parse_loadavg_file +++ b/src/awk/exe/parse_loadavg_file.awk @@ -1,10 +1,3 @@ -#! /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, "/") diff --git a/bin/khatus_parse_metar_d_output b/src/awk/exe/parse_metar_d_output.awk similarity index 78% rename from bin/khatus_parse_metar_d_output rename to src/awk/exe/parse_metar_d_output.awk index 1dd2778..fa354da 100755 --- a/bin/khatus_parse_metar_d_output +++ b/src/awk/exe/parse_metar_d_output.awk @@ -1,13 +1,6 @@ -#! /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 @@ -15,15 +8,15 @@ BEGIN { /[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 } @@ -45,9 +38,3 @@ END { } } } - -function strip(s) { - sub("^ *", "", s) - sub(" *$", "", s) - return s -} diff --git a/bin/khatus_parse_mpd_status_currentsong b/src/awk/exe/parse_mpd_status_currentsong.awk similarity index 95% rename from bin/khatus_parse_mpd_status_currentsong rename to src/awk/exe/parse_mpd_status_currentsong.awk index c045c0f..c29f5fa 100755 --- a/bin/khatus_parse_mpd_status_currentsong +++ b/src/awk/exe/parse_mpd_status_currentsong.awk @@ -1,10 +1,3 @@ -#! /usr/bin/awk -f - -BEGIN { - OFS = msg_fs ? msg_fs : "|" - Kfs = key_fs ? key_fs : ":" -} - # Msg separator /^OK/ {msg_count++; next} diff --git a/bin/khatus_parse_pactl_list_sinks b/src/awk/exe/parse_pactl_list_sinks.awk similarity index 90% rename from bin/khatus_parse_pactl_list_sinks rename to src/awk/exe/parse_pactl_list_sinks.awk index 7ed10e6..6a2a4a1 100755 --- a/bin/khatus_parse_pactl_list_sinks +++ b/src/awk/exe/parse_pactl_list_sinks.awk @@ -1,10 +1,3 @@ -#! /usr/bin/awk -f - -BEGIN { - OFS = msg_fs ? msg_fs : "|" - Kfs = key_fs ? key_fs : ":" -} - /^Sink \#[0-9]+$/ { sub("^#", "", $2) sink = $2 diff --git a/bin/khatus_parse_ps b/src/awk/exe/parse_ps.awk similarity index 80% rename from bin/khatus_parse_ps rename to src/awk/exe/parse_ps.awk index a0f41c5..518b4f3 100755 --- a/bin/khatus_parse_ps +++ b/src/awk/exe/parse_ps.awk @@ -1,10 +1,3 @@ -#! /usr/bin/awk -f - -BEGIN { - OFS = "|" - Kfs = ":" -} - { pid = $1 state = $2 diff --git a/src/awk/exe/parse_sys_block_stat.awk b/src/awk/exe/parse_sys_block_stat.awk new file mode 100755 index 0000000..522dffb --- /dev/null +++ b/src/awk/exe/parse_sys_block_stat.awk @@ -0,0 +1,4 @@ +{ + print("sectors_read" , $3) + print("sectors_written", $7) +} diff --git a/bin/khatus_parse_udevadm_monitor_block b/src/awk/exe/parse_udevadm_monitor_block.awk similarity index 91% rename from bin/khatus_parse_udevadm_monitor_block rename to src/awk/exe/parse_udevadm_monitor_block.awk index 75c00c3..6e6326e 100755 --- a/bin/khatus_parse_udevadm_monitor_block +++ b/src/awk/exe/parse_udevadm_monitor_block.awk @@ -1,9 +1,4 @@ -#! /usr/bin/awk -f - BEGIN { - OFS = msg_fs ? msg_fs : "|" - Kfs = key_fs ? key_fs : ":" - Re_Begin = "^UDEV + \[ *[0-9]+\.[0-9]+\] +" } diff --git a/bin/khatus_parse_upower b/src/awk/exe/parse_upower.awk similarity index 91% rename from bin/khatus_parse_upower rename to src/awk/exe/parse_upower.awk index af73e19..07af1cb 100755 --- a/bin/khatus_parse_upower +++ b/src/awk/exe/parse_upower.awk @@ -1,10 +1,3 @@ -#! /usr/bin/awk -f - -BEGIN { - OFS = msg_fs ? msg_fs : "|" - Kfs = key_fs ? key_fs : ":" -} - # When parsing 'upower --dump' /^Device:[ \t]+/ { device["path"] = $2 diff --git a/src/awk/lib/alert.awk b/src/awk/lib/alert.awk new file mode 100755 index 0000000..c043ea8 --- /dev/null +++ b/src/awk/lib/alert.awk @@ -0,0 +1,6 @@ +function alert(priority, subject, body) { + # priority : "low" | "med" | "hi" + # subject : string without spaces + # body : anything + print("OK", "alert", priority, subject, body) +} diff --git a/src/awk/lib/cache.awk b/src/awk/lib/cache.awk new file mode 100755 index 0000000..fbdd122 --- /dev/null +++ b/src/awk/lib/cache.awk @@ -0,0 +1,117 @@ +# 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 + } +} diff --git a/src/awk/lib/msg_in.awk b/src/awk/lib/msg_in.awk new file mode 100755 index 0000000..d1f62d6 --- /dev/null +++ b/src/awk/lib/msg_in.awk @@ -0,0 +1,4 @@ +BEGIN { + FS = Msg_fs ? Msg_fs : "|" + Kfs = Key_fs ? Key_fs : ":" +} diff --git a/src/awk/lib/msg_out.awk b/src/awk/lib/msg_out.awk new file mode 100755 index 0000000..9207fd0 --- /dev/null +++ b/src/awk/lib/msg_out.awk @@ -0,0 +1,20 @@ +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 +} diff --git a/src/awk/lib/util.awk b/src/awk/lib/util.awk new file mode 100755 index 0000000..b7a92e6 --- /dev/null +++ b/src/awk/lib/util.awk @@ -0,0 +1,43 @@ +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