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