From a4ecb5bc5f7e403bda61fe1e202a7a146933e2b2 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Thu, 17 Jan 2019 18:36:09 -0500 Subject: [PATCH] Bring back v1 from the dead --- ...hatus_cpu_usage_from_proc_since_last_check | 99 +++ v1/bin/khatus_show | 577 ++++++++++++++++++ v1/bin/khatus_update_network | 37 ++ v1/bin/khatus_update_weather | 35 ++ v1/install | 15 + 5 files changed, 763 insertions(+) create mode 100755 v1/bin/khatus_cpu_usage_from_proc_since_last_check create mode 100755 v1/bin/khatus_show create mode 100755 v1/bin/khatus_update_network create mode 100755 v1/bin/khatus_update_weather create mode 100755 v1/install diff --git a/v1/bin/khatus_cpu_usage_from_proc_since_last_check b/v1/bin/khatus_cpu_usage_from_proc_since_last_check new file mode 100755 index 0000000..e76d21d --- /dev/null +++ b/v1/bin/khatus_cpu_usage_from_proc_since_last_check @@ -0,0 +1,99 @@ +#! /bin/sh + +proc_stat_parse() { + proc_stat="$1" + n='[0-9]\+' + echo "$proc_stat" \ + | grep "^cpu$n $n $n $n $n $n $n $n $n $n $n$" \ + | awk ' + { + cpu = $1; + user = $2; + sys = $4; + idle = $5; + + total = user + sys + idle; + busy = user + sys; + + if (NR > 1) {printf " "}; + + out = sprintf("%s %d %d", cpu, total, busy); + #print out >> "cpu_usage_debug.txt"; + printf "%s", out; + } + END { + #print "" >> "cpu_usage_debug.txt"; + print ""; + } + ' +} + +calc_delta() { + for proc_stat in "$1" "$2"; do + proc_stat_parse "$proc_stat" + done \ + | awk ' + { + t = NR; + for (i = 1; i <= (NF - 2); i += 3) { + cpu_count[t]++; + cpu_id = $i; # For occasional debugging + total = $(i + 1); + busy = $(i + 2); + cpu[cpu_count[t], "total", t] = total; + cpu[cpu_count[t], "busy" , t] = busy; + } + } + + END { + for (c=1; c<=cpu_count[2]; c++) { + total_1 = cpu[c, "total", 1]; + total_2 = cpu[c, "total", 2]; + busy_1 = cpu[c, "busy" , 1]; + busy_2 = cpu[c, "busy" , 2]; + total_d = total_2 - total_1; + busy_d = busy_2 - busy_1; + percent_busy = (busy_d / total_d) * 100; + + #printf(\ + # "c: %d, total_1: %f total_2: %f, total_d: %f\n", + # c, total_1, total_2, total_d \ + #) >> "cpu_usage_debug.txt"; + #printf(\ + # "c: %d, busy_1: %f busy_2: %f, busy_d: %f\n", + # c, busy_1, busy_2, busy_d \ + #) >> "cpu_usage_debug.txt"; + #printf(\ + # "c: %d, percent_busy: %f\n", + # c, percent_busy \ + #) >> "cpu_usage_debug.txt"; + + if (c > 1) {printf " "}; + out = sprintf("%3.0f%%", percent_busy) + #printf "c: %d, out: %s\n", c, out >> "cpu_usage_debug.txt"; + printf "%s", out; + } + #print "" >> "cpu_usage_debug.txt"; + print ""; + } + ' +} + +main() { + last_proc_stat="$HOME/var/run/cpu_usage_from_proc_since_last_check/last_proc_stat" + + if [ ! -f "$last_proc_stat" ] + then + mkdir -p `dirname "$last_proc_stat"` + cat /proc/stat > "$last_proc_stat" + sleep 0.1 + fi + + previous=`cat $last_proc_stat`; + cat /proc/stat > "$last_proc_stat" + current=`cat $last_proc_stat`; + + calc_delta "$previous" "$current" +} + +main $@ diff --git a/v1/bin/khatus_show b/v1/bin/khatus_show new file mode 100755 index 0000000..5170492 --- /dev/null +++ b/v1/bin/khatus_show @@ -0,0 +1,577 @@ +#! /bin/bash + +set -e + +BIN=$HOME/bin +STATUS_DIR=$HOME/var/run/status +STATUS_FILE__WIFI=$STATUS_DIR/wifi +STATUS_FILE__ENERGY_NOTIFIED_BELLOW_HALF=$STATUS_DIR/notified_energy_bellow_half +while getopts ":b:d:s:i:w:" opt +do + case "$opt" in + b) + SCREEN_BRIGHTNESS_DEVICE_NAME="$OPTARG" + ;; + d) + DISK_IO_DEVICE="$OPTARG" + ;; + s) + DISK_SPACE_DEVICE="$OPTARG" + ;; + i) + PREFIXES_OF_INTERFACES_TO_SHOW="$OPTARG" + ;; + w) + WEATHER_STATION_ID="$OPTARG" + ;; + \?) + echo "Unknown option: $OPTARG" >&2 + exit 1 + ;; + :) + echo "Missing argument for option: $OPTARG" >&2 + exit 1 + ;; + esac +done +if [ "$SCREEN_BRIGHTNESS_DEVICE_NAME" == '' ]; then echo 'Missing -b' >&2; exit 1; fi +if [ "$DISK_IO_DEVICE" == '' ]; then echo 'Missing -d' >&2; exit 1; fi +if [ "$DISK_SPACE_DEVICE" == '' ]; then echo 'Missing -s' >&2; exit 1; fi +if [ "$WEATHER_STATION_ID" == '' ]; then echo 'Missing -w' >&2; exit 1; fi +SCREEN_BRIGHTNESS_DEVICE_PATH="/sys/class/backlight/$SCREEN_BRIGHTNESS_DEVICE_NAME" + + +load=$(awk '{printf("%4.2f", $1)}' /proc/loadavg) + +fan=$(awk '/^speed:/ {printf "%4d", $2}' /proc/acpi/ibm/fan) + +#cpu=$($BIN/khatus_cpu_usage_from_proc_since_last_check) + +memory=$( + free \ + | awk ' + function round(n) {return int(n + 0.5)} + + $1 == "Mem:" { + total=$2; + used=$3; + cache=$6; + prev_file = ENVIRON["HOME"] "/var/run/status/memory_used_percentage"; + curr = round(used / total * 100); + getline prev < prev_file; + print curr > prev_file; + if (curr > prev) { + direction = ">"; + } else if (curr < prev) { + direction = "<"; + } else { + direction = "="; + } + printf("%s%d%%", direction, curr); + }') + +temp=$(awk 'NR == 1 {print $1 / 1000}' /sys/class/thermal/thermal_zone0/temp) + +disk_io=$( + awk ' + { + bytes_per_sector = 512 + bytes_per_unit = 1024 * 1024 + + curr_sectors_read = $3 + curr_sectors_write = $7 + + prev_file_prefix = ENVIRON["HOME"] "/var/run/status/disk_io" + prev_sectors_read_file = prev_file_prefix "_sectors_read" + prev_sectors_write_file = prev_file_prefix "_sectors_write" + + getline prev_sectors_read < prev_sectors_read_file + getline prev_sectors_write < prev_sectors_write_file + + diff_read_sectors = (curr_sectors_read - prev_sectors_read) + diff_write_sectors = (curr_sectors_write - prev_sectors_write) + + diff_read_bytes = diff_read_sectors * bytes_per_sector + diff_write_bytes = diff_write_sectors * bytes_per_sector + + diff_read = diff_read_bytes / bytes_per_unit + diff_write = diff_write_bytes / bytes_per_unit + + print curr_sectors_read > prev_sectors_read_file + print curr_sectors_write > prev_sectors_write_file + + printf("%0.3f▲ %0.3f▼\n", diff_write, diff_read); + + } + ' "/sys/block/$DISK_IO_DEVICE/stat" +) + +disk=$( + df \ + | awk \ + -v disk_io="$disk_io" \ + -v device="$DISK_SPACE_DEVICE" \ + ' + function round(n) {return int(n + 0.5)} + + $1 == device { + curr_perc = $5; sub("%$", "", curr_perc); + prev_perc_file = ENVIRON["HOME"] "/var/run/status/disk_space_used"; + getline prev_perc < prev_perc_file; + print curr_perc > prev_perc_file; + if (curr_perc > prev_perc) { + direction = ">"; + } else if (curr_perc < prev_perc) { + direction = "<"; + } else { + direction = "="; + } + printf("%s[%d%% %s]", direction, curr_perc, disk_io); + }') + +# TODO: Wi-Fi status file should be a file per-wifi-device +network=$( + ip -s addr \ + | awk \ + -v wifi_conn="$(cat $STATUS_FILE__WIFI)" \ + -v prefixes_of_interfaces_to_show="$PREFIXES_OF_INTERFACES_TO_SHOW" \ + ' + 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"] + + prefix = ENVIRON["HOME"] "/var/run/status/io_net_" interface + prev_read_file = prefix "_read" + prev_write_file = prefix "_write" + + getline prev_read < prev_read_file + getline prev_write < prev_write_file + + diff_read = (curr_read - prev_read ) / bytes_per_unit + diff_written = (curr_write - prev_write) / bytes_per_unit + + print curr_read > prev_read_file + print curr_write > prev_write_file + + io_stat = sprintf("%0.3f▲ %0.3f▼", diff_written, diff_read) + if (interface ~ "^w") { + label = label ":" wifi_conn + } + } else { + io_stat = "--" + } + number_of_interfaces_to_show = \ + split(\ + prefixes_of_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] + if (interface ~ ("^" prefix)) { + if (++count_printed > 1) { + sep = " " + } else { + sep = "" + } + printf("%s%s:%s", sep, label, io_stat) + } + } + } + }' +) + +energy=$( + upower -e \ + | grep battery \ + | xargs upower -i \ + | awk ' + /^ +percentage: +/ {percentage=$2} + /^ +state: +/ {state=$2} + END { + if (state == "discharging") { + direction_of_change = "<" + } else if (state == "charging") { + direction_of_change = ">" + } else { + direction_of_change = "=" + }; + printf("%s%s", direction_of_change, percentage) + }') + +datetime=$(date +'%a %b %d %H:%M:%S') +#datetime=$( +# date +'%a %u %b %d %H:%M:%S' \ +# | awk ' +# { +# wday_name = $1 +# wday_seq = $2 +# month = $3 +# mday = $4 +# time = $5 +# +# week = "" +# for (i=1; i<=7; i++) { +# if (i == 6 || i == 4) { +# sep = " " +# } else { +# sep = "" +# } +# +# if (i == wday_seq) { +# #symbol = substr(wday_name, 1, 1) +# symbol = "/" +# } else if (i < wday_seq){ +# symbol = "X" +# } else { +# symbol = "_" +# } +# week = week sep symbol +# } +# +# print "["week"]", month, mday, time; +# } +# ' +#) + +#volume_amixer=$( +# amixer get Master \ +# | tail -1 \ +# | awk ' +# { +# level = $4; +# sub("^\\[", "", level); +# sub("\\]$", "", level); +# print level; +# }' \ +# ) + +#volume_amixer=$( +# amixer get Master \ +# | tail -n 1 \ +# | awk '{print $4}' \ +# | tr -d '[]' +#) + +volume_pactl=$( + 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") { + printf("x") + } else { + printf("%s %s", left, right) + } + } + ' +) + +volume="($volume_pactl)" + +screen_brightness=$( + echo -n $(( + $(cat $SCREEN_BRIGHTNESS_DEVICE_PATH/brightness) + / $(cat $SCREEN_BRIGHTNESS_DEVICE_PATH/max_brightness) + * 100 + )) +) + +#bluetooth_status=$( +# grep '^status:' /proc/acpi/ibm/bluetooth \ +# | awk ' +# $2 == "disabled" {printf "off"} +# $2 == "enabled" {printf "on"} +# ' +#) + +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", power_status); + }' +) + +#touchpad_status=$( +# xinput list-props 12 \ +# | awk ' +# /^\tDevice Enabled \([0-9]+\):/ { +# status = $4; +# printf("%s", status); +# }' +#) + +#color_off='\033[0m' +#color_on_bg_gray='\033[m\033[40m' + +energy_direction=$(echo "$energy" | cut -b 1) +energy_percentage=$(echo "$energy" | tr -d '<>=%') +if [[ "$energy_direction" = '<' ]] +then + if [[ $energy_percentage -le 5 ]] + then + DISPLAY=:0.0 notify-send \ + -u critical \ + "Energy CRITICALLY low: $energy" \ + 'CHARGE NOW!!! GO GO GO!!!' + elif [[ $energy_percentage -le 10 ]] + then + DISPLAY=:0.0 notify-send \ + -u critical \ + "Energy VERY low: $energy" \ + 'Plug it in ASAP.' + elif [[ $energy_percentage -le 15 ]] + then + DISPLAY=:0.0 notify-send \ + -u critical \ + "Energy low: $energy" \ + 'Get the charger.' + elif [[ $energy_percentage -le 50 ]] + then + if [[ ! -a "$STATUS_FILE__ENERGY_NOTIFIED_BELLOW_HALF" ]] + then + DISPLAY=:0.0 notify-send \ + -u normal \ + "Energy bellow half: $energy" \ + 'Where is the charger?' + touch "$STATUS_FILE__ENERGY_NOTIFIED_BELLOW_HALF" + fi + fi +else + rm -f "$STATUS_FILE__ENERGY_NOTIFIED_BELLOW_HALF" +fi + +weather=$( + awk \ + 'NR == 1 {printf("%s°F", $1)}' \ + "$HOME/var/run/metar-${WEATHER_STATION_ID}-decoded-temp-fahrenheit" +) + +#signal_last_msg_age=$( +# ls -lt --time-style=+%s $HOME/var/lib/signal/latest_message.json \ +# | awk -v now_seconds=$(date +%s) \ +# '{ +# mtime_seconds = $6; +# seconds = now_seconds - mtime_seconds; +# minutes = seconds / 60; +# hours = minutes / 60; +# days = hours / 24; +# weeks = days / 7; +# months = days / 30; +# #fmt = "%.1f"; +# fmt = "%d"; +# printf(fmt " s\n", seconds); +# printf(fmt " m\n", minutes); +# printf(fmt " h\n", hours); +# printf(fmt " d\n", days); +# printf(fmt " w\n", weeks); +# printf(fmt " mo\n", months); +# }' \ +# | awk '$1 >= 1' \ +# | sort -n -k 1 \ +# | head -1 \ +# | tr -d ' ' +#) + +mpd_currentsong=$( + echo 'currentsong' \ + | nc 127.0.0.1 6600 \ + | awk -v max_chars=10 ' + /^OK/ { + next + } + + { + key = $1 + val = $2 + for (i=3; i<=NF; i++) {val = val " " $i} + 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 = "" + } + + printf("%s", substr(out, 1, max_chars)) + } + ' +) + +mpd_state=$( + echo 'status' \ + | nc 127.0.0.1 6600 \ + | awk \ + -v current_song="$mpd_currentsong" \ + ' + { + 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 = "~" + } + } + + function print_known_state(symbol) { + printf(\ + "%s %s %s %s", + symbol, current_time, current_percentage, current_song \ + ) + } + + function print_unknown_state(symbol) { + printf("%s", symbol) + } + + END { + state = status["state:"] + + if (state == "play") { + print_known_state("▶") + } else if (state == "pause") { + print_known_state("❚❚") + } else if (state == "stop") { + print_known_state("⬛") + } else { + print_unknown_state("--") + } + } + ' +) + +#graphics_card=$( + #nvidia-smi \ + #--format=csv,noheader,nounits \ + #--query-gpu=memory.total,memory.used,temperature.gpu \ + #| awk -F ',' ' + #{ + #mem_total = $1; + #mem_used = $2; + #temp = $3; + #mem_used_percent = (100 * mem_used) / mem_total; + #printf("[%d%% %dC]", mem_used_percent, temp); + #} + #' +#) + +echo \ +"\ + E$energy\ + \ + M$memory\ + \ + C=[$load ${temp}°C ${fan}rpm]\ + \ + D$disk\ + \ + N:[$network]\ + \ + B:$bluetooth_power\ + \ + *$screen_brightness%\ + \ + $volume\ + \ + [$mpd_state]\ + \ + $weather\ + \ + $datetime \ +" diff --git a/v1/bin/khatus_update_network b/v1/bin/khatus_update_network new file mode 100755 index 0000000..f3b562f --- /dev/null +++ b/v1/bin/khatus_update_network @@ -0,0 +1,37 @@ +#! /bin/bash + +set -e + +#TERM=xterm-256color # To keep unicode charcters from BARS + +STATUS_DIR=$HOME/var/run/status +STATUS_FILE_WIFI=$STATUS_DIR/wifi +STATUS_FILE_ETH=$STATUS_DIR/eth + +mkdir -p $STATUS_DIR + +# nmcli d \ +# | awk \ +# -v file_wifi="$STATUS_FILE_WIFI" \ +# -v file_eth="$STATUS_FILE_ETH" \ +# ' +# $2 == "wifi" {wifi = $4} +# $2 == "ethernet" {eth=$4} +# END { +# print(wifi) > file_wifi; +# print(eth) > file_eth; +# } +# ' + +nmcli \ + -f ACTIVE,SSID,SIGNAL \ + -t \ + d wifi \ +| awk \ + -F ':' \ + -v file_wifi="$STATUS_FILE_WIFI" \ + ' + BEGIN {wifi_status = "--"} + $1 == "yes" {wifi_status = $2 ":" $3 "%"} + END {print wifi_status > file_wifi} + ' diff --git a/v1/bin/khatus_update_weather b/v1/bin/khatus_update_weather new file mode 100755 index 0000000..665ae07 --- /dev/null +++ b/v1/bin/khatus_update_weather @@ -0,0 +1,35 @@ +#! /bin/bash + +set -e + +STATION_ID="$1" # ICAO designator. e.g. KJFK, KBOS + +FILE_METAR_DECODED="$HOME/var/run/metar-${STATION_ID}-decoded" +FILE_TEMP_FAHRENHEIT="${FILE_METAR_DECODED}-temp-fahrenheit" +FILE_TEMP_CELSIUS="${FILE_METAR_DECODED}-temp-celsius" + +(metar -d "$STATION_ID" 2>&1) > $FILE_METAR_DECODED # TODO: Better error handling + +awk \ + -v file_fahrenheit="$FILE_TEMP_FAHRENHEIT" \ + -v file_celsius="$FILE_TEMP_CELSIUS" \ + ' + /METAR pattern not found in NOAA data/ { + failures++ + } + + /^Temperature/ { + celsius = $3; + fahrenheit = (celsius * (9 / 5)) + 32; + } + + END { + if (failures > 0) { + print "--" > file_fahrenheit + print "--" > file_celsius + } else { + print fahrenheit > file_fahrenheit + print celsius > file_celsius + } + }' \ + $FILE_METAR_DECODED diff --git a/v1/install b/v1/install new file mode 100755 index 0000000..44fa3fe --- /dev/null +++ b/v1/install @@ -0,0 +1,15 @@ +#! /bin/sh + +PREFIX="$HOME/bin" + +if [ $1 ] +then + PREFIX=$1 +fi + +cd bin + +for filename in * +do + ln -s "`pwd`/$filename" "$PREFIX/$filename" +done -- 2.20.1