5 produce_net_addr_io
() {
8 -v prefixes_of_interfaces_to_show
="$PREFIXES_OF_INTERFACES_TO_SHOW" \
11 bytes_per_unit = 1024 * 1024
19 interfaces[sequence] = interface
23 sub("/[0-9]+", "", $2)
25 addrs[interface] = addr
28 /^ +RX: / {transfer_direction = "r"}
29 /^ +TX: / {transfer_direction = "w"}
31 /^ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ +[0-9]+ *$/ {
32 io[interface, transfer_direction] = $1;
36 for (seq=1; seq<=sequence; seq++) {
37 interface = interfaces[seq]
38 label = substr(interface, 1, 1)
39 if (addrs[interface]) {
40 curr_read = io[interface, "r"]
41 curr_write = io[interface, "w"]
42 print(interface, addrs[interface], curr_write, curr_read)
50 produce_net_wifi_status
() {
52 -f ACTIVE
,SSID
,SIGNAL \
58 BEGIN {wifi_status = "--"}
59 $1 == "yes" {wifi_status = $2 ":" $3 "%"}
60 END {print wifi_status}
64 produce_bluetooth_power
() {
65 echo -e 'show \n quit' \
70 controllers[++ctrl_count] = controller;
72 /^\t[A-Z][A-Za-z]+:/ {
76 for (i=3; i<=NF; i++) {
78 data[controller, key] = val;
81 # Using the 1st seen controller. Should we select specific instead?
82 power_status = data[controllers[1], "Powered"];
84 if (power_status == "no") {
86 } else if (power_status == "yes") {
89 printf("Unexpected bluetooth power status: %s\n", power_status)\
91 power_status = "ERROR"
94 power_status = "off" # TODO: Perhaps use differentiated marker?
96 printf("%s", power_status);
100 produce_screen_brightness
() {
101 screen_brightness_device_path
="$1"
103 $(cat $screen_brightness_device_path/max_brightness) \
104 $(cat $screen_brightness_device_path/brightness)\
115 for (i=2; i<=NF; i++) printf(" %s", $i);
118 /^[ \t]*Mute:/ {mute = $2}
119 /^[ \t]*front-left:/ {left = $4}
120 /^[ \t]*front-right:/ {right = $4}
125 printf("%s %s", left, right)
131 produce_mpd_state
() {
133 | nc
127.0.0.1 6600 \
139 /^time: +[0-9]+:[0-9]+$/ {
141 seconds_current = time[1]
142 seconds_total = time[2]
144 hours = int(seconds_current / 60 / 60);
145 secs_beyond_hours = seconds_current - (hours * 60 * 60);
146 mins = int(secs_beyond_hours / 60);
147 secs = secs_beyond_hours - (mins * 60);
149 current_time = sprintf("%d:%.2d:%.2d", hours, mins, secs)
151 current_time = sprintf("%.2d:%.2d", mins, secs)
154 if (seconds_total > 0) {
155 time_percentage = (seconds_current / seconds_total) * 100
156 current_percentage = sprintf("%d%%", time_percentage)
158 current_percentage = "~"
163 state = status["state:"]
165 if (state == "play") {
167 } else if (state == "pause") {
169 } else if (state == "stop") {
177 status["state:"], current_time, current_percentage\
185 | nc
127.0.0.1 6600 \
193 sub("^" key " +", "")
200 title = data["Title:"]
208 last = split(file, parts, "/")
219 weather_station_id
="$1"
220 metar
-d "$weather_station_id" 2>&1 \
222 /METAR pattern not found in NOAA data/ {
228 fahrenheit = (celsius * (9 / 5)) + 32;
229 temperature = fahrenheit
236 print temperature "°F"
241 date +'%a %b %d %H:%M:%S'
247 prefixes_of_net_interfaces_to_show
="$3"
250 -v opt_debug
="$debug" \
251 -v opt_mpd_song_max_chars
=10 \
252 -v opt_prefixes_of_net_interfaces_to_show
="$prefixes_of_net_interfaces_to_show" \
260 /^in:NET_WIFI_STATUS/\
263 db["net_wifi_status"] = msg_body
266 /^in:BLUETOOTH_POWER/\
269 db["bluetooth_power"] = msg_body
272 /^in:SCREEN_BRIGHTNESS/\
275 set_screen_brightness()
281 db["volume"] = msg_body
288 db["mpd_curr_song_time"] = $2
289 db["mpd_curr_song_percent"] = $3
295 db["mpd_curr_song_name"] = msg_body
301 db["weather_temperature"] = msg_body
307 db["datetime"] = msg_body
317 function set_net_addr_io( \
318 interface, address, io_curr_w, io_curr_r, io_prev_w, io_prev_r\
325 if (address && io_curr_w && io_curr_r) {
327 io_prev_w = net_io_curr_w[interface]
328 io_prev_r = net_io_curr_r[interface]
330 net_addr[interface] = address
331 net_io_curr_w[interface] = io_curr_w
332 net_io_curr_r[interface] = io_curr_r
333 net_io_diff_w[interface] = io_curr_w - io_prev_w
334 net_io_diff_r[interface] = io_curr_r - io_prev_r
337 net_addr[interface] = ""
338 net_io_curr_w[interface] = 0
339 net_io_curr_r[interface] = 0
340 net_io_diff_w[interface] = 0
341 net_io_diff_r[interface] = 0
346 function set_screen_brightness( max, cur) {
349 db["screen_brightness"] = (cur / max) * 100
352 function split_msg_parts() {
354 sub("^" msg_head " +", "")
356 debug(msg_head, msg_body)
359 function make_bar( position, bar, sep, i, j) {
360 position[++i] = make_status_net()
361 position[++i] = sprintf("B=%s", db["bluetooth_power"])
362 position[++i] = sprintf("*%d%%", db["screen_brightness"])
363 position[++i] = sprintf("(%s)", db["volume"])
364 position[++i] = make_status_mpd()
365 position[++i] = db["weather_temperature"]
366 position[++i] = db["datetime"]
369 for (j = 1; j <= i; j++) {
370 bar = bar sep position[j]
376 function make_status_net( \
378 number_of_interfaces_to_show,
380 array_of_prefixes_of_interfaces_to_show,
391 number_of_interfaces_to_show = \
393 opt_prefixes_of_net_interfaces_to_show,\
394 array_of_prefixes_of_interfaces_to_show,\
397 for (n = 1; n <= number_of_interfaces_to_show; n++) {
398 prefix = array_of_prefixes_of_interfaces_to_show[n]
399 for (interface in net_addr) {
400 if (interface ~ ("^" prefix)) {
401 label = substr(interface, 1, 1)
402 if (net_addr[interface]) {
403 bytes_per_mb = 1024 * 1024 # TODO: option
404 dw = net_io_diff_w[interface] / bytes_per_mb
405 dr = net_io_diff_r[interface] / bytes_per_mb
406 io_stat = sprintf("%0.3f▲ %0.3f▼", dw, dr)
410 if (interface ~ "^w") {
411 label = label ":" db["net_wifi_status"]
413 if (++count_printed > 1) {
418 out = out sep label ":" io_stat
422 return sprintf("N[%s]", out)
425 function make_status_mpd( state, status) {
426 state = db["mpd_state"]
428 if (state == "play") {
429 status = make_status_mpd_state_known("▶")
430 } else if (state == "pause") {
431 status = make_status_mpd_state_known("❚❚")
432 } else if (state == "stop") {
433 status = make_status_mpd_state_known("⬛")
435 status = make_status_mpd_state_unknown("--")
438 return sprintf("[%s]", status)
441 function make_status_mpd_state_known(symbol) {
445 db["mpd_curr_song_time"],
446 db["mpd_curr_song_percent"],
447 substr(db["mpd_curr_song_name"], 1, opt_mpd_song_max_chars)\
451 function make_status_mpd_state_unknown(symbol) {
452 return sprintf("%s", symbol)
455 function debug(location, msg) {
457 print_error(location, msg)
461 function print_error(location, msg) {
462 print(location " ==> " msg) > "/dev/stderr"
477 $cmd |
while read line
; do
478 echo "${msg_head} $line" > "$pipe"
487 dir_data
="$HOME/.khatus"
488 weather_station_id
='KJFK'
489 screen_brightness_device_name
='acpi_video0'
490 prefixes_of_net_interfaces_to_show
='w' # comma-separated
494 long_options
+='debug'
495 long_options
+=',data-dir:'
496 long_options
+=',weather-station:'
497 long_options
+=',screen-device:'
498 long_options
+=',prefixes_of_net_interfaces_to_show:'
518 weather_station_id
="$2"
522 screen_brightness_device_name
="$2"
525 --prefixes_of_net_interfaces_to_show)
526 prefixes_of_net_interfaces_to_show
="$2"
536 pipe
="$dir_data/khatus_data_pipe"
537 screen_brightness_device_path
='/sys/class/backlight'
538 screen_brightness_device_path
+="/$screen_brightness_device_name"
540 ( echo "Khatus starting with the following parameters:"
541 ( echo " debug|= $debug"
542 echo " dir_data|= $dir_data"
544 echo " screen_brightness_device_name|= $screen_brightness_device_name"
545 echo " screen_brightness_device_path|= $screen_brightness_device_path"
546 echo " weather_station_id|= $weather_station_id"
547 echo " prefixes_of_net_interfaces_to_show|=$prefixes_of_net_interfaces_to_show"
556 cmd_produce_screen_brightness
='produce_screen_brightness'
557 cmd_produce_screen_brightness
+=" $screen_brightness_device_path"
559 cmd_produce_weather
="produce_weather $weather_station_id"
561 # TODO: Redirect each worker's stderr to a dedicated log file
562 spawn produce_datetime
"$pipe" 'in:DATE_TIME' 1
563 spawn
"$cmd_produce_screen_brightness" "$pipe" 'in:SCREEN_BRIGHTNESS' 1
564 spawn
"$cmd_produce_weather" "$pipe" 'in:WEATHER' $
(( 30 * 60 ))
565 spawn produce_mpd_state
"$pipe" 'in:MPD_STATE' 1
566 spawn produce_mpd_song
"$pipe" 'in:MPD_SONG' 1
567 spawn produce_volume
"$pipe" 'in:VOLUME' 1
568 spawn produce_bluetooth_power
"$pipe" 'in:BLUETOOTH_POWER' 5
569 spawn produce_net_wifi_status
"$pipe" 'in:NET_WIFI_STATUS' 5
570 spawn produce_net_addr_io
"$pipe" 'in:NET_ADDR_IO' 1
571 spawn produce_bar_req
"$pipe" 'out:BAR' 1
576 "$prefixes_of_net_interfaces_to_show"