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