From f37162a4803ea6318e3620b6deccd8659316f31d Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Tue, 31 Jul 2018 12:55:16 -0400 Subject: [PATCH] Split workers into dedicated files --- bin/khatus | 698 ++-------------------------- bin/khatus_controller | 337 ++++++++++++++ bin/khatus_sensor_bar_req | 3 + bin/khatus_sensor_bluetooth_power | 37 ++ bin/khatus_sensor_datetime | 3 + bin/khatus_sensor_disk_io | 14 + bin/khatus_sensor_disk_space | 7 + bin/khatus_sensor_energy | 12 + bin/khatus_sensor_fan | 7 + bin/khatus_sensor_loadavg | 5 + bin/khatus_sensor_memory | 5 + bin/khatus_sensor_mpd_song | 36 ++ bin/khatus_sensor_mpd_state | 53 +++ bin/khatus_sensor_net_addr_io | 40 ++ bin/khatus_sensor_net_wifi_status | 15 + bin/khatus_sensor_screen_brightness | 10 + bin/khatus_sensor_temperature | 7 + bin/khatus_sensor_volume | 24 + bin/khatus_sensor_weather | 24 + 19 files changed, 681 insertions(+), 656 deletions(-) create mode 100755 bin/khatus_controller create mode 100755 bin/khatus_sensor_bar_req create mode 100755 bin/khatus_sensor_bluetooth_power create mode 100755 bin/khatus_sensor_datetime create mode 100755 bin/khatus_sensor_disk_io create mode 100755 bin/khatus_sensor_disk_space create mode 100755 bin/khatus_sensor_energy create mode 100755 bin/khatus_sensor_fan create mode 100755 bin/khatus_sensor_loadavg create mode 100755 bin/khatus_sensor_memory create mode 100755 bin/khatus_sensor_mpd_song create mode 100755 bin/khatus_sensor_mpd_state create mode 100755 bin/khatus_sensor_net_addr_io create mode 100755 bin/khatus_sensor_net_wifi_status create mode 100755 bin/khatus_sensor_screen_brightness create mode 100755 bin/khatus_sensor_temperature create mode 100755 bin/khatus_sensor_volume create mode 100755 bin/khatus_sensor_weather diff --git a/bin/khatus b/bin/khatus index d29755d..129ecf7 100755 --- a/bin/khatus +++ b/bin/khatus @@ -2,648 +2,26 @@ set -e -produce_energy() { - upower -e \ - | grep battery \ - | xargs upower -i \ - | awk ' - /^ +percentage: +/ { percentage=$2 } - /^ +state: +/ { state=$2 } - END { print(state, percentage) } - ' -} - - -produce_memory() { - free | awk '$1 == "Mem:" {print $2, $3}' -} - -produce_fan() { - fan_path="$1" - cat "$fan_path" -} - -produce_temperature() { - thermal_zone="$1" - cat "/sys/class/thermal/thermal_zone${thermal_zone}/temp" -} - -produce_loadavg() { - cat /proc/loadavg -} - -produce_disk_io() { - disk_io_device="$1" - awk ' - { - r = $3 - w = $7 - print w, r - } - ' "/sys/block/$disk_io_device/stat" -} - -produce_disk_space() { - disk_space_device="$1" - df --output=pcent "$disk_space_device" | awk 'NR == 2 {print $1}' -} - -produce_net_addr_io() { - ip -s addr \ - | awk ' - BEGIN { - bytes_per_unit = 1024 * 1024 - } - - /^[0-9]+:/ { - sub(":$", "", $1) - sub(":$", "", $2) - sequence = $1 - interface = $2 - interfaces[sequence] = interface - } - - /^ +inet [0-9]/ { - sub("/[0-9]+", "", $2) - addr = $2 - addrs[interface] = addr - } - - /^ +RX: / {transfer_direction = "r"} - /^ +TX: / {transfer_direction = "w"} - - /^ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ *$/ { - io[interface, transfer_direction] = $1; - } - - END { - for (seq=1; seq<=sequence; seq++) { - interface = interfaces[seq] - label = substr(interface, 1, 1) - if (addrs[interface]) { - curr_read = io[interface, "r"] - curr_write = io[interface, "w"] - print(interface, addrs[interface], curr_write, curr_read) - } else { - print(interface) - } - } - }' -} - -produce_net_wifi_status() { - nmcli \ - -f ACTIVE,SSID,SIGNAL \ - -t \ - d wifi \ - | awk \ - -F ':' \ - ' - BEGIN {wifi_status = "--"} - $1 == "yes" {wifi_status = $2 ":" $3 "%"} - END {print wifi_status} - ' -} - -produce_bluetooth_power() { - echo -e 'show \n quit' \ - | bluetoothctl \ - | awk ' - /^Controller / { - controller = $2; - controllers[++ctrl_count] = controller; - } - /^\t[A-Z][A-Za-z]+:/ { - key = $1; - sub(":$", "", key); - val = $2; - for (i=3; i<=NF; i++) { - val = val " " $i}; - data[controller, key] = val; - } - END { - # Using the 1st seen controller. Should we select specific instead? - power_status = data[controllers[1], "Powered"]; - if (ctrl_count > 0) { - if (power_status == "no") { - power_status = "off" - } else if (power_status == "yes") { - power_status = "on" - } else { - printf("Unexpected bluetooth power status: %s\n", power_status)\ - > "/dev/stderr"; - power_status = "ERROR" - } - } else { - power_status = "off" # TODO: Perhaps use differentiated marker? - } - printf("%s\n", power_status); - }' -} - -produce_screen_brightness() { - screen_brightness_device_path="$1" - echo "\ - $(cat $screen_brightness_device_path/max_brightness) \ - $(cat $screen_brightness_device_path/brightness)\ - " -} - -produce_volume() { - pactl list sinks \ - | awk ' - /^\tMute:/ { - printf("%s,", $0); - } - /^\tVolume:/ { - for (i=2; i<=NF; i++) printf(" %s", $i); - }' \ - | awk -v RS=',' ' - /^[ \t]*Mute:/ {mute = $2} - /^[ \t]*front-left:/ {left = $4} - /^[ \t]*front-right:/ {right = $4} - END { - if (mute == "yes") { - print("x") - } else { - print("%s %s\n", left, right) - } - } - ' -} - -produce_mpd_state() { - echo 'status' \ - | nc 127.0.0.1 6600 \ - | awk ' - { - status[$1] = $2 - } - - /^time: +[0-9]+:[0-9]+$/ { - split($2, 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 = "~" - } - } - - END { - state = status["state:"] - - if (state == "play") { - symbol = "▶" - } else if (state == "pause") { - symbol = "❚❚" - } else if (state == "stop") { - symbol = "⬛" - } else { - symbol = "--" - } - - printf(\ - "%s %s %s\n", - status["state:"], current_time, current_percentage\ - ) - } - ' -} - -produce_mpd_song() { - echo 'currentsong' \ - | nc 127.0.0.1 6600 \ - | awk ' - /^OK/ { - next - } - - { - key = $1 - sub("^" key " +", "") - val = $0 - data[key] = val - } - - END { - name = data["Name:"] - title = data["Title:"] - file = data["file:"] - - if (name) { - out = name - } else if (title) { - out = title - } else if (file) { - last = split(file, parts, "/") - out = parts[last] - } else { - out = "" - } - print out - } - ' -} - -produce_weather() { - weather_station_id="$1" - metar -d "$weather_station_id" 2>&1 \ - | awk ' - /METAR pattern not found in NOAA data/ { - failures++ - } - - /^Temperature/ { - celsius = $3; - fahrenheit = (celsius * (9 / 5)) + 32; - temperature = fahrenheit - } - - END { - if (failures > 0) { - temperature = "--" - } - print temperature "°F" - }' -} - -produce_datetime() { - date +'%a %b %d %H:%M:%S' -} - consume() { pipe="$1" debug="$2" - prefixes_of_net_interfaces_to_show="$3" + dir_bin="$3" + prefixes_of_net_interfaces_to_show="$4" tail -f "$pipe" \ - | stdbuf -o L awk \ + | stdbuf -o L "$dir_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" \ - ' - /^in:ENERGY/\ - { - split_msg_parts() - db["energy_state"] = $1 - db["energy_percentage"] = $2 - } - - /^in:MEMORY/\ - { - split_msg_parts() - db["memory_total"] = $1 - db["memory_used"] = $2 - } - - /^in:FAN +status:/\ - { - split_msg_parts() - db["fan_status"] = $2 - } - - /^in:FAN +speed:/\ - { - split_msg_parts() - db["fan_speed"] = $2 - } - - /^in:FAN +level:/\ - { - split_msg_parts() - db["fan_level"] = $2 - } - - /^in:TEMPERATURE/\ - { - split_msg_parts() - db["temperature"] = $1 - } - - /^in:LOAD_AVG/\ - { - split_msg_parts() - set_load_avg() - } - - /^in:DISK_IO/\ - { - split_msg_parts() - set_disk_io() - } - - /^in:DISK_SPACE/\ - { - split_msg_parts() - db["disk_space_used"] = msg_body - } - - /^in:NET_ADDR_IO/\ - { - split_msg_parts() - set_net_addr_io() - } - - /^in:NET_WIFI_STATUS/\ - { - split_msg_parts() - db["net_wifi_status"] = msg_body - } - - /^in:BLUETOOTH_POWER/\ - { - split_msg_parts() - db["bluetooth_power"] = msg_body - } - - /^in:SCREEN_BRIGHTNESS/\ - { - split_msg_parts() - set_screen_brightness() - } - - /^in:VOLUME/\ - { - split_msg_parts() - db["volume"] = msg_body - } - - /^in:MPD_STATE/\ - { - split_msg_parts() - db["mpd_state"] = $1 - db["mpd_curr_song_time"] = $2 - db["mpd_curr_song_percent"] = $3 - } - - /^in:MPD_SONG/\ - { - split_msg_parts() - db["mpd_curr_song_name"] = msg_body - } - - /^in:WEATHER/\ - { - split_msg_parts() - db["weather_temperature"] = msg_body - } - - /^in:DATE_TIME/\ - { - split_msg_parts() - db["datetime"] = msg_body - } - - /^out:BAR/\ - { - split_msg_parts() - print make_bar() - } - - 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_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 - } - - function split_msg_parts() { - msg_head = $1 - sub("^" msg_head " +", "") - msg_body = $0 - debug(msg_head, msg_body) - } - - function make_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"] - if (state == "discharging") { - direction_of_change = "<" - } else if (state == "charging") { - direction_of_change = ">" - } else { - direction_of_change = "=" - }; - printf("E%s%s", 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"] - } - 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_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_curr_song_time"], - db["mpd_curr_song_percent"], - substr(db["mpd_curr_song_name"], 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) { - if (opt_debug) { - print_error(location, msg) - } - } - - function print_error(location, msg) { - print(location " ==> " msg) > "/dev/stderr" - } - ' -} - -produce_bar_req() { - echo '' + -v opt_prefixes_of_net_interfaces_to_show="$prefixes_of_net_interfaces_to_show" } spawn() { - cmd="$1" - pipe="$2" - msg_head="$3" - interval="$4" + pipe="$1" + dir_bin="$2" + cmd="$3" + msg_head="$4" + interval="$5" while true; do - $cmd | while read line; do + "$dir_bin"/$cmd | while read line; do echo "${msg_head} $line" > "$pipe" done sleep "$interval" @@ -653,6 +31,7 @@ spawn() { main() { # Defaults debug=0 + dir_bin="$HOME/bin" dir_data=$(mktemp -d) weather_station_id='KJFK' screen_brightness_device_name='acpi_video0' @@ -683,6 +62,7 @@ main() { # User-overrides long_options='' long_options+='debug' + long_options+=',bin_dir:' long_options+=',data_dir:' long_options+=',weather_station:' long_options+=',screen_device:' @@ -722,6 +102,10 @@ main() { debug=1 shift ;; + --bin_dir) + dir_bin="$2" + shift 2 + ;; --data_dir) dir_data="$2" shift 2 @@ -835,6 +219,7 @@ main() { ( echo "Khatus starting with the following parameters:" ( echo " debug|= $debug" + echo " dir_bin|= $dir_bin" echo " dir_data|= $dir_data" echo " pipe|= $pipe" echo " screen_brightness_device_name|= $screen_brightness_device_name" @@ -853,41 +238,42 @@ main() { rm -f "$pipe" mkfifo "$pipe" - cmd_produce_screen_brightness='produce_screen_brightness' - cmd_produce_screen_brightness+=" $screen_brightness_device_path" + cmd_sens_screen_brightness='khatus_sensor_screen_brightness' + cmd_sens_screen_brightness+=" $screen_brightness_device_path" - cmd_produce_weather="produce_weather $weather_station_id" + cmd_sens_weather="khatus_sensor_weather $weather_station_id" - cmd_produce_disk_space="produce_disk_space $disk_space_device" + cmd_sens_disk_space="khatus_sensor_disk_space $disk_space_device" - cmd_produce_disk_io="produce_disk_io $disk_io_device" + cmd_sens_disk_io="khatus_sensor_disk_io $disk_io_device" - cmd_produce_temperature="produce_temperature $thermal_zone" + cmd_sens_temperature="khatus_sensor_temperature $thermal_zone" - cmd_produce_fan="produce_fan $fan_path" + cmd_sens_fan="khatus_sensor_fan $fan_path" # TODO: Redirect each worker's stderr to a dedicated log file - spawn produce_datetime "$pipe" 'in:DATE_TIME' $interval_inp_datetime - spawn "$cmd_produce_screen_brightness" "$pipe" 'in:SCREEN_BRIGHTNESS' $interval_inp_brightness - spawn "$cmd_produce_weather" "$pipe" 'in:WEATHER' $interval_inp_weather - spawn produce_mpd_state "$pipe" 'in:MPD_STATE' $interval_inp_mpd_state - spawn produce_mpd_song "$pipe" 'in:MPD_SONG' $interval_inp_mpd_song - spawn produce_volume "$pipe" 'in:VOLUME' $interval_inp_volume - spawn produce_bluetooth_power "$pipe" 'in:BLUETOOTH_POWER' $interval_inp_bluetooth - spawn produce_net_wifi_status "$pipe" 'in:NET_WIFI_STATUS' $interval_inp_net_wifi - spawn produce_net_addr_io "$pipe" 'in:NET_ADDR_IO' $interval_inp_net_io - spawn "$cmd_produce_disk_space" "$pipe" 'in:DISK_SPACE' $interval_inp_disk_space - spawn "$cmd_produce_disk_io" "$pipe" 'in:DISK_IO' $interval_inp_disk_io - spawn produce_loadavg "$pipe" 'in:LOAD_AVG' $interval_inp_loadavg - spawn "$cmd_produce_temperature" "$pipe" 'in:TEMPERATURE' $interval_inp_temp - spawn "$cmd_produce_fan" "$pipe" 'in:FAN' $interval_inp_fan - spawn produce_memory "$pipe" 'in:MEMORY' $interval_inp_mem - spawn produce_energy "$pipe" 'in:ENERGY' $interval_inp_energy - spawn produce_bar_req "$pipe" 'out:BAR' $interval_outp_bar + spawn "$pipe" "$dir_bin" khatus_sensor_datetime 'in:DATE_TIME' $interval_inp_datetime + spawn "$pipe" "$dir_bin" "$cmd_sens_screen_brightness" 'in:SCREEN_BRIGHTNESS' $interval_inp_brightness + spawn "$pipe" "$dir_bin" "$cmd_sens_weather" 'in:WEATHER' $interval_inp_weather + spawn "$pipe" "$dir_bin" khatus_sensor_mpd_state 'in:MPD_STATE' $interval_inp_mpd_state + spawn "$pipe" "$dir_bin" khatus_sensor_mpd_song 'in:MPD_SONG' $interval_inp_mpd_song + spawn "$pipe" "$dir_bin" khatus_sensor_volume 'in:VOLUME' $interval_inp_volume + spawn "$pipe" "$dir_bin" khatus_sensor_bluetooth_power 'in:BLUETOOTH_POWER' $interval_inp_bluetooth + spawn "$pipe" "$dir_bin" khatus_sensor_net_wifi_status 'in:NET_WIFI_STATUS' $interval_inp_net_wifi + spawn "$pipe" "$dir_bin" khatus_sensor_net_addr_io 'in:NET_ADDR_IO' $interval_inp_net_io + spawn "$pipe" "$dir_bin" "$cmd_sens_disk_space" 'in:DISK_SPACE' $interval_inp_disk_space + spawn "$pipe" "$dir_bin" "$cmd_sens_disk_io" 'in:DISK_IO' $interval_inp_disk_io + spawn "$pipe" "$dir_bin" khatus_sensor_loadavg 'in:LOAD_AVG' $interval_inp_loadavg + spawn "$pipe" "$dir_bin" "$cmd_sens_temperature" 'in:TEMPERATURE' $interval_inp_temp + spawn "$pipe" "$dir_bin" "$cmd_sens_fan" 'in:FAN' $interval_inp_fan + spawn "$pipe" "$dir_bin" khatus_sensor_memory 'in:MEMORY' $interval_inp_mem + spawn "$pipe" "$dir_bin" khatus_sensor_energy 'in:ENERGY' $interval_inp_energy + spawn "$pipe" "$dir_bin" khatus_sensor_bar_req 'out:BAR' $interval_outp_bar consume \ "$pipe" \ "$debug" \ + "$dir_bin" \ "$prefixes_of_net_interfaces_to_show" } diff --git a/bin/khatus_controller b/bin/khatus_controller new file mode 100755 index 0000000..e6954a2 --- /dev/null +++ b/bin/khatus_controller @@ -0,0 +1,337 @@ +#! /usr/bin/awk -f + +/^in:ENERGY/\ +{ + split_msg_parts() + db["energy_state"] = $1 + db["energy_percentage"] = $2 +} + +/^in:MEMORY/\ +{ + split_msg_parts() + db["memory_total"] = $1 + db["memory_used"] = $2 +} + +/^in:FAN +status:/\ +{ + split_msg_parts() + db["fan_status"] = $2 +} + +/^in:FAN +speed:/\ +{ + split_msg_parts() + db["fan_speed"] = $2 +} + +/^in:FAN +level:/\ +{ + split_msg_parts() + db["fan_level"] = $2 +} + +/^in:TEMPERATURE/\ +{ + split_msg_parts() + db["temperature"] = $1 +} + +/^in:LOAD_AVG/\ +{ + split_msg_parts() + set_load_avg() +} + +/^in:DISK_IO/\ +{ + split_msg_parts() + set_disk_io() +} + +/^in:DISK_SPACE/\ +{ + split_msg_parts() + db["disk_space_used"] = msg_body +} + +/^in:NET_ADDR_IO/\ +{ + split_msg_parts() + set_net_addr_io() +} + +/^in:NET_WIFI_STATUS/\ +{ + split_msg_parts() + db["net_wifi_status"] = msg_body +} + +/^in:BLUETOOTH_POWER/\ +{ + split_msg_parts() + db["bluetooth_power"] = msg_body +} + +/^in:SCREEN_BRIGHTNESS/\ +{ + split_msg_parts() + set_screen_brightness() +} + +/^in:VOLUME/\ +{ + split_msg_parts() + db["volume"] = msg_body +} + +/^in:MPD_STATE/\ +{ + split_msg_parts() + db["mpd_state"] = $1 + db["mpd_curr_song_time"] = $2 + db["mpd_curr_song_percent"] = $3 +} + +/^in:MPD_SONG/\ +{ + split_msg_parts() + db["mpd_curr_song_name"] = msg_body +} + +/^in:WEATHER/\ +{ + split_msg_parts() + db["weather_temperature"] = msg_body +} + +/^in:DATE_TIME/\ +{ + split_msg_parts() + db["datetime"] = msg_body +} + +/^out:BAR/\ +{ + split_msg_parts() + print make_bar() +} + +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_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 +} + +function split_msg_parts() { + msg_head = $1 + sub("^" msg_head " +", "") + msg_body = $0 + debug(msg_head, msg_body) +} + +function make_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"] + if (state == "discharging") { + direction_of_change = "<" + } else if (state == "charging") { + direction_of_change = ">" + } else { + direction_of_change = "=" + }; + printf("E%s%s", 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"] + } + 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_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_curr_song_time"], + db["mpd_curr_song_percent"], + substr(db["mpd_curr_song_name"], 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) { + if (opt_debug) { + print_error(location, msg) + } +} + +function print_error(location, msg) { + print(location " ==> " msg) > "/dev/stderr" +} diff --git a/bin/khatus_sensor_bar_req b/bin/khatus_sensor_bar_req new file mode 100755 index 0000000..d4fb1c1 --- /dev/null +++ b/bin/khatus_sensor_bar_req @@ -0,0 +1,3 @@ +#! /bin/sh + +echo '' diff --git a/bin/khatus_sensor_bluetooth_power b/bin/khatus_sensor_bluetooth_power new file mode 100755 index 0000000..92c2128 --- /dev/null +++ b/bin/khatus_sensor_bluetooth_power @@ -0,0 +1,37 @@ +#! /bin/sh + +set -e + +echo -e 'show \n quit' \ +| bluetoothctl \ +| awk ' + /^Controller / { + controller = $2; + controllers[++ctrl_count] = controller; + } + /^\t[A-Z][A-Za-z]+:/ { + key = $1; + sub(":$", "", key); + val = $2; + for (i=3; i<=NF; i++) { + val = val " " $i}; + data[controller, key] = val; + } + END { + # Using the 1st seen controller. Should we select specific instead? + power_status = data[controllers[1], "Powered"]; + if (ctrl_count > 0) { + if (power_status == "no") { + power_status = "off" + } else if (power_status == "yes") { + power_status = "on" + } else { + printf("Unexpected bluetooth power status: %s\n", power_status)\ + > "/dev/stderr"; + power_status = "ERROR" + } + } else { + power_status = "off" # TODO: Perhaps use differentiated marker? + } + printf("%s\n", power_status); + }' diff --git a/bin/khatus_sensor_datetime b/bin/khatus_sensor_datetime new file mode 100755 index 0000000..ee1da65 --- /dev/null +++ b/bin/khatus_sensor_datetime @@ -0,0 +1,3 @@ +#! /bin/sh + +date +'%a %b %d %H:%M:%S' diff --git a/bin/khatus_sensor_disk_io b/bin/khatus_sensor_disk_io new file mode 100755 index 0000000..379bcb3 --- /dev/null +++ b/bin/khatus_sensor_disk_io @@ -0,0 +1,14 @@ +#! /bin/sh + +set -e + +disk_io_device="$1" + +awk ' + { + r = $3 + w = $7 + print w, r + } + ' \ + "/sys/block/$disk_io_device/stat" diff --git a/bin/khatus_sensor_disk_space b/bin/khatus_sensor_disk_space new file mode 100755 index 0000000..b0f00e6 --- /dev/null +++ b/bin/khatus_sensor_disk_space @@ -0,0 +1,7 @@ +#! /bin/sh + +set -e + +disk_space_device="$1" + +df --output=pcent "$disk_space_device" | awk 'NR == 2 {print $1}' diff --git a/bin/khatus_sensor_energy b/bin/khatus_sensor_energy new file mode 100755 index 0000000..f91155f --- /dev/null +++ b/bin/khatus_sensor_energy @@ -0,0 +1,12 @@ +#! /bin/sh + +set -e + +upower -e \ +| grep battery \ +| xargs upower -i \ +| awk ' + /^ +percentage: +/ { percentage=$2 } + /^ +state: +/ { state=$2 } + END { print(state, percentage) } + ' diff --git a/bin/khatus_sensor_fan b/bin/khatus_sensor_fan new file mode 100755 index 0000000..12db7b6 --- /dev/null +++ b/bin/khatus_sensor_fan @@ -0,0 +1,7 @@ +#! /bin/sh + +set -e + +fan_path="$1" + +cat "$fan_path" diff --git a/bin/khatus_sensor_loadavg b/bin/khatus_sensor_loadavg new file mode 100755 index 0000000..283d032 --- /dev/null +++ b/bin/khatus_sensor_loadavg @@ -0,0 +1,5 @@ +#! /bin/sh + +set -e + +cat /proc/loadavg diff --git a/bin/khatus_sensor_memory b/bin/khatus_sensor_memory new file mode 100755 index 0000000..0b79722 --- /dev/null +++ b/bin/khatus_sensor_memory @@ -0,0 +1,5 @@ +#! /bin/sh + +set -e + +free | awk '$1 == "Mem:" {print $2, $3}' diff --git a/bin/khatus_sensor_mpd_song b/bin/khatus_sensor_mpd_song new file mode 100755 index 0000000..49f7f15 --- /dev/null +++ b/bin/khatus_sensor_mpd_song @@ -0,0 +1,36 @@ +#! /bin/sh + +set -e + +echo 'currentsong' \ +| nc 127.0.0.1 6600 \ +| awk ' + /^OK/ { + next + } + + { + key = $1 + sub("^" key " +", "") + val = $0 + data[key] = val + } + + END { + name = data["Name:"] + title = data["Title:"] + file = data["file:"] + + if (name) { + out = name + } else if (title) { + out = title + } else if (file) { + last = split(file, parts, "/") + out = parts[last] + } else { + out = "" + } + print out + } + ' diff --git a/bin/khatus_sensor_mpd_state b/bin/khatus_sensor_mpd_state new file mode 100755 index 0000000..b5c9b08 --- /dev/null +++ b/bin/khatus_sensor_mpd_state @@ -0,0 +1,53 @@ +#! /bin/sh + +set -e + +echo 'status' \ +| nc 127.0.0.1 6600 \ +| awk ' + { + status[$1] = $2 + } + + /^time: +[0-9]+:[0-9]+$/ { + split($2, 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 = "~" + } + } + + END { + state = status["state:"] + + if (state == "play") { + symbol = "▶" + } else if (state == "pause") { + symbol = "❚❚" + } else if (state == "stop") { + symbol = "⬛" + } else { + symbol = "--" + } + + printf(\ + "%s %s %s\n", + status["state:"], current_time, current_percentage\ + ) + } + ' diff --git a/bin/khatus_sensor_net_addr_io b/bin/khatus_sensor_net_addr_io new file mode 100755 index 0000000..48b9b07 --- /dev/null +++ b/bin/khatus_sensor_net_addr_io @@ -0,0 +1,40 @@ +#! /bin/sh + +set -e + +ip -s addr \ +| awk ' + /^[0-9]+:/ { + sub(":$", "", $1) + sub(":$", "", $2) + sequence = $1 + interface = $2 + interfaces[sequence] = interface + } + + /^ +inet [0-9]/ { + sub("/[0-9]+", "", $2) + addr = $2 + addrs[interface] = addr + } + + /^ +RX: / {transfer_direction = "r"} + /^ +TX: / {transfer_direction = "w"} + + /^ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ *$/ { + io[interface, transfer_direction] = $1; + } + + END { + for (seq=1; seq<=sequence; seq++) { + interface = interfaces[seq] + label = substr(interface, 1, 1) + if (addrs[interface]) { + curr_read = io[interface, "r"] + curr_write = io[interface, "w"] + print(interface, addrs[interface], curr_write, curr_read) + } else { + print(interface) + } + } + }' diff --git a/bin/khatus_sensor_net_wifi_status b/bin/khatus_sensor_net_wifi_status new file mode 100755 index 0000000..de7fd58 --- /dev/null +++ b/bin/khatus_sensor_net_wifi_status @@ -0,0 +1,15 @@ +#! /bin/sh + +set -e + +nmcli \ + -f ACTIVE,SSID,SIGNAL \ + -t \ + d wifi \ +| awk \ + -F ':' \ + ' + BEGIN {wifi_status = "--"} + $1 == "yes" {wifi_status = $2 ":" $3 "%"} + END {print wifi_status} + ' diff --git a/bin/khatus_sensor_screen_brightness b/bin/khatus_sensor_screen_brightness new file mode 100755 index 0000000..7628987 --- /dev/null +++ b/bin/khatus_sensor_screen_brightness @@ -0,0 +1,10 @@ +#! /bin/sh + +set -e + +screen_brightness_device_path="$1" +# TODO: single cat +echo "\ + $(cat $screen_brightness_device_path/max_brightness) \ + $(cat $screen_brightness_device_path/brightness)\ +" diff --git a/bin/khatus_sensor_temperature b/bin/khatus_sensor_temperature new file mode 100755 index 0000000..6f9bd23 --- /dev/null +++ b/bin/khatus_sensor_temperature @@ -0,0 +1,7 @@ +#! /bin/sh + +set -e + +thermal_zone="$1" + +cat "/sys/class/thermal/thermal_zone${thermal_zone}/temp" diff --git a/bin/khatus_sensor_volume b/bin/khatus_sensor_volume new file mode 100755 index 0000000..ec09274 --- /dev/null +++ b/bin/khatus_sensor_volume @@ -0,0 +1,24 @@ +#! /bin/sh + +set -e + +pactl list sinks \ +| awk ' + /^\tMute:/ { + printf("%s,", $0); + } + /^\tVolume:/ { + for (i=2; i<=NF; i++) printf(" %s", $i); + }' \ +| awk -v RS=',' ' + /^[ \t]*Mute:/ {mute = $2} + /^[ \t]*front-left:/ {left = $4} + /^[ \t]*front-right:/ {right = $4} + END { + if (mute == "yes") { + print("x") + } else { + print("%s %s\n", left, right) + } + } + ' diff --git a/bin/khatus_sensor_weather b/bin/khatus_sensor_weather new file mode 100755 index 0000000..340175d --- /dev/null +++ b/bin/khatus_sensor_weather @@ -0,0 +1,24 @@ +#! /bin/sh + +set -e + +weather_station_id="$1" + +metar -d "$weather_station_id" 2>&1 \ +| awk ' + /METAR pattern not found in NOAA data/ { + failures++ + } + + /^Temperature/ { + celsius = $3; + fahrenheit = (celsius * (9 / 5)) + 32; + temperature = fahrenheit + } + + END { + if (failures > 0) { + temperature = "--" + } + print temperature "°F" + }' -- 2.20.1