Take prefixes of net interfaces from CLI options
[khatus.git] / bin / khatus_show
CommitLineData
756b9d5a
SK
1#! /bin/bash
2
3set -e
4
5BIN=$HOME/bin
6STATUS_DIR=$HOME/var/run/status
7STATUS_FILE__WIFI=$STATUS_DIR/wifi
8STATUS_FILE__ENERGY_NOTIFIED_BELLOW_HALF=$STATUS_DIR/notified_energy_bellow_half
7e990898 9while getopts ":b:d:s:i:" opt
ea734d22
SK
10do
11 case "$opt" in
12 b)
13 SCREEN_BRIGHTNESS_DEVICE_NAME="$OPTARG"
14 ;;
15 d)
16 DISK_IO_DEVICE="$OPTARG"
17 ;;
18 s)
19 DISK_SPACE_DEVICE="$OPTARG"
20 ;;
7e990898
SK
21 i)
22 PREFIXES_OF_INTERFACES_TO_SHOW="$OPTARG"
23 ;;
ea734d22
SK
24 \?)
25 echo "Unknown option: $OPTARG" >&2
26 exit 1
27 ;;
28 :)
29 echo "Missing argument for option: $OPTARG" >&2
30 exit 1
31 ;;
32 esac
33done
34if [ "$SCREEN_BRIGHTNESS_DEVICE_NAME" == '' ]; then echo 'Missing -b' >&2; exit 1; fi
35if [ "$DISK_IO_DEVICE" == '' ]; then echo 'Missing -d' >&2; exit 1; fi
36if [ "$DISK_SPACE_DEVICE" == '' ]; then echo 'Missing -s' >&2; exit 1; fi
e002d85b 37SCREEN_BRIGHTNESS_DEVICE_PATH="/sys/class/backlight/$SCREEN_BRIGHTNESS_DEVICE_NAME"
14df51f3 38
756b9d5a 39
14dc912f 40load=$(awk '{printf("%4.2f", $1)}' /proc/loadavg)
756b9d5a
SK
41
42fan=$(awk '/^speed:/ {printf "%4d", $2}' /proc/acpi/ibm/fan)
43
2d2c9b54 44#cpu=$($BIN/khatus_cpu_usage_from_proc_since_last_check)
756b9d5a
SK
45
46memory=$(
47 free \
48 | awk '
49 function round(n) {return int(n + 0.5)}
50
51 $1 == "Mem:" {
52 total=$2;
53 used=$3;
54 cache=$6;
e2664fda 55 prev_file = ENVIRON["HOME"] "/var/run/status/memory_used_percentage";
756b9d5a 56 curr = round(used / total * 100);
bd61022d
SK
57 getline prev < prev_file;
58 print curr > prev_file;
756b9d5a
SK
59 if (curr > prev) {
60 direction = ">";
61 } else if (curr < prev) {
62 direction = "<";
63 } else {
64 direction = "=";
65 }
66 printf("%s%d%%", direction, curr);
67 }')
68
69temp=$(awk 'NR == 1 {print $1 / 1000}' /sys/class/thermal/thermal_zone0/temp)
70
0da41dc2
SK
71disk_io=$(
72 awk '
73 {
74 bytes_per_sector = 512
75 bytes_per_unit = 1024 * 1024
76
77 curr_sectors_read = $3
78 curr_sectors_write = $7
79
e2664fda 80 prev_file_prefix = ENVIRON["HOME"] "/var/run/status/disk_io"
0da41dc2
SK
81 prev_sectors_read_file = prev_file_prefix "_sectors_read"
82 prev_sectors_write_file = prev_file_prefix "_sectors_write"
83
84 getline prev_sectors_read < prev_sectors_read_file
85 getline prev_sectors_write < prev_sectors_write_file
86
87 diff_read_sectors = (curr_sectors_read - prev_sectors_read)
88 diff_write_sectors = (curr_sectors_write - prev_sectors_write)
89
90 diff_read_bytes = diff_read_sectors * bytes_per_sector
91 diff_write_bytes = diff_write_sectors * bytes_per_sector
92
93 diff_read = diff_read_bytes / bytes_per_unit
94 diff_write = diff_write_bytes / bytes_per_unit
95
96 print curr_sectors_read > prev_sectors_read_file
97 print curr_sectors_write > prev_sectors_write_file
98
99 printf("%0.3f▲ %0.3f▼\n", diff_write, diff_read);
100
101 }
14df51f3 102 ' "/sys/block/$DISK_IO_DEVICE/stat"
0da41dc2
SK
103)
104
756b9d5a
SK
105disk=$(
106 df \
14df51f3
SK
107 | awk \
108 -v disk_io="$disk_io" \
109 -v device="$DISK_SPACE_DEVICE" \
110 '
756b9d5a
SK
111 function round(n) {return int(n + 0.5)}
112
14df51f3 113 $1 == device {
0ca0fd63 114 curr_perc = $5; sub("%$", "", curr_perc);
e2664fda 115 prev_perc_file = ENVIRON["HOME"] "/var/run/status/disk_space_used";
0ca0fd63 116 getline prev_perc < prev_perc_file;
0ca0fd63
SK
117 print curr_perc > prev_perc_file;
118 if (curr_perc > prev_perc) {
756b9d5a 119 direction = ">";
0ca0fd63 120 } else if (curr_perc < prev_perc) {
756b9d5a
SK
121 direction = "<";
122 } else {
123 direction = "=";
124 }
0da41dc2 125 printf("%s[%d%% %s]", direction, curr_perc, disk_io);
756b9d5a
SK
126 }')
127
628e9cfa 128# TODO: Wi-Fi status file should be a file per-wifi-device
6b2a0f95 129network=$(
7f9bd752 130 ip -s addr \
628e9cfa
SK
131 | awk \
132 -v wifi_conn="$(cat $STATUS_FILE__WIFI)" \
7e990898 133 -v prefixes_of_interfaces_to_show="$PREFIXES_OF_INTERFACES_TO_SHOW" \
628e9cfa 134 '
f32c814f 135 BEGIN {
5d65d6cb 136 bytes_per_unit = 1024 * 1024
f32c814f
SK
137 }
138
37d619ee 139 /^[0-9]+:/ {
7f9bd752
SK
140 sub(":$", "", $1)
141 sub(":$", "", $2)
142 sequence = $1
143 interface = $2
144 interfaces[sequence] = interface
62bb00b2
SK
145 }
146
7f9bd752
SK
147 /^ +inet [0-9]/ {
148 sub("/[0-9]+", "", $2)
149 addr = $2
150 addrs[interface] = addr
62bb00b2
SK
151 }
152
7f9bd752
SK
153 /^ +RX: / {transfer_direction = "r"}
154 /^ +TX: / {transfer_direction = "w"}
155
156 /^ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ *$/ {
157 io[interface, transfer_direction] = $1;
6b2a0f95
SK
158 }
159
160 END {
628e9cfa
SK
161 for (seq=1; seq<=sequence; seq++) {
162 interface = interfaces[seq]
2d2c9b54 163 label = substr(interface, 1, 1)
7f9bd752
SK
164 if (addrs[interface]) {
165 curr_read = io[interface, "r"]
166 curr_write = io[interface, "w"]
167
e2664fda 168 prefix = ENVIRON["HOME"] "/var/run/status/io_net_" interface
7f9bd752
SK
169 prev_read_file = prefix "_read"
170 prev_write_file = prefix "_write"
171
172 getline prev_read < prev_read_file
173 getline prev_write < prev_write_file
174
37d619ee
SK
175 diff_read = (curr_read - prev_read ) / bytes_per_unit
176 diff_written = (curr_write - prev_write) / bytes_per_unit
7f9bd752
SK
177
178 print curr_read > prev_read_file
179 print curr_write > prev_write_file
180
37d619ee 181 io_stat = sprintf("%0.3f▲ %0.3f▼", diff_written, diff_read)
628e9cfa 182 if (interface ~ "^w") {
2d2c9b54
SK
183 label = label ":" wifi_conn
184 }
37d619ee
SK
185 } else {
186 io_stat = "--"
187 }
628e9cfa
SK
188 number_of_interfaces_to_show = \
189 split(\
190 prefixes_of_interfaces_to_show,\
191 array_of_prefixes_of_interfaces_to_show,\
192 " +"\
193 )
194 for (n = 1; n <= number_of_interfaces_to_show; n++) {
195 prefix = array_of_prefixes_of_interfaces_to_show[n]
196 if (interface ~ ("^" prefix)) {
197 if (++count_printed > 1) {
198 sep = " "
199 } else {
200 sep = ""
201 }
202 printf("%s%s:%s", sep, label, io_stat)
2d2c9b54 203 }
62bb00b2 204 }
1ca0626b 205 }
7f9bd752 206 }'
f32c814f
SK
207)
208
756b9d5a
SK
209energy=$(
210 upower -e \
211 | grep battery \
212 | xargs upower -i \
213 | awk '
214 /^ +percentage: +/ {percentage=$2}
215 /^ +state: +/ {state=$2}
216 END {
217 if (state == "discharging") {
218 direction_of_change = "<"
219 } else if (state == "charging") {
220 direction_of_change = ">"
221 } else {
222 direction_of_change = "="
223 };
224 printf("%s%s", direction_of_change, percentage)
225 }')
226
2d2c9b54
SK
227datetime=$(date +'%a %b %d %H:%M:%S')
228#datetime=$(
229# date +'%a %u %b %d %H:%M:%S' \
230# | awk '
231# {
232# wday_name = $1
233# wday_seq = $2
234# month = $3
235# mday = $4
236# time = $5
237#
238# week = ""
239# for (i=1; i<=7; i++) {
240# if (i == 6 || i == 4) {
241# sep = " "
242# } else {
243# sep = ""
244# }
245#
246# if (i == wday_seq) {
247# #symbol = substr(wday_name, 1, 1)
248# symbol = "/"
249# } else if (i < wday_seq){
250# symbol = "X"
251# } else {
252# symbol = "_"
253# }
254# week = week sep symbol
255# }
256#
257# print "["week"]", month, mday, time;
258# }
259# '
260#)
756b9d5a
SK
261
262#volume_amixer=$(
263# amixer get Master \
264# | tail -1 \
265# | awk '
266# {
267# level = $4;
268# sub("^\\[", "", level);
269# sub("\\]$", "", level);
270# print level;
271# }' \
272# )
273
274#volume_amixer=$(
275# amixer get Master \
276# | tail -n 1 \
277# | awk '{print $4}' \
278# | tr -d '[]'
279#)
280
281volume_pactl=$(
282 pactl list sinks \
283 | awk '
284 /^\tMute:/ {
285 printf("%s,", $0);
286 }
287 /^\tVolume:/ {
288 for (i=2; i<=NF; i++) printf(" %s", $i);
289 }' \
290 | awk -v RS=',' '
291 /^[ \t]*Mute:/ {mute = $2}
292 /^[ \t]*front-left:/ {left = $4}
293 /^[ \t]*front-right:/ {right = $4}
294 END {
295 if (mute == "yes") {
296 printf("x")
297 } else {
298 printf("%s %s", left, right)
299 }
300 }
301 '
302)
303
2d2c9b54 304volume="($volume_pactl)"
756b9d5a 305
756b9d5a 306screen_brightness=$(
e002d85b
SK
307 echo -n $((
308 $(cat $SCREEN_BRIGHTNESS_DEVICE_PATH/brightness)
309 / $(cat $SCREEN_BRIGHTNESS_DEVICE_PATH/max_brightness)
310 * 100
311 ))
756b9d5a
SK
312)
313
314#bluetooth_status=$(
315# grep '^status:' /proc/acpi/ibm/bluetooth \
316# | awk '
317# $2 == "disabled" {printf "off"}
318# $2 == "enabled" {printf "on"}
319# '
320#)
321
322bluetooth_power=$(
323 echo -e 'show \n quit' \
324 | bluetoothctl \
325 | awk '
326 /^Controller / {
327 controller = $2;
328 controllers[++ctrl_count] = controller;
329 }
330 /^\t[A-Z][A-Za-z]+:/ {
331 key = $1;
332 sub(":$", "", key);
333 val = $2;
334 for (i=3; i<=NF; i++) {
335 val = val " " $i};
336 data[controller, key] = val;
337 }
338 END {
339 # Using the 1st seen controller. Should we select specific instead?
340 power_status = data[controllers[1], "Powered"];
341 if (ctrl_count > 0) {
342 if (power_status == "no") {
343 power_status = "off"
344 } else if (power_status == "yes") {
345 power_status = "on"
346 } else {
347 printf("Unexpected bluetooth power status: %s\n", power_status)\
348 > "/dev/stderr";
349 power_status = "ERROR"
350 }
351 } else {
352 power_status = "off" # TODO: Perhaps use differentiated marker?
353 }
354 printf("%s", power_status);
355 }'
356)
357
358#touchpad_status=$(
359# xinput list-props 12 \
360# | awk '
361# /^\tDevice Enabled \([0-9]+\):/ {
362# status = $4;
363# printf("%s", status);
364# }'
365#)
366
367#color_off='\033[0m'
368#color_on_bg_gray='\033[m\033[40m'
369
370energy_direction=$(echo "$energy" | cut -b 1)
371energy_percentage=$(echo "$energy" | tr -d '<>=%')
372if [[ "$energy_direction" = '<' ]]
373then
374 if [[ $energy_percentage -le 5 ]]
375 then
376 DISPLAY=:0.0 notify-send \
377 -u critical \
378 "Energy CRITICALLY low: $energy" \
379 'CHARGE NOW!!! GO GO GO!!!'
380 elif [[ $energy_percentage -le 10 ]]
381 then
382 DISPLAY=:0.0 notify-send \
383 -u critical \
384 "Energy VERY low: $energy" \
385 'Plug it in ASAP.'
386 elif [[ $energy_percentage -le 15 ]]
387 then
388 DISPLAY=:0.0 notify-send \
389 -u critical \
390 "Energy low: $energy" \
391 'Get the charger.'
392 elif [[ $energy_percentage -le 50 ]]
393 then
394 if [[ ! -a "$STATUS_FILE__ENERGY_NOTIFIED_BELLOW_HALF" ]]
395 then
396 DISPLAY=:0.0 notify-send \
397 -u normal \
398 "Energy bellow half: $energy" \
399 'Where is the charger?'
400 touch "$STATUS_FILE__ENERGY_NOTIFIED_BELLOW_HALF"
401 fi
402 fi
403else
404 rm -f "$STATUS_FILE__ENERGY_NOTIFIED_BELLOW_HALF"
405fi
406
2d2c9b54 407weather=$(awk 'NR == 1 {printf("%s°F", $1)}' ~/var/run/metar-KJFK-decoded-temp-fahrenheit)
756b9d5a 408
97ce66c2
SK
409#signal_last_msg_age=$(
410# ls -lt --time-style=+%s $HOME/var/lib/signal/latest_message.json \
411# | awk -v now_seconds=$(date +%s) \
412# '{
413# mtime_seconds = $6;
414# seconds = now_seconds - mtime_seconds;
415# minutes = seconds / 60;
416# hours = minutes / 60;
417# days = hours / 24;
418# weeks = days / 7;
419# months = days / 30;
420# #fmt = "%.1f";
421# fmt = "%d";
422# printf(fmt " s\n", seconds);
423# printf(fmt " m\n", minutes);
424# printf(fmt " h\n", hours);
425# printf(fmt " d\n", days);
426# printf(fmt " w\n", weeks);
427# printf(fmt " mo\n", months);
428# }' \
429# | awk '$1 >= 1' \
430# | sort -n -k 1 \
431# | head -1 \
432# | tr -d ' '
433#)
756b9d5a 434
2d2c9b54 435mpd_currentsong=$(
94fb2cd7
SK
436 echo 'currentsong' \
437 | nc 127.0.0.1 6600 \
438 | awk -v max_chars=10 '
a6f61387
SK
439 /^OK/ {
440 next
441 }
442
443 {
444 key = $1
445 val = $2
446 for (i=3; i<=NF; i++) {val = val " " $i}
447 data[key] = val
448 }
449
450 END {
2d2c9b54
SK
451 name = data["Name:"]
452 title = data["Title:"]
453 file = data["file:"]
454
455 if (name) {
456 out = name
457 } else if (title) {
458 out = title
459 } else if (file) {
a6f61387
SK
460 last = split(file, parts, "/")
461 out = parts[last]
2d2c9b54
SK
462 } else {
463 out = ""
a6f61387 464 }
2d2c9b54 465
a6f61387 466 printf("%s", substr(out, 1, max_chars))
94fb2cd7
SK
467 }
468 '
469)
470
2d2c9b54
SK
471mpd_state=$(
472 echo 'status' \
473 | nc 127.0.0.1 6600 \
474 | awk \
475 -v current_song="$mpd_currentsong" \
476 '
78fe905a 477 {
2d2c9b54
SK
478 status[$1] = $2
479 }
480
481 /^time: +[0-9]+:[0-9]+$/ {
482 split($2, time, ":")
483 seconds_current = time[1]
484 seconds_total = time[2]
485
486 hours = int(seconds_current / 60 / 60);
487 secs_beyond_hours = seconds_current - (hours * 60 * 60);
488 mins = int(secs_beyond_hours / 60);
489 secs = secs_beyond_hours - (mins * 60);
490 if (hours > 0) {
491 current_time = sprintf("%d:%.2d:%.2d", hours, mins, secs)
492 } else {
493 current_time = sprintf("%.2d:%.2d", mins, secs)
494 }
495
496 if (seconds_total > 0) {
497 time_percentage = (seconds_current / seconds_total) * 100
498 current_percentage = sprintf("%d%%", time_percentage)
499 } else {
500 current_percentage = "~"
501 }
502 }
503
504 function print_known_state(symbol) {
505 printf(\
506 "%s %s %s %s",
507 symbol, current_time, current_percentage, current_song \
508 )
509 }
510
511 function print_unknown_state(symbol) {
512 printf("%s", symbol)
513 }
514
515 END {
516 state = status["state:"]
517
518 if (state == "play") {
519 print_known_state("▶")
520 } else if (state == "pause") {
521 print_known_state("❚❚")
522 } else if (state == "stop") {
523 print_known_state("⬛")
524 } else {
525 print_unknown_state("--")
526 }
78fe905a
SK
527 }
528 '
529)
530
2d2c9b54
SK
531#graphics_card=$(
532 #nvidia-smi \
533 #--format=csv,noheader,nounits \
534 #--query-gpu=memory.total,memory.used,temperature.gpu \
535 #| awk -F ',' '
536 #{
537 #mem_total = $1;
538 #mem_used = $2;
539 #temp = $3;
540 #mem_used_percent = (100 * mem_used) / mem_total;
541 #printf("[%d%% %dC]", mem_used_percent, temp);
542 #}
543 #'
544#)
545
756b9d5a
SK
546echo \
547"\
548 E$energy\
1b554fca 549 \
756b9d5a 550 M$memory\
1b554fca 551 \
2d2c9b54 552 C=[$load ${temp}°C ${fan}rpm]\
14dc912f 553 \
a8f74eda 554 D$disk\
1b554fca 555 \
7f9bd752 556 N:[$network]\
1b554fca 557 \
756b9d5a 558 B:$bluetooth_power\
1b554fca 559 \
e002d85b 560 *$screen_brightness%\
1b554fca 561 \
2d2c9b54 562 $volume\
a8f74eda 563 \
2d2c9b54 564 [$mpd_state]\
a8c81faf 565 \
756b9d5a
SK
566 $weather\
567 \
568 $datetime \
569"
This page took 0.099116 seconds and 4 git commands to generate.