#! /bin/bash
+MSG_FS='|'
+
set -e
-consume() {
- pipe="$1"
- debug="$2"
- bin="$3"
- prefixes_of_net_interfaces_to_show="$4"
- tail -f "$pipe" \
- | stdbuf -o L "$bin"/khatus_controller \
- -v opt_debug="$debug" \
- -v opt_mpd_song_max_chars=10 \
- -v opt_prefixes_of_net_interfaces_to_show="$prefixes_of_net_interfaces_to_show"
+executable_name_of_cmd() {
+ basename "$(echo $1 | awk '{print $1; exit}')"
}
run_producer() {
pipe="$1"
bin="$2"
cmd="$3"
- msg_head="$4"
+ executable_name="$4"
perf_log="$5"
if [ ! "$perf_log" = '' ]
2> >(
while read line
do
- echo "ERROR ${msg_head} $line" > "$pipe"
+ echo "ERROR${MSG_FS}${executable_name}${MSG_FS}$line" > "$pipe"
done \
) \
| while read line
do
- echo "OK ${msg_head} $line" > "$pipe"
+ echo "OK${MSG_FS}${executable_name}${MSG_FS}$line" > "$pipe"
done
cmd_exit_code=${PIPESTATUS[0]}
if [ "$cmd_exit_code" -ne 0 ]
then
- echo "ERROR ${msg_head} NON_ZERO_EXIT_CODE $cmd_exit_code" > "$pipe"
+ echo
+ "ERROR${MSG_FS}${executable_name}${MSG_FS}NON_ZERO_EXIT_CODE${MSG_FS}$cmd_exit_code" \
+ > "$pipe"
fi
}
fork_watcher() {
- run_producer "$@" &
+ pipe="$1"
+ bin="$2"
+ cmd="$3"
+ executable_name=$(executable_name_of_cmd "$cmd")
+ run_producer "$pipe" "$bin" "$cmd" "$executable_name" &
}
fork_poller() {
interval="$1"
perf_log_dir="$2"
shift 2
+ pipe="$1"
+ bin="$2"
+ cmd="$3"
+
+ executable_name=$(basename "$(echo $cmd | awk '{print $1; exit}')")
if [ ! "$perf_log_dir" = '' ]
then
cmd="$3"
- perf_log_file=$(basename "$(echo $cmd | awk '{print $1; exit}')").log
+ perf_log_file=${executable_name}.log
mkdir -p "$perf_log_dir"
perf_log_path="$perf_log_dir/$perf_log_file"
fi
while :
do
- run_producer "$@" "$perf_log_path"
+ run_producer "$pipe" "$bin" "$cmd" "$executable_name" "$perf_log_path"
sleep "$interval"
done &
}
["--file_pipe"]=$(mktemp)
["--weather_station_id"]='KJFK'
["--screen_brightness_device_name"]='acpi_video0'
- ["--prefixes_of_net_interfaces_to_show"]='w' # comma-separated
+ ["--net_interfaces_to_show"]='' # comma-separated
["--wifi_interface"]=''
["--disk_space_device"]='/'
["--disk_io_device"]='sda'
["--thermal_zone"]=0
["--fan_path"]='/proc/acpi/ibm/fan'
+ ["--pulseaudio_sink"]='0'
["--interval_inp_datetime"]=1
["--interval_inp_brightness"]=1
["--interval_inp_weather"]=$(( 30 * 60)) # 30 minutes
- ["--interval_inp_mpd_state"]=1
- ["--interval_inp_mpd_song"]=1
+ ["--interval_inp_mpd"]=1
["--interval_inp_volume"]=1
- ["--interval_inp_bluetooth"]=5
- ["--interval_inp_net_wifi"]=5
+ ["--interval_inp_bluetooth"]=1
+ ["--interval_inp_net_wifi"]=1
["--interval_inp_net_io"]=1
- ["--interval_inp_disk_space"]=5
+ ["--interval_inp_disk_space"]=1
["--interval_inp_disk_io"]=1
["--interval_inp_loadavg"]=1
["--interval_inp_temp"]=1
cmd_sens_screen_brightness+=" $screen_brightness_device_path"
cmd_sens_weather="khatus_sensor_weather $bin ${opts['--weather_station_id']}"
- cmd_sens_disk_space="khatus_sensor_disk_space ${opts['--disk_space_device']}"
- cmd_sens_disk_io="khatus_sensor_disk_io ${opts['--disk_io_device']}"
+ cmd_sens_disk_space="khatus_sensor_disk_space $bin ${opts['--disk_space_device']}"
+ cmd_sens_disk_io="khatus_sensor_disk_io $bin ${opts['--disk_io_device']}"
cmd_sens_temperature="khatus_sensor_temperature ${opts['--thermal_zone']}"
- cmd_sens_fan="khatus_sensor_fan ${opts['--fan_path']}"
+ cmd_sens_fan="khatus_sensor_fan $bin ${opts['--fan_path']}"
cmd_sens_bluetooth="khatus_sensor_bluetooth_power $bin"
- cmd_sens_mpd_state="khatus_sensor_mpd_state $bin"
+ cmd_sens_mpd="khatus_sensor_mpd $bin"
cmd_sens_net_addr_io="khatus_sensor_net_addr_io $bin"
cmd_sens_volume="khatus_sensor_volume $bin"
cmd_sens_wifi="khatus_sensor_net_wifi_status $bin ${opts['--wifi_interface']}"
+ cmd_sens_loadavg="khatus_sensor_loadavg $bin"
+ cmd_sens_memory="khatus_sensor_memory $bin"
+
+ fork_watcher "$pipe" "$bin" "khatus_sensor_energy $bin"
+ fork_poller "${opts['--interval_inp_datetime']}" "$perf" "$pipe" "$bin" khatus_sensor_datetime
+ fork_poller "${opts['--interval_inp_brightness']}" "$perf" "$pipe" "$bin" "$cmd_sens_screen_brightness"
+ fork_poller "${opts['--interval_inp_weather']}" "$perf" "$pipe" "$bin" "$cmd_sens_weather"
+ fork_poller "${opts['--interval_inp_mpd']}" "$perf" "$pipe" "$bin" "$cmd_sens_mpd"
+ fork_poller "${opts['--interval_inp_volume']}" "$perf" "$pipe" "$bin" "$cmd_sens_volume"
+ fork_poller "${opts['--interval_inp_bluetooth']}" "$perf" "$pipe" "$bin" "$cmd_sens_bluetooth"
+ fork_poller "${opts['--interval_inp_net_wifi']}" "$perf" "$pipe" "$bin" "$cmd_sens_wifi"
+ fork_poller "${opts['--interval_inp_net_io']}" "$perf" "$pipe" "$bin" "$cmd_sens_net_addr_io"
+ fork_poller "${opts['--interval_inp_disk_space']}" "$perf" "$pipe" "$bin" "$cmd_sens_disk_space"
+ fork_poller "${opts['--interval_inp_disk_io']}" "$perf" "$pipe" "$bin" "$cmd_sens_disk_io"
+ fork_poller "${opts['--interval_inp_loadavg']}" "$perf" "$pipe" "$bin" "$cmd_sens_loadavg"
+ fork_poller "${opts['--interval_inp_temp']}" "$perf" "$pipe" "$bin" "$cmd_sens_temperature"
+ fork_poller "${opts['--interval_inp_fan']}" "$perf" "$pipe" "$bin" "$cmd_sens_fan"
+ fork_poller "${opts['--interval_inp_mem']}" "$perf" "$pipe" "$bin" "$cmd_sens_memory"
+
+ stdbuf -o L tail -f "$pipe" \
+ | stdbuf -o L "$bin"/khatus_transform_total_to_diff \
+ -F "$MSG_FS" \
+ -v status='OK' \
+ -v src='khatus_sensor_net_addr_io' \
+ -v key_prefix='bytes_read' \
+ | stdbuf -o L "$bin"/khatus_transform_total_to_diff \
+ -F "$MSG_FS" \
+ -v status='OK' \
+ -v src='khatus_sensor_net_addr_io' \
+ -v key_prefix='bytes_written' \
+ | stdbuf -o L "$bin"/khatus_transform_total_to_diff \
+ -F "$MSG_FS" \
+ -v status='OK' \
+ -v src='khatus_sensor_disk_io' \
+ -v key_prefix='sectors_read' \
+ | stdbuf -o L "$bin"/khatus_transform_total_to_diff \
+ -F "$MSG_FS" \
+ -v status='OK' \
+ -v src='khatus_sensor_disk_io' \
+ -v key_prefix='sectors_written' \
+ | stdbuf -o L "$bin"/khatus_bar \
+ -F "$MSG_FS" \
+ -v opt_debug=""${opts['--debug']}"" \
+ -v opt_mpd_song_max_chars=10 \
+ -v opt_net_interfaces_to_show="${opts['--net_interfaces_to_show']}" \
+ -v opt_pulseaudio_sink="${opts['--pulseaudio_sink']}" \
+ | stdbuf -o L tee >("$bin"/khatus_actuate_status_bar_to_xsetroot_name) \
+ | stdbuf -o L "$bin"/khatus_monitor_energy \
+ | stdbuf -o L "$bin"/khatus_monitor_errors \
+ | stdbuf -o L tee >("$bin"/khatus_actuate_alert_to_notify_send) \
+ > /dev/null
- fork_watcher "$pipe" "$bin" "khatus_sensor_energy $bin" 'in:ENERGY'
- fork_poller "${opts['--interval_inp_datetime']}" "$perf" "$pipe" "$bin" khatus_sensor_datetime 'in:DATE_TIME'
- fork_poller "${opts['--interval_inp_brightness']}" "$perf" "$pipe" "$bin" "$cmd_sens_screen_brightness" 'in:SCREEN_BRIGHTNESS'
- fork_poller "${opts['--interval_inp_weather']}" "$perf" "$pipe" "$bin" "$cmd_sens_weather" 'in:WEATHER'
- fork_poller "${opts['--interval_inp_mpd_state']}" "$perf" "$pipe" "$bin" "$cmd_sens_mpd_state" 'in:MPD_STATE'
- fork_poller "${opts['--interval_inp_mpd_song']}" "$perf" "$pipe" "$bin" khatus_sensor_mpd_song 'in:MPD_SONG'
- fork_poller "${opts['--interval_inp_volume']}" "$perf" "$pipe" "$bin" "$cmd_sens_volume" 'in:VOLUME'
- fork_poller "${opts['--interval_inp_bluetooth']}" "$perf" "$pipe" "$bin" "$cmd_sens_bluetooth" 'in:BLUETOOTH_POWER'
- fork_poller "${opts['--interval_inp_net_wifi']}" "$perf" "$pipe" "$bin" "$cmd_sens_wifi" 'in:NET_WIFI_STATUS'
- fork_poller "${opts['--interval_inp_net_io']}" "$perf" "$pipe" "$bin" "$cmd_sens_net_addr_io" 'in:NET_ADDR_IO'
- fork_poller "${opts['--interval_inp_disk_space']}" "$perf" "$pipe" "$bin" "$cmd_sens_disk_space" 'in:DISK_SPACE'
- fork_poller "${opts['--interval_inp_disk_io']}" "$perf" "$pipe" "$bin" "$cmd_sens_disk_io" 'in:DISK_IO'
- fork_poller "${opts['--interval_inp_loadavg']}" "$perf" "$pipe" "$bin" khatus_sensor_loadavg 'in:LOAD_AVG'
- fork_poller "${opts['--interval_inp_temp']}" "$perf" "$pipe" "$bin" "$cmd_sens_temperature" 'in:TEMPERATURE'
- fork_poller "${opts['--interval_inp_fan']}" "$perf" "$pipe" "$bin" "$cmd_sens_fan" 'in:FAN'
- fork_poller "${opts['--interval_inp_mem']}" "$perf" "$pipe" "$bin" khatus_sensor_memory 'in:MEMORY'
-
- consume \
- "$pipe" \
- "${opts['--debug']}" \
- "$bin" \
- "${opts['--prefixes_of_net_interfaces_to_show']}"
}
main $@
# 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 : ":"
}
-/^ALERT / {
+$1 == "OK" && \
+$3 == "alert" {
src = $2
- priority = $3
- subject = $4
- sub("^" $1 " +" $2 " +" $3 " +" $4 " +", "")
- body = $0
+ priority = $4
+ subject = $5
+
+ # 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 $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
#! /usr/bin/awk -f
-/^STATUS_BAR / {
- sub("^" $1 " +", "")
- # TODO: Move padding back to controller, now that we no-longer use readline
- system("xsetroot -name \" " $0 "\" ")
+BEGIN {
+ FS = msg_fs ? msg_fs : "|"
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
+}
+
+$1 == "OK" && \
+$2 == "khatus_bar" && \
+$3 == "status_bar" {
+ # Not just using $4 for val - because val 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)
+
+ system("xsetroot -name \"" val "\"")
next
}
--- /dev/null
+#! /usr/bin/awk -f
+
+BEGIN {
+ FS = msg_fs ? msg_fs : "|"
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
+}
+
+# -----------------------------------------------------------------------------
+# Input
+# -----------------------------------------------------------------------------
+$1 == "OK" {
+ Data_update()
+}
+
+$1 == "OK" && \
+$2 == "khatus_sensor_datetime" {
+ print_msg_ok("status_bar", make_status_bar())
+}
+
+# Let everything else through
+//
+
+# -----------------------------------------------------------------------------
+# Data
+# -----------------------------------------------------------------------------
+
+function Data_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)
+
+ Data[src, key] = val
+ time = Data_get_time()
+ M_time[src, key] = time
+
+ if (time % 3600 == 0) {
+ Data_gc()
+ }
+}
+
+function Data_get(src, key, age_max, time, age, is_expired) {
+ time = Data_get_time()
+ A_time[src, key] = time
+ age = time - M_time[src, key]
+ is_expired = age_max && age > age_max
+ return is_expired ? "" : Data[src, key]
+}
+
+function Data_get_time( src, key, time) {
+ src = "khatus_sensor_datetime"
+ key = "epoch"
+ time = Data[src, key]
+ A_time[src, key] = time
+ return time
+}
+
+function Data_gc( src_and_key, unused_for) {
+ for (src_and_key in Data) {
+ unused_for = Data_get_time() - A_time[src_and_key]
+ if (unused_for > 3600) {
+ print_msg_error(\
+ "Data_gc", "Deleting unused src_and_key: " src_and_key \
+ )
+ delete Data[src_and_key]
+ }
+ }
+}
+
+# -----------------------------------------------------------------------------
+# Status bar
+# -----------------------------------------------------------------------------
+
+function make_status_bar( position, bar, sep, i, j) {
+ position[++i] = ""
+ position[++i] = make_status_energy()
+ position[++i] = make_status_mem()
+ position[++i] = make_status_cpu()
+ position[++i] = make_status_disk()
+ position[++i] = make_status_net()
+ position[++i] = make_status_bluetooth()
+ position[++i] = make_status_screen_brightness()
+ position[++i] = make_status_volume()
+ position[++i] = make_status_mpd()
+ position[++i] = make_status_weather()
+ position[++i] = make_status_datetime()
+ position[++i] = ""
+ bar = ""
+ sep = ""
+ for (j = 1; j <= i; j++) {
+ bar = bar sep position[j]
+ sep = " "
+ }
+ return bar
+}
+
+function make_status_energy( state, charge, direction_of_change) {
+ state = Data_get("khatus_sensor_energy", "battery_state")
+ charge = Data_get("khatus_sensor_energy", "battery_percentage")
+
+ if (state == "discharging") {
+ direction_of_change = "<"
+ } else if (state == "charging") {
+ direction_of_change = ">"
+ } else {
+ direction_of_change = "="
+ }
+
+ return sprintf("E%s%d%%", direction_of_change, charge)
+}
+
+function make_status_mem( total, used, percent, status) {
+ total = Data_get("khatus_sensor_memory", "total", 2)
+ used = Data_get("khatus_sensor_memory", "used" , 2)
+ # To avoid division by zero when data is missing
+ if (total && used) {
+ percent = round((used / total) * 100)
+ status = sprintf("%d%%", percent)
+ } else {
+ status = "__"
+ }
+ return sprintf("M=%s", status)
+}
+
+function make_status_cpu( load, temp, fan) {
+ load = Data_get("khatus_sensor_loadavg" , "load_avg_1min", 2)
+ temp = Data_get("khatus_sensor_temperature", "temp_c" , 2)
+ fan = Data_get("khatus_sensor_fan" , "speed" , 2)
+
+ load = load ? sprintf("%4.2f", load) : "--"
+ temp = temp ? sprintf("%d" , temp) : "--"
+ fan = fan ? sprintf("%4d" , fan) : "--"
+
+ return sprintf("C=[%s %s°C %srpm]", load, temp, fan)
+}
+
+function make_status_disk( bytes_per_sector, bytes_per_mb, w, r, u) {
+ bytes_per_sector = 512
+ bytes_per_mb = 1024 * 1024
+
+ w = Data_get("khatus_sensor_disk_io" , "sectors_written" , 2)
+ r = Data_get("khatus_sensor_disk_io" , "sectors_read" , 2)
+ u = Data_get("khatus_sensor_disk_space", "disk_usage_percentage", 10)
+
+ w = w ? sprintf("%0.3f", (w * bytes_per_sector) / bytes_per_mb) : "--"
+ r = r ? sprintf("%0.3f", (r * bytes_per_sector) / bytes_per_mb) : "--"
+ u = u ? u : "--"
+
+ return sprintf("D=[%s%% %s▲ %s▼]", u, w, r)
+}
+
+function make_status_net( \
+ number_of_net_interfaces_to_show, \
+ net_interfaces_to_show, \
+ sensor_io, \
+ sensor_wi, \
+ out, \
+ sep, \
+ i, \
+ interface, \
+ label, \
+ addr, \
+ w, \
+ r, \
+ bytes_per_mb, \
+ io_stat, \
+ wifi \
+) {
+ number_of_net_interfaces_to_show = \
+ split(opt_net_interfaces_to_show, net_interfaces_to_show, ",")
+
+ sensor_io = "khatus_sensor_net_addr_io"
+ sensor_wi = "khatus_sensor_net_wifi_status"
+
+ out = ""
+ sep = ""
+ for (i = number_of_net_interfaces_to_show; i > 0; i--) {
+ interface = net_interfaces_to_show[i]
+ label = substr(interface, 1, 1)
+
+ addr = Data_get(sensor_io, "addr" Kfs interface, 2)
+ w = Data_get(sensor_io, "bytes_written" Kfs interface, 2)
+ r = Data_get(sensor_io, "bytes_read" Kfs interface, 2)
+
+ if (addr) {
+ bytes_per_mb = 1024 * 1024
+ w = w ? sprintf("%0.3f", w / bytes_per_mb) : "--"
+ r = r ? sprintf("%0.3f", r / bytes_per_mb) : "--"
+ io_stat = sprintf("%s▲ %s▼", w, r)
+ } else {
+ io_stat = "--"
+ }
+
+ if (interface ~ "^w") {
+ wifi = Data_get(sensor_wi, "status" Kfs interface, 5)
+ label = label ":" (wifi ? wifi : "--")
+ }
+
+ out = out sep label ":" io_stat
+ sep = " "
+ }
+
+ return sprintf("N[%s]", out)
+}
+
+function make_status_bluetooth( status) {
+ status = Data_get("khatus_sensor_bluetooth_power", "power_status", 5)
+ return sprintf("B=%s", status ? status : "--")
+}
+
+function make_status_screen_brightness( percentage) {
+ percentage = Data_get("khatus_sensor_screen_brightness", "percentage", 5)
+ percentage = percentage ? sprintf("%d", percentage) : "--"
+ return sprintf("*%s%%", percentage)
+}
+
+function make_status_volume( sink, mute, vol_l, vol_r, status) {
+ sink = opt_pulseaudio_sink
+ mute = Data_get("khatus_sensor_volume", "mute" Kfs sink, 2)
+ vol_l = Data_get("khatus_sensor_volume", "vol_left" Kfs sink, 2)
+ vol_r = Data_get("khatus_sensor_volume", "vol_right" Kfs sink, 2)
+
+ if (mute && vol_l && vol_r) {
+ if (mute == "yes") {status = "X"}
+ else if (mute == "no") {status = sprintf("%s %s", vol_l, vol_r)}
+ else {
+ print_msg_error(\
+ "make_status_volume", \
+ "Unexpected value for 'mute' field: " mute \
+ )
+ }
+ } else {
+ status = "--"
+ }
+
+ return sprintf("(%s)", status)
+}
+
+function make_status_mpd( state, status) {
+ if (state = Data_get("khatus_sensor_mpd", "state", 2)) {
+ if (state == "play") {
+ status = make_status_mpd_state_known("▶")
+ } else if (state == "pause") {
+ status = make_status_mpd_state_known("❚❚")
+ } else if (state == "stop") {
+ status = make_status_mpd_state_known("⬛")
+ } else {
+ print_msg_error(\
+ "make_status_mpd", \
+ "Unexpected value for 'state' field: " state \
+ )
+ status = "--"
+ }
+ } else {
+ status = "--"
+ }
+
+ return sprintf("[%s]", status)
+}
+
+function make_status_mpd_state_known(symbol, s, song, time, percentage) {
+ s = "khatus_sensor_mpd"
+ song = Data_get(s, "song" , 2)
+ time = Data_get(s, "play_time_minimal_units", 2)
+ percent = Data_get(s, "play_time_percentage" , 2)
+ song = substr(song, 1, opt_mpd_song_max_chars)
+ return sprintf("%s %s %s %s", symbol, time, percent, song)
+}
+
+function make_status_weather( hour, t_f) {
+ hour = 60 * 60
+ t_f = Data_get("khatus_sensor_weather", "temperature_f", 3 * hour)
+ t_f = t_f ? sprintf("%d", t_f) : "--"
+ return sprintf("%s°F", t_f)
+}
+
+function make_status_datetime( dt) {
+ dt = Data_get("khatus_sensor_datetime", "datetime", 2)
+ return dt ? dt : "--"
+}
+
+# -----------------------------------------------------------------------------
+# Output
+# -----------------------------------------------------------------------------
+
+function print_msg_ok(key, val) {
+ print_msg("OK", key, val, "/dev/stdout")
+}
+
+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
-#! /usr/bin/awk -f
-
-/^OK/ { debug("OK line", $0) }
-
-/^ERROR in:MPD.*NON_ZERO_EXIT_CODE/ {
- for (mpd_key in db) {
- if (mpd_key ~ "^mpd_") {
- delete db[mpd_key]
- }
- }
- next
-}
-
-/^ERROR/ {
- debug("ERROR line", $0)
- shift()
- msg_head = $1
- shift()
- msg_body = $0
- alert_trigger_hi(msg_head, "KhatusSensorError", msg_body)
-}
-
-/^OK in:ENERGY battery/\
-{
- debug("ENERGY battery", $0)
- sub("%$", "", $5)
- db["energy_state_prev"] = db["energy_state_curr"]
- db["energy_state_curr"] = $4
- db["energy_percentage"] = ensure_numeric($5)
- alert_check_energy_battery()
-}
-
-/^OK in:ENERGY line_power/\
-{
- debug("ENERGY line_power", $0)
- db["energy_line_power_prev"] = db["energy_line_power_curr"]
- db["energy_line_power_curr"] = $4
- alert_check_energy_line_power()
-}
-
-/^OK in:MEMORY/\
-{
- shift()
- shift()
- db["memory_total"] = $1
- db["memory_used"] = $2
-}
-
-/^OK in:FAN +status:/\
-{
- shift()
- shift()
- db["fan_status"] = $2
-}
-
-/^OK in:FAN +speed:/\
-{
- shift()
- shift()
- db["fan_speed"] = $2
-}
-
-/^OK in:FAN +level:/\
-{
- shift()
- shift()
- db["fan_level"] = $2
-}
-
-/^OK in:TEMPERATURE/\
-{
- shift()
- shift()
- db["temperature"] = $1
-}
-
-/^OK in:LOAD_AVG/\
-{
- shift()
- shift()
- set_load_avg()
-}
-
-/^OK in:DISK_IO/\
-{
- shift()
- shift()
- set_disk_io()
-}
-
-/^OK in:DISK_SPACE/\
-{
- shift()
- shift()
- db["disk_space_used"] = $0
-}
-
-/^OK in:NET_ADDR_IO/\
-{
- shift()
- shift()
- set_net_addr_io()
-}
-
-/^OK in:NET_WIFI_STATUS/\
-{
- shift()
- shift()
- set_net_wifi_status()
-}
-
-/^OK in:BLUETOOTH_POWER/\
-{
- shift()
- shift()
- db["bluetooth_power"] = $0
-}
-
-/^OK in:SCREEN_BRIGHTNESS/\
-{
- shift()
- shift()
- set_screen_brightness()
-}
-
-/^OK in:VOLUME/\
-{
- shift()
- set_volume()
-}
-
-/^OK in:MPD_SONG OK +MPD/ { delete db_mpd_song; next }
-/^OK in:MPD_SONG OK$/ { set_mpd_playing() ; next }
-/^OK in:MPD_SONG / { set_mpd_song() ; next }
-
-/^OK in:MPD_STATE /\
-{
- shift()
- shift()
- db["mpd_status_state"] = $1
- db["mpd_status_time"] = $2
- db["mpd_status_percent"] = $3
-}
-
-/^OK in:WEATHER temperature/\
-{
- shift()
- shift()
- shift()
- db["weather_temperature"] = $0
-}
-
-/^OK in:WEATHER phenomenon/\
-{
- shift()
- shift()
- shift()
- alert_trigger_low("weather_phenomenon", "WeatherPhenomenon", $0)
-}
-
-/^OK in:DATE_TIME/\
-{
- shift()
- shift()
- db["datetime"] = $0
- output_msg_status_bar(make_status_bar())
-}
-
-function set_volume( mute, left, right) {
- # 0 RUNNING no 75% 75%
- #msg_head = $1
- #sink = $2
- #state = $3
- mute = $4
- left = $5
- right = $6
-
- if (mute == "no") {
- db["volume"] = sprintf("%s %s", left, right)
- } else if (mute == "yes") {
- db["volume"] = "X"
- } else {
- error("set_volume", "Unexpected value for 'mute' field: " mute)
- }
-}
-
-function set_mpd_song( key, val) {
- shift()
- key = $2
- shift()
- shift()
- val = $0
- db_mpd_song[key] = val
- debug("set_mpd_song", "", db_mpd_song)
-}
-
-function set_mpd_playing( \
- currently_playing, name, title, file, last, parts\
-) {
- debug("set_mpd_playing", "", db_mpd_song)
- name = db_mpd_song["Name:"]
- title = db_mpd_song["Title:"]
- file = db_mpd_song["file:"]
-
- if (name) {
- currently_playing = name
- } else if (title) {
- currently_playing = title
- } else if (file) {
- last = split(file, parts, "/")
- currently_playing = parts[last]
- } else {
- currently_playing = ""
- }
- db["mpd_playing_prev"] = db["mpd_playing_curr"]
- db["mpd_playing_curr"] = currently_playing
-
- alert_check_mpd()
-}
-
-function alert_check_mpd( curr, prev, name, body) {
- prev = db["mpd_playing_prev"]
- curr = db["mpd_playing_curr"]
- if (curr && curr != prev) {
- name = db_mpd_song["Name:"]
- if (name) {
- body = name
- } else {
- body = \
- db_mpd_song["Artist:"] \
- " - " db_mpd_song["Album:"] \
- " - " db_mpd_song["Title:"]
- }
- alert_trigger_low("alert_check_mpd", "MpdNowPlaying", body)
- }
-}
-
-# TODO: Generalize alert spec lang
-# - trigger threshold
-# - above/bellow/equal to threshold value
-# - priority
-# - snooze time (if already alerted, when to re-alert?)
-# - text: subject/body
-function alert_check_energy_battery( \
- from, dbg, state_curr, state_prev, remaining, subj, body\
-) {
- from = "alert_check_energy_battery"
-
- state_curr = db["energy_state_curr"]
- state_prev = db["energy_state_prev"]
- remaining = db["energy_percentage"]
-
- dbg["state_curr"] = state_curr
- dbg["remaining"] = remaining
- debug(from, "", dbg)
-
- if (state_curr == "discharging") {
- if (remaining < 5) {
- subj = "Energy_CRITICALLY_Low"
- body = sprintf("%d%% CHARGE NOW!!! GO GO GO!!!", remaining)
- alert_trigger_hi(from, subj, body)
- } else if (remaining < 10) {
- subj = "Energy_Very_Low"
- body = sprintf("%d%% Plug it in ASAP.", remaining)
- alert_trigger_hi(from, subj, body)
- } else if (remaining < 15) {
- subj = "Energy_Low"
- body = sprintf("%d%% Get the charger.", remaining)
- alert_trigger_hi(from, subj, body)
- } else if (remaining < 20) {
- subj = "Energy_Low"
- body = sprintf("%d%% Get the charger.", remaining)
- alert_trigger_med(from, subj, body)
- } else if (remaining < 50) {
- if (!state__alerts__energy__notified_bellow_half) {
- state__alerts__energy__notified_bellow_half = 1
- subj = "Energy_Bellow_Half"
- body = sprintf("%d%% Where is the charger?", remaining)
- alert_trigger_med(from, subj, body)
- }
- }
- } else {
- # TODO: Reconsider the competing global-state organizing-conventions
- state__alerts__energy__notified_bellow_half = 0
- }
-}
-
-function alert_check_energy_line_power( \
- from, dbg, line_power_curr, line_power_prev, subj, body \
-) {
- from = "alert_check_energy_line_power"
-
- dbg["energy_line_power_prev"] = db["energy_line_power_prev"]
- dbg["energy_line_power_curr"] = db["energy_line_power_curr"]
- debug(from, "", dbg)
-
- line_power_curr = db["energy_line_power_curr"]
- line_power_prev = db["energy_line_power_prev"]
-
- if (line_power_curr == "no" && line_power_prev != "no") {
- alert_trigger_low(from, "PowerUnplugged", "")
- }
-}
-
-function alert_trigger_low(from, subject, body) {
- alert_trigger("low", from, subject, body)
-}
-
-function alert_trigger_med(from, subject, body) {
- alert_trigger("med", from, subject, body)
-}
-
-function alert_trigger_hi(from, subject, body) {
- alert_trigger("hi", from, subject, body)
-}
-
-function alert_trigger(priority, from, subject, body, msg) {
- # priority : "low" | "med" | "hi"
- # subject : no spaces
- # body : anything
- msg = sprintf("khatus_%s %s %s %s", from, priority, subject, body)
- output_msg_alert(msg)
-}
-
-function output_msg_alert(msg) {
- # TODO: Should alerts go into a dedicated channel?
- output_msg("ALERT", msg, "/dev/stdout")
-}
-
-function output_msg_status_bar(msg) {
- output_msg("STATUS_BAR", msg, "/dev/stdout")
-}
-
-function output_msg(type, content, channel) {
- print(type, content) > channel
-}
-
-function set_load_avg( sched) {
- split($4, sched, "/")
- db["load_avg_1min"] = $1
- db["load_avg_5min"] = $2
- db["load_avg_15min"] = $3
- db["kern_sched_queue_runnable"] = sched[1]
- db["kern_sched_queue_total"] = sched[2]
- db["kern_sched_latest_pid"] = $5
-}
-
-function set_disk_io( curr_w, curr_r, prev_w, prev_r) {
- curr_w = $1
- curr_r = $2
- prev_w = db["disk_io_curr_w"]
- prev_r = db["disk_io_curr_r"]
- db["disk_io_curr_w"] = curr_w
- db["disk_io_curr_r"] = curr_r
- db["disk_io_diff_w"] = curr_w - prev_w
- db["disk_io_diff_r"] = curr_r - prev_r
-}
-
-function set_net_wifi_status( interface) {
- interface = $1
- shift()
- db["net_wifi_status", interface] = $0
-}
-
-function set_net_addr_io( \
- interface, address, io_curr_w, io_curr_r, io_prev_w, io_prev_r\
-) {
- interface = $1
- address = $2
- io_curr_w = $3
- io_curr_r = $4
- if (interface) {
- if (address && io_curr_w && io_curr_r) {
- # recalculate
- io_prev_w = net_io_curr_w[interface]
- io_prev_r = net_io_curr_r[interface]
-
- net_addr[interface] = address
- net_io_curr_w[interface] = io_curr_w
- net_io_curr_r[interface] = io_curr_r
- net_io_diff_w[interface] = io_curr_w - io_prev_w
- net_io_diff_r[interface] = io_curr_r - io_prev_r
- } else {
- # clear
- net_addr[interface] = ""
- net_io_curr_w[interface] = 0
- net_io_curr_r[interface] = 0
- net_io_diff_w[interface] = 0
- net_io_diff_r[interface] = 0
- }
- }
-}
-
-function set_screen_brightness( max, cur) {
- max = $1
- cur = $2
- db["screen_brightness"] = (cur / max) * 100
-}
-
-# TODO: Revise overuse of shift() where it is not really needed
-function shift() {
- sub("^" $1 " +", "")
-}
-
-function make_status_bar( position, bar, sep, i, j) {
- position[++i] = make_status_energy()
- position[++i] = make_status_mem()
- position[++i] = make_status_cpu()
- position[++i] = make_status_disk()
- position[++i] = make_status_net()
- position[++i] = sprintf("B=%s", db["bluetooth_power"])
- position[++i] = sprintf("*%d%%", db["screen_brightness"])
- position[++i] = sprintf("(%s)", db["volume"])
- position[++i] = make_status_mpd()
- position[++i] = db["weather_temperature"]
- position[++i] = db["datetime"]
- bar = ""
- sep = ""
- for (j = 1; j <= i; j++) {
- bar = bar sep position[j]
- sep = " "
- }
- return bar
-}
-
-function make_status_energy( state, direction_of_change) {
- state = db["energy_state_curr"]
- if (state == "discharging") {
- direction_of_change = "<"
- } else if (state == "charging") {
- direction_of_change = ">"
- } else {
- direction_of_change = "="
- };
- return sprintf("E%s%d%%", direction_of_change, db["energy_percentage"])
-}
-
-function make_status_mem( total, used, percent, status) {
- total = db["memory_total"]
- used = db["memory_used"]
- # To avoid division by zero when data is missing
- if (total && used) {
- percent = round((used / total) * 100)
- status = sprintf("%d%%", percent)
- } else {
- status = "__"
- }
- return sprintf("M=%s", status)
-}
-
-function make_status_cpu( load, temp, fan) {
- load = db["load_avg_1min"]
- temp = db["temperature"] / 1000
- fan = db["fan_speed"]
- return sprintf("C=[%4.2f %d°C %4drpm]", load, temp, fan)
-}
-
-function make_status_disk( bytes_per_sector, bytes_per_mb, w, r) {
- bytes_per_sector = 512
- bytes_per_mb = 1024 * 1024
- w = (db["disk_io_diff_w"] * bytes_per_sector) / bytes_per_mb
- r = (db["disk_io_diff_r"] * bytes_per_sector) / bytes_per_mb
- return \
- sprintf("D=[%s %0.3f▲ %0.3f▼]", db["disk_space_used"], w, r)
-}
-
-function make_status_net( \
- out,
- number_of_interfaces_to_show,
- n,
- array_of_prefixes_of_interfaces_to_show,
- prefix,
- interface,
- label,
- count_printed,
- sep,
- io_stat,
- dw, dr,
- bytes_per_unit\
-) {
- out = ""
- number_of_interfaces_to_show = \
- split(\
- opt_prefixes_of_net_interfaces_to_show,\
- array_of_prefixes_of_interfaces_to_show,\
- ","\
- )
- for (n = 1; n <= number_of_interfaces_to_show; n++) {
- prefix = array_of_prefixes_of_interfaces_to_show[n]
- for (interface in net_addr) {
- if (interface ~ ("^" prefix)) {
- label = substr(interface, 1, 1)
- if (net_addr[interface]) {
- bytes_per_mb = 1024 * 1024 # TODO: option
- dw = net_io_diff_w[interface] / bytes_per_mb
- dr = net_io_diff_r[interface] / bytes_per_mb
- io_stat = sprintf("%0.3f▲ %0.3f▼", dw, dr)
- } else {
- io_stat = "--"
- }
- if (interface ~ "^w") {
- label = label ":" db["net_wifi_status", interface]
- }
- if (++count_printed > 1) {
- sep = " "
- } else {
- sep = ""
- }
- out = out sep label ":" io_stat
- }
- }
- }
- return sprintf("N[%s]", out)
-}
-
-function make_status_mpd( state, status) {
- state = db["mpd_status_state"]
-
- if (state == "play") {
- status = make_status_mpd_state_known("▶")
- } else if (state == "pause") {
- status = make_status_mpd_state_known("❚❚")
- } else if (state == "stop") {
- status = make_status_mpd_state_known("⬛")
- } else {
- status = make_status_mpd_state_unknown("--")
- }
-
- return sprintf("[%s]", status)
-}
-
-function make_status_mpd_state_known(symbol) {
- return sprintf(\
- "%s %s %s %s",
- symbol,
- db["mpd_status_time"],
- db["mpd_status_percent"],
- substr(db["mpd_playing_curr"], 1, opt_mpd_song_max_chars)\
- )
-}
-
-function make_status_mpd_state_unknown(symbol) {
- return sprintf("%s", symbol)
-}
-
-function round(n) {
- return int(n + 0.5)
-}
-
-function debug(location, msg, values, sep, vals, key, payload) {
- if (opt_debug) {
- sep = ""
- vals = ""
- for (key in values) {
- vals = sprintf("%s%s%s: %s", vals, sep, key, values[key])
- sep = ", "
- }
- payload = \
- sprintf("LOCATION[%s] MSG[%s] DATA[%s]", location, msg, vals)
- output_msg("DEBUG", payload, "/dev/stderr")
- }
-}
-
-function error(location, msg) {
- # TODO: Reconsider classifying internal errors as alerts
- # Maybe better to keep the error class distinct and provide a
- # an optional transformation from error to alert
- alert_trigger_hi(location, "KhatusControllerError", msg)
-}
-
-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 : ":"
+
+ 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
+ printf("BATTERY_STATE prev:%s curr:%s\n", battery_state_prev, battery_state_curr)
+}
+
+$1 == "OK" && \
+$2 == "khatus_sensor_energy" && \
+$3 == "battery_percentage" {
+ battery_percentage = ensure_numeric($4)
+ printf("BATTERY_PERCENTAGE %s\n", battery_percentage)
+ 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
+ }
+}
+
+# After peeking, let everything pass through!
+//
+
+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)
+}
+
+# After peeking, let everything pass through!
+//
+
+function alert(priority, subject, body) {
+ # priority : "low" | "med" | "hi"
+ # subject : no spaces
+ # body : anything
+ print("OK", "khatus_monitor_errors", "alert", priority, subject, body)
+}
#! /usr/bin/awk -f
+BEGIN {
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
+}
+
/^Controller / {
controller = $2
controllers[++ctrl_count] = controller
} else {
show = "n/a"
}
- print(show)
+ print("power_status", show)
}
function print_error(msg) {
--- /dev/null
+#! /usr/bin/awk -f
+
+BEGIN {
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
+}
+
+NR == 2 {
+ percentage = $1
+ sub("%$", "", percentage)
+ print("disk_usage_percentage", percentage)
+}
--- /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)
+}
#! /usr/bin/awk -f
+BEGIN {
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
+}
+
/^[0-9]+:/ {
sub(":$", "", $1)
sub(":$", "", $2)
sequence = $1
interface = $2
- interfaces[sequence] = interface
+ Interfaces[sequence] = interface
}
/^ +inet [0-9]/ {
sub("/[0-9]+", "", $2)
addr = $2
- addrs[interface] = addr
+ Addrs[interface] = addr
}
/^ +RX: / {transfer_direction = "r"}
END {
for (seq=1; seq<=sequence; seq++) {
- interface = interfaces[seq]
+ interface = Interfaces[seq]
label = substr(interface, 1, 1)
- addr = addrs[interface]
+ addr = Addrs[interface]
if (addr) {
- curr_read = io[interface, "r"]
- curr_write = io[interface, "w"]
- print(interface, addr, curr_write, curr_read)
+ bytes_read = io[interface, "r"]
+ bytes_written = io[interface, "w"]
} else {
- print(interface)
+ bytes_read = ""
+ bytes_written = ""
}
+ output["addr" Kfs interface] = addr
+ output["bytes_read" Kfs interface] = bytes_read
+ output["bytes_written" Kfs interface] = bytes_written
+ }
+ for (key in output) {
+ print(key, output[key])
}
}
#
# 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, ":")
END {
i = requested_interface
- status = link[i] ? sprintf("%s %s:%d%%", i, essid[i], link[i]) : i " --"
- print(status)
+ status = link[i] ? sprintf("%s:%d%%", essid[i], link[i]) : "--:--%"
+ print("status" Kfs i, status)
}
--- /dev/null
+#! /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, "/")
+ print("load_avg_1min" , $1)
+ print("load_avg_5min" , $2)
+ print("load_avg_15min" , $3)
+ print("kern_sched_queue_runnable" , sched[1])
+ print("kern_sched_queue_total" , sched[2])
+ print("kern_sched_latest_pid" , $5)
+}
# Qualifying the name as "_d_output" lest it be mistaken for parser of actual
# metar format.
-function strip(s) {
- sub("^ *", "", s)
- sub(" *$", "", s)
- return s
+BEGIN {
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
}
/METAR pattern not found in NOAA data/ {
split(temp_string, temp_parts, " +")
temp_celsius = temp_parts[1]
temp_fahrenheit = (temp_celsius * (9 / 5)) + 32
- print "temperature " temp_fahrenheit "°F"
+ print("temperature_c", temp_celsius) # °C
+ print("temperature_f", temp_fahrenheit) # °F
for (i=first["Phenomena"]; i<=last["Phenomena"]; i++) {
phenomenon = values[i]
if (phenomenon) {
- print "phenomenon " phenomenon
+ print("phenomenon" Kfs i, phenomenon)
}
}
}
}
+
+function strip(s) {
+ sub("^ *", "", s)
+ sub(" *$", "", s)
+ return s
+}
+++ /dev/null
-#! /usr/bin/awk -f
-
-# Msg BEGINs
-/^OK MPD / { delete status; next}
-
-# Msg ENDs
-/^OK$/ {
- split(status["time"], time, ":")
- seconds_current = time[1]
- seconds_total = time[2]
-
- hours = int(seconds_current / 60 / 60);
- secs_beyond_hours = seconds_current - (hours * 60 * 60);
- mins = int(secs_beyond_hours / 60);
- secs = secs_beyond_hours - (mins * 60);
-
- if (hours > 0) {
- current_time = sprintf("%d:%.2d:%.2d", hours, mins, secs)
- } else {
- current_time = sprintf("%.2d:%.2d", mins, secs)
- }
-
- if (seconds_total > 0) {
- time_percentage = (seconds_current / seconds_total) * 100
- current_percentage = sprintf("%d%%", time_percentage)
- } else {
- current_percentage = "~"
- }
-
- printf("%s %s %s\n", status["state"], current_time, current_percentage)
- next
-}
-
-# Msg content
-/^[a-z]+: / {
- sub(":$", "", $1)
- status[$1] = $2
- next
-}
--- /dev/null
+#! /usr/bin/awk -f
+
+BEGIN {
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
+}
+
+# Msg separator
+/^OK/ {msg_count++; next}
+
+# Msg content
+/^[a-zA-Z-]+: / {
+ key = $1
+ val = $0
+ sub(".*" key " *", "", val)
+ sub(":$", "", key)
+ key = tolower(key)
+ # Note that we expect a particular order of response messages (also
+ # reflected in the name of this script file): "status" THEN "currentsong"
+ if (msg_count == 1) {status[key] = val}
+ else if (msg_count == 2) {currentsong[key] = val}
+ else {
+ printf("Unexpected msg_count in mpd response: %d\n", msg_count) \
+ > "/dev/stderr"
+ exit 1
+ }
+ next
+}
+
+END {
+ name = currentsong["name"]
+ title = currentsong["title"]
+ file = currentsong["file"]
+
+ if (name) {
+ song = name
+ } else if (title) {
+ song = title
+ } else if (file) {
+ last = split(file, parts, "/")
+ song = parts[last]
+ } else {
+ song = "?"
+ }
+
+ format_time(status["time"], time)
+ output["play_time_minimal_units"] = time["minimal_units"]
+ output["play_time_percentage"] = time["percentage"]
+ output["state"] = status["state"]
+ output["song"] = song
+ for (key in output) {
+ print(key, output[key])
+ }
+}
+
+function format_time(time_str, time_arr, \
+ \
+ time_str_parts,
+ seconds_current,
+ seconds_total,
+ hours,
+ secs_beyond_hours,
+ mins,
+ secs,
+ time_percentage \
+) {
+ split(time_str, time_str_parts, ":")
+ seconds_current = time_str_parts[1]
+ seconds_total = time_str_parts[2]
+
+ hours = int(seconds_current / 60 / 60);
+ secs_beyond_hours = seconds_current - (hours * 60 * 60);
+ mins = int(secs_beyond_hours / 60);
+ secs = secs_beyond_hours - (mins * 60);
+
+ if (hours > 0) {
+ time_arr["minimal_units"] = sprintf("%d:%.2d:%.2d", hours, mins, secs)
+ } else {
+ time_arr["minimal_units"] = sprintf("%.2d:%.2d", mins, secs)
+ }
+
+ if (seconds_total > 0) {
+ time_percentage = (seconds_current / seconds_total) * 100
+ time_arr["percentage"] = sprintf("%d%%", time_percentage)
+ } else {
+ time_arr["percentage"] = "~"
+ }
+}
#! /usr/bin/awk -f
+BEGIN {
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
+}
+
/^Sink \#[0-9]+$/ {
sub("^#", "", $2)
sink = $2
END {
for (sink in state) {
- printf(\
- "%s %s %s %s %s\n",
- sink, state[sink], mute[sink], vol_left[sink], vol_right[sink] \
- )
+ print("state" Kfs sink, state[sink])
+ print("mute" Kfs sink, mute[sink])
+ print("vol_left" Kfs sink, vol_left[sink])
+ print("vol_right" Kfs sink, vol_right[sink])
}
}
--- /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)
+}
#! /usr/bin/awk -f
+BEGIN {
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
+}
+
# When parsing 'upower --dump'
/^Device:[ \t]+/ {
device["path"] = $2
/ percentage:/ && device["is_battery"] {
device["battery_percentage"] = $2
+ sub("%$", "", device["battery_percentage"])
next
}
/^$/ && device["is_battery"] {
- printf("battery %s %s\n", device["battery_state"], device["battery_percentage"])
+ print("battery_state" , device["battery_state"])
+ print("battery_percentage", device["battery_percentage"])
}
# END battery
}
/^$/ && device["is_line_power"] {
- printf("line_power %s\n", device["line_power_online"])
+ print("line_power", device["line_power_online"])
}
# END line-power
#! /bin/sh
-date +'%a %b %d %H:%M:%S'
+set -e
+
+date +'%s %a %b %d %H:%M:%S' \
+| awk '
+ BEGIN {
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
+ }
+
+ {
+ epoch = $1
+ datetime = $0
+ sub("^" epoch " +", "", datetime)
+ print("epoch" , epoch)
+ print("datetime", datetime)
+ }
+ '
set -e
-disk_io_device="$1"
+dir_bin="$1"
+disk_io_device="$2"
-awk '
- {
- r = $3
- w = $7
- print w, r
- }
- ' \
- "/sys/block/$disk_io_device/stat"
+"$dir_bin"/khatus_parse_sys_block_stat "/sys/block/$disk_io_device/stat"
set -e
-disk_space_device="$1"
+dir_bin="$1"
+disk_space_device="$2"
-df --output=pcent "$disk_space_device" | awk 'NR == 2 {print $1}'
+df --output=pcent "$disk_space_device" | "$dir_bin"/khatus_parse_df_pcent
set -e
-fan_path="$1"
+dir_bin="$1"
+fan_path="$2"
-cat "$fan_path"
+"$dir_bin"/khatus_parse_fan_file "$fan_path"
set -e
-cat /proc/loadavg
+dir_bin="$1"
+
+"$dir_bin"/khatus_parse_loadavg_file /proc/loadavg
set -e
-free | awk '$1 == "Mem:" {print $2, $3}'
+dir_bin="$1"
+
+free | "$dir_bin"/khatus_parse_free
--- /dev/null
+#! /bin/sh
+
+set -e
+
+dir_bin="$1"
+
+echo 'status\ncurrentsong' \
+| nc 127.0.0.1 6600 \
+| "$dir_bin"/khatus_parse_mpd_status_currentsong
+++ /dev/null
-#! /bin/sh
-
-set -e
-
-echo 'currentsong' | nc 127.0.0.1 6600
+++ /dev/null
-#! /bin/sh
-
-set -e
-
-dir_bin="$1"
-
-echo 'status' \
-| nc 127.0.0.1 6600 \
-| "$dir_bin"/khatus_parse_mpd_status
screen_brightness_device_path="$1"
-echo "\
- $(cat $screen_brightness_device_path/max_brightness) \
- $(cat $screen_brightness_device_path/brightness)\
-"
+awk '
+ BEGIN {
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
+ }
+
+ FILENAME ~ "/max_brightness$" {max = $1; next}
+ FILENAME ~ "/brightness$" {cur = $1; next}
+ END {print("percentage", (cur / max) * 100)}
+' \
+"$screen_brightness_device_path/max_brightness" \
+"$screen_brightness_device_path/brightness"
thermal_zone="$1"
-cat "/sys/class/thermal/thermal_zone${thermal_zone}/temp"
+awk '
+ BEGIN {
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
+ }
+
+ {print("temp_c", $1 / 1000)}
+' \
+"/sys/class/thermal/thermal_zone${thermal_zone}/temp"
--- /dev/null
+#! /usr/bin/awk -f
+
+BEGIN {
+ FS = msg_fs ? msg_fs : "|"
+ OFS = msg_fs ? msg_fs : "|"
+ Kfs = key_fs ? key_fs : ":"
+}
+
+# Modify the record we're interested in
+$1 == status && $2 == src && ($3 ~ ("^" key_prefix)) {
+ key = $3
+ val = $4
+ prev[key] = curr[key]
+ curr[key] = val
+ diff[key] = curr[key] - prev[key]
+ print($1, $2, $3, diff[key])
+ next
+}
+
+# Let everything else through untouched
+//