From: Siraaj Khandkar Date: Thu, 16 Aug 2018 00:47:00 +0000 (-0400) Subject: Redesign component interfaces X-Git-Url: https://git.xandkar.net/?p=khatus.git;a=commitdiff_plain;h=75b23ff8a814c76a4fa0fa12a40e6a929beec695 Redesign component interfaces to be consistent src/key/val triples --- diff --git a/bin/khatus b/bin/khatus index bbc7ab8..371b15c 100755 --- a/bin/khatus +++ b/bin/khatus @@ -1,24 +1,18 @@ #! /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" = '' ] @@ -42,40 +36,51 @@ run_producer() { 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 & } @@ -88,22 +93,22 @@ main() { ["--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 @@ -175,38 +180,67 @@ main() { 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 $@ diff --git a/bin/khatus_actuate_alert_to_notify_send b/bin/khatus_actuate_alert_to_notify_send index b1c695a..e383917 100755 --- a/bin/khatus_actuate_alert_to_notify_send +++ b/bin/khatus_actuate_alert_to_notify_send @@ -6,14 +6,23 @@ BEGIN { # 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 diff --git a/bin/khatus_actuate_status_bar_to_xsetroot_name b/bin/khatus_actuate_status_bar_to_xsetroot_name index a7463e2..f41cbd1 100755 --- a/bin/khatus_actuate_status_bar_to_xsetroot_name +++ b/bin/khatus_actuate_status_bar_to_xsetroot_name @@ -1,8 +1,21 @@ #! /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 } diff --git a/bin/khatus_bar b/bin/khatus_bar new file mode 100755 index 0000000..025b968 --- /dev/null +++ b/bin/khatus_bar @@ -0,0 +1,310 @@ +#! /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) +} diff --git a/bin/khatus_controller b/bin/khatus_controller deleted file mode 100755 index 72136d0..0000000 --- a/bin/khatus_controller +++ /dev/null @@ -1,602 +0,0 @@ -#! /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 diff --git a/bin/khatus_monitor_energy b/bin/khatus_monitor_energy new file mode 100755 index 0000000..a295e3e --- /dev/null +++ b/bin/khatus_monitor_energy @@ -0,0 +1,98 @@ +#! /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 diff --git a/bin/khatus_monitor_errors b/bin/khatus_monitor_errors new file mode 100755 index 0000000..459b0ea --- /dev/null +++ b/bin/khatus_monitor_errors @@ -0,0 +1,28 @@ +#! /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) +} diff --git a/bin/khatus_parse_bluetoothctl_show b/bin/khatus_parse_bluetoothctl_show index ed1e228..0d56853 100755 --- a/bin/khatus_parse_bluetoothctl_show +++ b/bin/khatus_parse_bluetoothctl_show @@ -1,5 +1,10 @@ #! /usr/bin/awk -f +BEGIN { + OFS = msg_fs ? msg_fs : "|" + Kfs = key_fs ? key_fs : ":" +} + /^Controller / { controller = $2 controllers[++ctrl_count] = controller @@ -28,7 +33,7 @@ END { } else { show = "n/a" } - print(show) + print("power_status", show) } function print_error(msg) { diff --git a/bin/khatus_parse_df_pcent b/bin/khatus_parse_df_pcent new file mode 100755 index 0000000..7e4a534 --- /dev/null +++ b/bin/khatus_parse_df_pcent @@ -0,0 +1,12 @@ +#! /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) +} diff --git a/bin/khatus_parse_fan_file b/bin/khatus_parse_fan_file new file mode 100755 index 0000000..120e150 --- /dev/null +++ b/bin/khatus_parse_fan_file @@ -0,0 +1,13 @@ +#! /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 new file mode 100755 index 0000000..452f44d --- /dev/null +++ b/bin/khatus_parse_free @@ -0,0 +1,11 @@ +#! /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_ip_addr b/bin/khatus_parse_ip_addr index bc833b2..b1b2ecd 100755 --- a/bin/khatus_parse_ip_addr +++ b/bin/khatus_parse_ip_addr @@ -1,17 +1,22 @@ #! /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"} @@ -23,15 +28,21 @@ 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]) } } diff --git a/bin/khatus_parse_iwconfig b/bin/khatus_parse_iwconfig index e502731..a33b50f 100755 --- a/bin/khatus_parse_iwconfig +++ b/bin/khatus_parse_iwconfig @@ -15,6 +15,11 @@ # # 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, ":") @@ -32,6 +37,6 @@ 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) } diff --git a/bin/khatus_parse_loadavg_file b/bin/khatus_parse_loadavg_file new file mode 100755 index 0000000..f7665fa --- /dev/null +++ b/bin/khatus_parse_loadavg_file @@ -0,0 +1,17 @@ +#! /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) +} diff --git a/bin/khatus_parse_metar_d_output b/bin/khatus_parse_metar_d_output index b228390..1dd2778 100755 --- a/bin/khatus_parse_metar_d_output +++ b/bin/khatus_parse_metar_d_output @@ -3,10 +3,9 @@ # 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/ { @@ -36,12 +35,19 @@ END { 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 +} diff --git a/bin/khatus_parse_mpd_status b/bin/khatus_parse_mpd_status deleted file mode 100755 index 1088b4e..0000000 --- a/bin/khatus_parse_mpd_status +++ /dev/null @@ -1,39 +0,0 @@ -#! /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 -} diff --git a/bin/khatus_parse_mpd_status_currentsong b/bin/khatus_parse_mpd_status_currentsong new file mode 100755 index 0000000..c045c0f --- /dev/null +++ b/bin/khatus_parse_mpd_status_currentsong @@ -0,0 +1,88 @@ +#! /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"] = "~" + } +} diff --git a/bin/khatus_parse_pactl_list_sinks b/bin/khatus_parse_pactl_list_sinks index 2de73e8..7ed10e6 100755 --- a/bin/khatus_parse_pactl_list_sinks +++ b/bin/khatus_parse_pactl_list_sinks @@ -1,5 +1,10 @@ #! /usr/bin/awk -f +BEGIN { + OFS = msg_fs ? msg_fs : "|" + Kfs = key_fs ? key_fs : ":" +} + /^Sink \#[0-9]+$/ { sub("^#", "", $2) sink = $2 @@ -34,9 +39,9 @@ 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]) } } diff --git a/bin/khatus_parse_sys_block_stat b/bin/khatus_parse_sys_block_stat new file mode 100755 index 0000000..923e3ee --- /dev/null +++ b/bin/khatus_parse_sys_block_stat @@ -0,0 +1,11 @@ +#! /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/bin/khatus_parse_upower b/bin/khatus_parse_upower index 6761508..af73e19 100755 --- a/bin/khatus_parse_upower +++ b/bin/khatus_parse_upower @@ -1,5 +1,10 @@ #! /usr/bin/awk -f +BEGIN { + OFS = msg_fs ? msg_fs : "|" + Kfs = key_fs ? key_fs : ":" +} + # When parsing 'upower --dump' /^Device:[ \t]+/ { device["path"] = $2 @@ -25,11 +30,13 @@ / 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 @@ -45,7 +52,7 @@ } /^$/ && device["is_line_power"] { - printf("line_power %s\n", device["line_power_online"]) + print("line_power", device["line_power_online"]) } # END line-power diff --git a/bin/khatus_sensor_datetime b/bin/khatus_sensor_datetime index ee1da65..effcb1a 100755 --- a/bin/khatus_sensor_datetime +++ b/bin/khatus_sensor_datetime @@ -1,3 +1,19 @@ #! /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) + } + ' diff --git a/bin/khatus_sensor_disk_io b/bin/khatus_sensor_disk_io index 379bcb3..840aed3 100755 --- a/bin/khatus_sensor_disk_io +++ b/bin/khatus_sensor_disk_io @@ -2,13 +2,7 @@ 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" diff --git a/bin/khatus_sensor_disk_space b/bin/khatus_sensor_disk_space index b0f00e6..218d050 100755 --- a/bin/khatus_sensor_disk_space +++ b/bin/khatus_sensor_disk_space @@ -2,6 +2,7 @@ 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 diff --git a/bin/khatus_sensor_fan b/bin/khatus_sensor_fan index 12db7b6..40c580b 100755 --- a/bin/khatus_sensor_fan +++ b/bin/khatus_sensor_fan @@ -2,6 +2,7 @@ set -e -fan_path="$1" +dir_bin="$1" +fan_path="$2" -cat "$fan_path" +"$dir_bin"/khatus_parse_fan_file "$fan_path" diff --git a/bin/khatus_sensor_loadavg b/bin/khatus_sensor_loadavg index 283d032..04f386f 100755 --- a/bin/khatus_sensor_loadavg +++ b/bin/khatus_sensor_loadavg @@ -2,4 +2,6 @@ set -e -cat /proc/loadavg +dir_bin="$1" + +"$dir_bin"/khatus_parse_loadavg_file /proc/loadavg diff --git a/bin/khatus_sensor_memory b/bin/khatus_sensor_memory index 0b79722..10dd058 100755 --- a/bin/khatus_sensor_memory +++ b/bin/khatus_sensor_memory @@ -2,4 +2,6 @@ set -e -free | awk '$1 == "Mem:" {print $2, $3}' +dir_bin="$1" + +free | "$dir_bin"/khatus_parse_free diff --git a/bin/khatus_sensor_mpd b/bin/khatus_sensor_mpd new file mode 100755 index 0000000..058cecd --- /dev/null +++ b/bin/khatus_sensor_mpd @@ -0,0 +1,9 @@ +#! /bin/sh + +set -e + +dir_bin="$1" + +echo 'status\ncurrentsong' \ +| nc 127.0.0.1 6600 \ +| "$dir_bin"/khatus_parse_mpd_status_currentsong diff --git a/bin/khatus_sensor_mpd_song b/bin/khatus_sensor_mpd_song deleted file mode 100755 index 0d119d1..0000000 --- a/bin/khatus_sensor_mpd_song +++ /dev/null @@ -1,5 +0,0 @@ -#! /bin/sh - -set -e - -echo 'currentsong' | nc 127.0.0.1 6600 diff --git a/bin/khatus_sensor_mpd_state b/bin/khatus_sensor_mpd_state deleted file mode 100755 index 20cc49a..0000000 --- a/bin/khatus_sensor_mpd_state +++ /dev/null @@ -1,9 +0,0 @@ -#! /bin/sh - -set -e - -dir_bin="$1" - -echo 'status' \ -| nc 127.0.0.1 6600 \ -| "$dir_bin"/khatus_parse_mpd_status diff --git a/bin/khatus_sensor_screen_brightness b/bin/khatus_sensor_screen_brightness index 08a8dfc..9b075d3 100755 --- a/bin/khatus_sensor_screen_brightness +++ b/bin/khatus_sensor_screen_brightness @@ -4,7 +4,15 @@ set -e 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" diff --git a/bin/khatus_sensor_temperature b/bin/khatus_sensor_temperature index 6f9bd23..321c8d8 100755 --- a/bin/khatus_sensor_temperature +++ b/bin/khatus_sensor_temperature @@ -4,4 +4,12 @@ set -e 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" diff --git a/bin/khatus_transform_total_to_diff b/bin/khatus_transform_total_to_diff new file mode 100755 index 0000000..59894c0 --- /dev/null +++ b/bin/khatus_transform_total_to_diff @@ -0,0 +1,21 @@ +#! /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 +//