Split workers into dedicated files
authorSiraaj Khandkar <siraaj@khandkar.net>
Tue, 31 Jul 2018 16:55:16 +0000 (12:55 -0400)
committerSiraaj Khandkar <siraaj@khandkar.net>
Tue, 31 Jul 2018 16:56:51 +0000 (12:56 -0400)
19 files changed:
bin/khatus
bin/khatus_controller [new file with mode: 0755]
bin/khatus_sensor_bar_req [new file with mode: 0755]
bin/khatus_sensor_bluetooth_power [new file with mode: 0755]
bin/khatus_sensor_datetime [new file with mode: 0755]
bin/khatus_sensor_disk_io [new file with mode: 0755]
bin/khatus_sensor_disk_space [new file with mode: 0755]
bin/khatus_sensor_energy [new file with mode: 0755]
bin/khatus_sensor_fan [new file with mode: 0755]
bin/khatus_sensor_loadavg [new file with mode: 0755]
bin/khatus_sensor_memory [new file with mode: 0755]
bin/khatus_sensor_mpd_song [new file with mode: 0755]
bin/khatus_sensor_mpd_state [new file with mode: 0755]
bin/khatus_sensor_net_addr_io [new file with mode: 0755]
bin/khatus_sensor_net_wifi_status [new file with mode: 0755]
bin/khatus_sensor_screen_brightness [new file with mode: 0755]
bin/khatus_sensor_temperature [new file with mode: 0755]
bin/khatus_sensor_volume [new file with mode: 0755]
bin/khatus_sensor_weather [new file with mode: 0755]

index d29755d..129ecf7 100755 (executable)
 
 set -e
 
-produce_energy() {
-    upower -e \
-    | grep battery \
-    | xargs upower -i \
-    | awk '
-        /^ +percentage: +/ { percentage=$2 }
-        /^ +state: +/      { state=$2 }
-        END                { print(state, percentage) }
-        '
-}
-
-
-produce_memory() {
-    free | awk '$1 == "Mem:" {print $2, $3}'
-}
-
-produce_fan() {
-    fan_path="$1"
-    cat "$fan_path"
-}
-
-produce_temperature() {
-    thermal_zone="$1"
-    cat "/sys/class/thermal/thermal_zone${thermal_zone}/temp"
-}
-
-produce_loadavg() {
-    cat /proc/loadavg
-}
-
-produce_disk_io() {
-    disk_io_device="$1"
-    awk '
-        {
-            r = $3
-            w = $7
-            print w, r
-        }
-        ' "/sys/block/$disk_io_device/stat"
-}
-
-produce_disk_space() {
-    disk_space_device="$1"
-    df --output=pcent "$disk_space_device" | awk 'NR == 2 {print $1}'
-}
-
-produce_net_addr_io() {
-    ip -s addr \
-    | awk '
-        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"]
-                    print(interface, addrs[interface], curr_write, curr_read)
-                } else {
-                    print(interface)
-                }
-            }
-        }'
-}
-
-produce_net_wifi_status() {
-    nmcli \
-        -f ACTIVE,SSID,SIGNAL \
-        -t \
-        d wifi \
-    | awk \
-        -F ':' \
-        '
-        BEGIN       {wifi_status = "--"}
-        $1 == "yes" {wifi_status =  $2 ":" $3 "%"}
-        END         {print wifi_status}
-        '
-}
-
-produce_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\n", power_status);
-        }'
-}
-
-produce_screen_brightness() {
-    screen_brightness_device_path="$1"
-    echo "\
-        $(cat $screen_brightness_device_path/max_brightness) \
-        $(cat $screen_brightness_device_path/brightness)\
-    "
-}
-
-produce_volume() {
-    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") {
-                print("x")
-            } else {
-                print("%s %s\n", left, right)
-            }
-        }
-        '
-}
-
-produce_mpd_state() {
-    echo 'status' \
-    | nc 127.0.0.1 6600 \
-    | awk '
-        {
-            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 = "~"
-            }
-        }
-
-        END {
-            state = status["state:"]
-
-            if (state == "play") {
-                symbol = "▶"
-            } else if (state == "pause") {
-                symbol = "❚❚"
-            } else if (state == "stop") {
-                symbol = "⬛"
-            } else {
-                symbol = "--"
-            }
-
-            printf(\
-                "%s %s %s\n",
-                status["state:"], current_time, current_percentage\
-            )
-        }
-        '
-}
-
-produce_mpd_song() {
-    echo 'currentsong' \
-    | nc 127.0.0.1 6600 \
-    | awk '
-        /^OK/ {
-            next
-        }
-
-        {
-            key = $1
-            sub("^" key " +", "")
-            val = $0
-            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 = ""
-            }
-            print out
-        }
-        '
-}
-
-produce_weather() {
-    weather_station_id="$1"
-    metar -d "$weather_station_id" 2>&1 \
-    | awk '
-        /METAR pattern not found in NOAA data/ {
-            failures++
-        }
-
-        /^Temperature/ {
-            celsius = $3;
-            fahrenheit = (celsius * (9 / 5)) + 32;
-            temperature = fahrenheit
-        }
-
-        END {
-            if (failures > 0) {
-                temperature = "--"
-            }
-            print temperature "°F"
-        }'
-}
-
-produce_datetime() {
-    date +'%a %b %d %H:%M:%S'
-}
-
 consume() {
     pipe="$1"
     debug="$2"
-    prefixes_of_net_interfaces_to_show="$3"
+    dir_bin="$3"
+    prefixes_of_net_interfaces_to_show="$4"
     tail -f "$pipe" \
-    | stdbuf -o L awk \
+    | stdbuf -o L "$dir_bin"/khatus_controller \
         -v opt_debug="$debug" \
         -v opt_mpd_song_max_chars=10 \
-        -v opt_prefixes_of_net_interfaces_to_show="$prefixes_of_net_interfaces_to_show" \
-        '
-            /^in:ENERGY/\
-            {
-                split_msg_parts()
-                db["energy_state"]      = $1
-                db["energy_percentage"] = $2
-            }
-
-            /^in:MEMORY/\
-            {
-                split_msg_parts()
-                db["memory_total"] = $1
-                db["memory_used"]  = $2
-            }
-
-            /^in:FAN +status:/\
-            {
-                split_msg_parts()
-                db["fan_status"] = $2
-            }
-
-            /^in:FAN +speed:/\
-            {
-                split_msg_parts()
-                db["fan_speed"] = $2
-            }
-
-            /^in:FAN +level:/\
-            {
-                split_msg_parts()
-                db["fan_level"] = $2
-            }
-
-            /^in:TEMPERATURE/\
-            {
-                split_msg_parts()
-                db["temperature"] = $1
-            }
-
-            /^in:LOAD_AVG/\
-            {
-                split_msg_parts()
-                set_load_avg()
-            }
-
-            /^in:DISK_IO/\
-            {
-                split_msg_parts()
-                set_disk_io()
-            }
-
-            /^in:DISK_SPACE/\
-            {
-                split_msg_parts()
-                db["disk_space_used"] = msg_body
-            }
-
-            /^in:NET_ADDR_IO/\
-            {
-                split_msg_parts()
-                set_net_addr_io()
-            }
-
-            /^in:NET_WIFI_STATUS/\
-            {
-                split_msg_parts()
-                db["net_wifi_status"] = msg_body
-            }
-
-            /^in:BLUETOOTH_POWER/\
-            {
-                split_msg_parts()
-                db["bluetooth_power"] = msg_body
-            }
-
-            /^in:SCREEN_BRIGHTNESS/\
-            {
-                split_msg_parts()
-                set_screen_brightness()
-            }
-
-            /^in:VOLUME/\
-            {
-                split_msg_parts()
-                db["volume"] = msg_body
-            }
-
-            /^in:MPD_STATE/\
-            {
-                split_msg_parts()
-                db["mpd_state"]             = $1
-                db["mpd_curr_song_time"]    = $2
-                db["mpd_curr_song_percent"] = $3
-            }
-
-            /^in:MPD_SONG/\
-            {
-                split_msg_parts()
-                db["mpd_curr_song_name"] = msg_body
-            }
-
-            /^in:WEATHER/\
-            {
-                split_msg_parts()
-                db["weather_temperature"] = msg_body
-            }
-
-            /^in:DATE_TIME/\
-            {
-                split_msg_parts()
-                db["datetime"] = msg_body
-            }
-
-            /^out:BAR/\
-            {
-                split_msg_parts()
-                print make_bar()
-            }
-
-            function set_load_avg(    sched) {
-                split($4, sched, "/")
-                db["load_avg_1min"]             = $1
-                db["load_avg_5min"]             = $2
-                db["load_avg_15min"]            = $3
-                db["kern_sched_queue_runnable"] = sched[1]
-                db["kern_sched_queue_total"]    = sched[2]
-                db["kern_sched_latest_pid"]     = $5
-            }
-
-            function set_disk_io(    curr_w, curr_r, prev_w, prev_r) {
-                curr_w = $1
-                curr_r = $2
-                prev_w = db["disk_io_curr_w"]
-                prev_r = db["disk_io_curr_r"]
-                db["disk_io_curr_w"] = curr_w
-                db["disk_io_curr_r"] = curr_r
-                db["disk_io_diff_w"] = curr_w - prev_w
-                db["disk_io_diff_r"] = curr_r - prev_r
-            }
-
-            function set_net_addr_io(    \
-                interface, address, io_curr_w, io_curr_r, io_prev_w, io_prev_r\
-            ) {
-                interface = $1
-                address   = $2
-                io_curr_w = $3
-                io_curr_r = $4
-                if (interface) {
-                    if (address && io_curr_w && io_curr_r) {
-                        # recalculate
-                        io_prev_w = net_io_curr_w[interface]
-                        io_prev_r = net_io_curr_r[interface]
-
-                        net_addr[interface]      = address
-                        net_io_curr_w[interface] = io_curr_w
-                        net_io_curr_r[interface] = io_curr_r
-                        net_io_diff_w[interface] = io_curr_w - io_prev_w
-                        net_io_diff_r[interface] = io_curr_r - io_prev_r
-                    } else {
-                        # clear
-                        net_addr[interface]      = ""
-                        net_io_curr_w[interface] = 0
-                        net_io_curr_r[interface] = 0
-                        net_io_diff_w[interface] = 0
-                        net_io_diff_r[interface] = 0
-                    }
-                }
-            }
-
-            function set_screen_brightness(    max, cur) {
-                max = $1
-                cur = $2
-                db["screen_brightness"] = (cur / max) * 100
-            }
-
-            function split_msg_parts() {
-                msg_head = $1
-                sub("^" msg_head " +", "")
-                msg_body = $0
-                debug(msg_head, msg_body)
-            }
-
-            function make_bar(    position, bar, sep, i, j) {
-                position[++i] = make_status_energy()
-                position[++i] = make_status_mem()
-                position[++i] = make_status_cpu()
-                position[++i] = make_status_disk()
-                position[++i] = make_status_net()
-                position[++i] = sprintf("B=%s", db["bluetooth_power"])
-                position[++i] = sprintf("*%d%%", db["screen_brightness"])
-                position[++i] = sprintf("(%s)", db["volume"])
-                position[++i] = make_status_mpd()
-                position[++i] = db["weather_temperature"]
-                position[++i] = db["datetime"]
-                bar = ""
-                sep = ""
-                for (j = 1; j <= i; j++) {
-                    bar = bar sep position[j]
-                    sep = " "
-                }
-                return bar
-            }
-
-            function make_status_energy(    state, direction_of_change) {
-                state = db["energy_state"]
-                if (state == "discharging") {
-                    direction_of_change = "<"
-                } else if (state == "charging") {
-                    direction_of_change = ">"
-                } else {
-                    direction_of_change = "="
-                };
-                printf("E%s%s", direction_of_change, db["energy_percentage"])
-            }
-
-            function make_status_mem(    total, used, percent, status) {
-                total = db["memory_total"]
-                used  = db["memory_used"]
-                # To avoid division by zero when data is missing
-                if (total && used) {
-                    percent = round((used / total) * 100)
-                    status = sprintf("%d%%", percent)
-                } else {
-                    status = "__"
-                }
-                return sprintf("M=%s", status)
-            }
-
-            function make_status_cpu(    load, temp, fan) {
-                load = db["load_avg_1min"]
-                temp = db["temperature"] / 1000
-                fan  = db["fan_speed"]
-                return sprintf("C=[%4.2f %d°C %4drpm]", load, temp, fan)
-            }
-
-            function make_status_disk(    bytes_per_sector, bytes_per_mb, w, r) {
-                bytes_per_sector = 512
-                bytes_per_mb     = 1024 * 1024
-                w = (db["disk_io_diff_w"] * bytes_per_sector) / bytes_per_mb
-                r = (db["disk_io_diff_r"] * bytes_per_sector) / bytes_per_mb
-                return \
-                    sprintf("D=[%s %0.3f▲ %0.3f▼]", db["disk_space_used"], w, r)
-            }
-
-            function make_status_net(    \
-                out,
-                number_of_interfaces_to_show,
-                n,
-                array_of_prefixes_of_interfaces_to_show,
-                prefix,
-                interface,
-                label,
-                count_printed,
-                sep,
-                io_stat,
-                dw, dr,
-                bytes_per_unit\
-            ) {
-                out = ""
-                number_of_interfaces_to_show = \
-                    split(\
-                        opt_prefixes_of_net_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]
-                    for (interface in net_addr) {
-                        if (interface ~ ("^" prefix)) {
-                            label = substr(interface, 1, 1)
-                            if (net_addr[interface]) {
-                                bytes_per_mb = 1024 * 1024  # TODO: option
-                                dw = net_io_diff_w[interface] / bytes_per_mb
-                                dr = net_io_diff_r[interface] / bytes_per_mb
-                                io_stat = sprintf("%0.3f▲ %0.3f▼", dw, dr)
-                            } else {
-                                io_stat = "--"
-                            }
-                            if (interface ~ "^w") {
-                                label = label ":" db["net_wifi_status"]
-                            }
-                            if (++count_printed > 1) {
-                                sep = "  "
-                            } else {
-                                sep = ""
-                            }
-                            out = out sep label ":" io_stat
-                        }
-                    }
-                }
-                return sprintf("N[%s]", out)
-            }
-
-            function make_status_mpd(    state, status) {
-                state = db["mpd_state"]
-
-                if (state == "play") {
-                    status = make_status_mpd_state_known("▶")
-                } else if (state == "pause") {
-                    status = make_status_mpd_state_known("❚❚")
-                } else if (state == "stop") {
-                    status = make_status_mpd_state_known("⬛")
-                } else {
-                    status = make_status_mpd_state_unknown("--")
-                }
-
-                return sprintf("[%s]", status)
-            }
-
-            function make_status_mpd_state_known(symbol) {
-                return sprintf(\
-                    "%s %s %s %s",
-                    symbol,
-                    db["mpd_curr_song_time"],
-                    db["mpd_curr_song_percent"],
-                    substr(db["mpd_curr_song_name"], 1, opt_mpd_song_max_chars)\
-                )
-            }
-
-            function make_status_mpd_state_unknown(symbol) {
-                return sprintf("%s", symbol)
-            }
-
-            function round(n) {
-                return int(n + 0.5)
-            }
-
-            function debug(location, msg) {
-                if (opt_debug) {
-                    print_error(location, msg)
-                }
-            }
-
-            function print_error(location, msg) {
-                print(location " ==> " msg) > "/dev/stderr"
-            }
-        '
-}
-
-produce_bar_req() {
-    echo ''
+        -v opt_prefixes_of_net_interfaces_to_show="$prefixes_of_net_interfaces_to_show"
 }
 
 spawn() {
-    cmd="$1"
-    pipe="$2"
-    msg_head="$3"
-    interval="$4"
+    pipe="$1"
+    dir_bin="$2"
+    cmd="$3"
+    msg_head="$4"
+    interval="$5"
     while true; do
-        $cmd | while read line; do
+        "$dir_bin"/$cmd | while read line; do
             echo "${msg_head} $line" > "$pipe"
         done
         sleep "$interval"
@@ -653,6 +31,7 @@ spawn() {
 main() {
     # Defaults
     debug=0
+    dir_bin="$HOME/bin"
     dir_data=$(mktemp -d)
     weather_station_id='KJFK'
     screen_brightness_device_name='acpi_video0'
@@ -683,6 +62,7 @@ main() {
     # User-overrides
     long_options=''
     long_options+='debug'
+    long_options+=',bin_dir:'
     long_options+=',data_dir:'
     long_options+=',weather_station:'
     long_options+=',screen_device:'
@@ -722,6 +102,10 @@ main() {
                 debug=1
                 shift
                 ;;
+            --bin_dir)
+                dir_bin="$2"
+                shift 2
+                ;;
             --data_dir)
                 dir_data="$2"
                 shift 2
@@ -835,6 +219,7 @@ main() {
 
     ( echo "Khatus starting with the following parameters:"
       ( echo "    debug|= $debug"
+        echo "    dir_bin|= $dir_bin"
         echo "    dir_data|= $dir_data"
         echo "    pipe|= $pipe"
         echo "    screen_brightness_device_name|= $screen_brightness_device_name"
@@ -853,41 +238,42 @@ main() {
     rm -f "$pipe"
     mkfifo "$pipe"
 
-    cmd_produce_screen_brightness='produce_screen_brightness'
-    cmd_produce_screen_brightness+=" $screen_brightness_device_path"
+    cmd_sens_screen_brightness='khatus_sensor_screen_brightness'
+    cmd_sens_screen_brightness+=" $screen_brightness_device_path"
 
-    cmd_produce_weather="produce_weather $weather_station_id"
+    cmd_sens_weather="khatus_sensor_weather $weather_station_id"
 
-    cmd_produce_disk_space="produce_disk_space $disk_space_device"
+    cmd_sens_disk_space="khatus_sensor_disk_space $disk_space_device"
 
-    cmd_produce_disk_io="produce_disk_io $disk_io_device"
+    cmd_sens_disk_io="khatus_sensor_disk_io $disk_io_device"
 
-    cmd_produce_temperature="produce_temperature $thermal_zone"
+    cmd_sens_temperature="khatus_sensor_temperature $thermal_zone"
 
-    cmd_produce_fan="produce_fan $fan_path"
+    cmd_sens_fan="khatus_sensor_fan $fan_path"
 
     # TODO: Redirect each worker's stderr to a dedicated log file
-    spawn produce_datetime                 "$pipe" 'in:DATE_TIME' $interval_inp_datetime
-    spawn "$cmd_produce_screen_brightness" "$pipe" 'in:SCREEN_BRIGHTNESS' $interval_inp_brightness
-    spawn "$cmd_produce_weather"           "$pipe" 'in:WEATHER' $interval_inp_weather
-    spawn produce_mpd_state                "$pipe" 'in:MPD_STATE' $interval_inp_mpd_state
-    spawn produce_mpd_song                 "$pipe" 'in:MPD_SONG' $interval_inp_mpd_song
-    spawn produce_volume                   "$pipe" 'in:VOLUME' $interval_inp_volume
-    spawn produce_bluetooth_power          "$pipe" 'in:BLUETOOTH_POWER' $interval_inp_bluetooth
-    spawn produce_net_wifi_status          "$pipe" 'in:NET_WIFI_STATUS' $interval_inp_net_wifi
-    spawn produce_net_addr_io              "$pipe" 'in:NET_ADDR_IO' $interval_inp_net_io
-    spawn "$cmd_produce_disk_space"        "$pipe" 'in:DISK_SPACE' $interval_inp_disk_space
-    spawn "$cmd_produce_disk_io"           "$pipe" 'in:DISK_IO' $interval_inp_disk_io
-    spawn produce_loadavg                  "$pipe" 'in:LOAD_AVG' $interval_inp_loadavg
-    spawn "$cmd_produce_temperature"       "$pipe" 'in:TEMPERATURE' $interval_inp_temp
-    spawn "$cmd_produce_fan"               "$pipe" 'in:FAN' $interval_inp_fan
-    spawn produce_memory                   "$pipe" 'in:MEMORY' $interval_inp_mem
-    spawn produce_energy                   "$pipe" 'in:ENERGY' $interval_inp_energy
-    spawn produce_bar_req                  "$pipe" 'out:BAR' $interval_outp_bar
+    spawn "$pipe" "$dir_bin" khatus_sensor_datetime        'in:DATE_TIME'         $interval_inp_datetime
+    spawn "$pipe" "$dir_bin" "$cmd_sens_screen_brightness" 'in:SCREEN_BRIGHTNESS' $interval_inp_brightness
+    spawn "$pipe" "$dir_bin" "$cmd_sens_weather"           'in:WEATHER'           $interval_inp_weather
+    spawn "$pipe" "$dir_bin" khatus_sensor_mpd_state       'in:MPD_STATE'         $interval_inp_mpd_state
+    spawn "$pipe" "$dir_bin" khatus_sensor_mpd_song        'in:MPD_SONG'          $interval_inp_mpd_song
+    spawn "$pipe" "$dir_bin" khatus_sensor_volume          'in:VOLUME'            $interval_inp_volume
+    spawn "$pipe" "$dir_bin" khatus_sensor_bluetooth_power 'in:BLUETOOTH_POWER'   $interval_inp_bluetooth
+    spawn "$pipe" "$dir_bin" khatus_sensor_net_wifi_status 'in:NET_WIFI_STATUS'   $interval_inp_net_wifi
+    spawn "$pipe" "$dir_bin" khatus_sensor_net_addr_io     'in:NET_ADDR_IO'       $interval_inp_net_io
+    spawn "$pipe" "$dir_bin" "$cmd_sens_disk_space"        'in:DISK_SPACE'        $interval_inp_disk_space
+    spawn "$pipe" "$dir_bin" "$cmd_sens_disk_io"           'in:DISK_IO'           $interval_inp_disk_io
+    spawn "$pipe" "$dir_bin" khatus_sensor_loadavg         'in:LOAD_AVG'          $interval_inp_loadavg
+    spawn "$pipe" "$dir_bin" "$cmd_sens_temperature"       'in:TEMPERATURE'       $interval_inp_temp
+    spawn "$pipe" "$dir_bin" "$cmd_sens_fan"               'in:FAN'               $interval_inp_fan
+    spawn "$pipe" "$dir_bin" khatus_sensor_memory          'in:MEMORY'            $interval_inp_mem
+    spawn "$pipe" "$dir_bin" khatus_sensor_energy          'in:ENERGY'            $interval_inp_energy
+    spawn "$pipe" "$dir_bin" khatus_sensor_bar_req         'out:BAR'              $interval_outp_bar
 
     consume \
       "$pipe" \
       "$debug" \
+      "$dir_bin" \
       "$prefixes_of_net_interfaces_to_show"
 }
 
diff --git a/bin/khatus_controller b/bin/khatus_controller
new file mode 100755 (executable)
index 0000000..e6954a2
--- /dev/null
@@ -0,0 +1,337 @@
+#! /usr/bin/awk -f
+
+/^in:ENERGY/\
+{
+    split_msg_parts()
+    db["energy_state"]      = $1
+    db["energy_percentage"] = $2
+}
+
+/^in:MEMORY/\
+{
+    split_msg_parts()
+    db["memory_total"] = $1
+    db["memory_used"]  = $2
+}
+
+/^in:FAN +status:/\
+{
+    split_msg_parts()
+    db["fan_status"] = $2
+}
+
+/^in:FAN +speed:/\
+{
+    split_msg_parts()
+    db["fan_speed"] = $2
+}
+
+/^in:FAN +level:/\
+{
+    split_msg_parts()
+    db["fan_level"] = $2
+}
+
+/^in:TEMPERATURE/\
+{
+    split_msg_parts()
+    db["temperature"] = $1
+}
+
+/^in:LOAD_AVG/\
+{
+    split_msg_parts()
+    set_load_avg()
+}
+
+/^in:DISK_IO/\
+{
+    split_msg_parts()
+    set_disk_io()
+}
+
+/^in:DISK_SPACE/\
+{
+    split_msg_parts()
+    db["disk_space_used"] = msg_body
+}
+
+/^in:NET_ADDR_IO/\
+{
+    split_msg_parts()
+    set_net_addr_io()
+}
+
+/^in:NET_WIFI_STATUS/\
+{
+    split_msg_parts()
+    db["net_wifi_status"] = msg_body
+}
+
+/^in:BLUETOOTH_POWER/\
+{
+    split_msg_parts()
+    db["bluetooth_power"] = msg_body
+}
+
+/^in:SCREEN_BRIGHTNESS/\
+{
+    split_msg_parts()
+    set_screen_brightness()
+}
+
+/^in:VOLUME/\
+{
+    split_msg_parts()
+    db["volume"] = msg_body
+}
+
+/^in:MPD_STATE/\
+{
+    split_msg_parts()
+    db["mpd_state"]             = $1
+    db["mpd_curr_song_time"]    = $2
+    db["mpd_curr_song_percent"] = $3
+}
+
+/^in:MPD_SONG/\
+{
+    split_msg_parts()
+    db["mpd_curr_song_name"] = msg_body
+}
+
+/^in:WEATHER/\
+{
+    split_msg_parts()
+    db["weather_temperature"] = msg_body
+}
+
+/^in:DATE_TIME/\
+{
+    split_msg_parts()
+    db["datetime"] = msg_body
+}
+
+/^out:BAR/\
+{
+    split_msg_parts()
+    print make_bar()
+}
+
+function set_load_avg(    sched) {
+    split($4, sched, "/")
+    db["load_avg_1min"]             = $1
+    db["load_avg_5min"]             = $2
+    db["load_avg_15min"]            = $3
+    db["kern_sched_queue_runnable"] = sched[1]
+    db["kern_sched_queue_total"]    = sched[2]
+    db["kern_sched_latest_pid"]     = $5
+}
+
+function set_disk_io(    curr_w, curr_r, prev_w, prev_r) {
+    curr_w = $1
+    curr_r = $2
+    prev_w = db["disk_io_curr_w"]
+    prev_r = db["disk_io_curr_r"]
+    db["disk_io_curr_w"] = curr_w
+    db["disk_io_curr_r"] = curr_r
+    db["disk_io_diff_w"] = curr_w - prev_w
+    db["disk_io_diff_r"] = curr_r - prev_r
+}
+
+function set_net_addr_io(    \
+    interface, address, io_curr_w, io_curr_r, io_prev_w, io_prev_r\
+) {
+    interface = $1
+    address   = $2
+    io_curr_w = $3
+    io_curr_r = $4
+    if (interface) {
+        if (address && io_curr_w && io_curr_r) {
+            # recalculate
+            io_prev_w = net_io_curr_w[interface]
+            io_prev_r = net_io_curr_r[interface]
+
+            net_addr[interface]      = address
+            net_io_curr_w[interface] = io_curr_w
+            net_io_curr_r[interface] = io_curr_r
+            net_io_diff_w[interface] = io_curr_w - io_prev_w
+            net_io_diff_r[interface] = io_curr_r - io_prev_r
+        } else {
+            # clear
+            net_addr[interface]      = ""
+            net_io_curr_w[interface] = 0
+            net_io_curr_r[interface] = 0
+            net_io_diff_w[interface] = 0
+            net_io_diff_r[interface] = 0
+        }
+    }
+}
+
+function set_screen_brightness(    max, cur) {
+    max = $1
+    cur = $2
+    db["screen_brightness"] = (cur / max) * 100
+}
+
+function split_msg_parts() {
+    msg_head = $1
+    sub("^" msg_head " +", "")
+    msg_body = $0
+    debug(msg_head, msg_body)
+}
+
+function make_bar(    position, bar, sep, i, j) {
+    position[++i] = make_status_energy()
+    position[++i] = make_status_mem()
+    position[++i] = make_status_cpu()
+    position[++i] = make_status_disk()
+    position[++i] = make_status_net()
+    position[++i] = sprintf("B=%s", db["bluetooth_power"])
+    position[++i] = sprintf("*%d%%", db["screen_brightness"])
+    position[++i] = sprintf("(%s)", db["volume"])
+    position[++i] = make_status_mpd()
+    position[++i] = db["weather_temperature"]
+    position[++i] = db["datetime"]
+    bar = ""
+    sep = ""
+    for (j = 1; j <= i; j++) {
+        bar = bar sep position[j]
+        sep = " "
+    }
+    return bar
+}
+
+function make_status_energy(    state, direction_of_change) {
+    state = db["energy_state"]
+    if (state == "discharging") {
+        direction_of_change = "<"
+    } else if (state == "charging") {
+        direction_of_change = ">"
+    } else {
+        direction_of_change = "="
+    };
+    printf("E%s%s", direction_of_change, db["energy_percentage"])
+}
+
+function make_status_mem(    total, used, percent, status) {
+    total = db["memory_total"]
+    used  = db["memory_used"]
+    # To avoid division by zero when data is missing
+    if (total && used) {
+        percent = round((used / total) * 100)
+        status = sprintf("%d%%", percent)
+    } else {
+        status = "__"
+    }
+    return sprintf("M=%s", status)
+}
+
+function make_status_cpu(    load, temp, fan) {
+    load = db["load_avg_1min"]
+    temp = db["temperature"] / 1000
+    fan  = db["fan_speed"]
+    return sprintf("C=[%4.2f %d°C %4drpm]", load, temp, fan)
+}
+
+function make_status_disk(    bytes_per_sector, bytes_per_mb, w, r) {
+    bytes_per_sector = 512
+    bytes_per_mb     = 1024 * 1024
+    w = (db["disk_io_diff_w"] * bytes_per_sector) / bytes_per_mb
+    r = (db["disk_io_diff_r"] * bytes_per_sector) / bytes_per_mb
+    return \
+        sprintf("D=[%s %0.3f▲ %0.3f▼]", db["disk_space_used"], w, r)
+}
+
+function make_status_net(    \
+    out,
+    number_of_interfaces_to_show,
+    n,
+    array_of_prefixes_of_interfaces_to_show,
+    prefix,
+    interface,
+    label,
+    count_printed,
+    sep,
+    io_stat,
+    dw, dr,
+    bytes_per_unit\
+) {
+    out = ""
+    number_of_interfaces_to_show = \
+        split(\
+            opt_prefixes_of_net_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]
+        for (interface in net_addr) {
+            if (interface ~ ("^" prefix)) {
+                label = substr(interface, 1, 1)
+                if (net_addr[interface]) {
+                    bytes_per_mb = 1024 * 1024  # TODO: option
+                    dw = net_io_diff_w[interface] / bytes_per_mb
+                    dr = net_io_diff_r[interface] / bytes_per_mb
+                    io_stat = sprintf("%0.3f▲ %0.3f▼", dw, dr)
+                } else {
+                    io_stat = "--"
+                }
+                if (interface ~ "^w") {
+                    label = label ":" db["net_wifi_status"]
+                }
+                if (++count_printed > 1) {
+                    sep = "  "
+                } else {
+                    sep = ""
+                }
+                out = out sep label ":" io_stat
+            }
+        }
+    }
+    return sprintf("N[%s]", out)
+}
+
+function make_status_mpd(    state, status) {
+    state = db["mpd_state"]
+
+    if (state == "play") {
+        status = make_status_mpd_state_known("▶")
+    } else if (state == "pause") {
+        status = make_status_mpd_state_known("❚❚")
+    } else if (state == "stop") {
+        status = make_status_mpd_state_known("⬛")
+    } else {
+        status = make_status_mpd_state_unknown("--")
+    }
+
+    return sprintf("[%s]", status)
+}
+
+function make_status_mpd_state_known(symbol) {
+    return sprintf(\
+        "%s %s %s %s",
+        symbol,
+        db["mpd_curr_song_time"],
+        db["mpd_curr_song_percent"],
+        substr(db["mpd_curr_song_name"], 1, opt_mpd_song_max_chars)\
+    )
+}
+
+function make_status_mpd_state_unknown(symbol) {
+    return sprintf("%s", symbol)
+}
+
+function round(n) {
+    return int(n + 0.5)
+}
+
+function debug(location, msg) {
+    if (opt_debug) {
+        print_error(location, msg)
+    }
+}
+
+function print_error(location, msg) {
+    print(location " ==> " msg) > "/dev/stderr"
+}
diff --git a/bin/khatus_sensor_bar_req b/bin/khatus_sensor_bar_req
new file mode 100755 (executable)
index 0000000..d4fb1c1
--- /dev/null
@@ -0,0 +1,3 @@
+#! /bin/sh
+
+echo ''
diff --git a/bin/khatus_sensor_bluetooth_power b/bin/khatus_sensor_bluetooth_power
new file mode 100755 (executable)
index 0000000..92c2128
--- /dev/null
@@ -0,0 +1,37 @@
+#! /bin/sh
+
+set -e
+
+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\n", power_status);
+    }'
diff --git a/bin/khatus_sensor_datetime b/bin/khatus_sensor_datetime
new file mode 100755 (executable)
index 0000000..ee1da65
--- /dev/null
@@ -0,0 +1,3 @@
+#! /bin/sh
+
+date +'%a %b %d %H:%M:%S'
diff --git a/bin/khatus_sensor_disk_io b/bin/khatus_sensor_disk_io
new file mode 100755 (executable)
index 0000000..379bcb3
--- /dev/null
@@ -0,0 +1,14 @@
+#! /bin/sh
+
+set -e
+
+disk_io_device="$1"
+
+awk '
+    {
+        r = $3
+        w = $7
+        print w, r
+    }
+    ' \
+    "/sys/block/$disk_io_device/stat"
diff --git a/bin/khatus_sensor_disk_space b/bin/khatus_sensor_disk_space
new file mode 100755 (executable)
index 0000000..b0f00e6
--- /dev/null
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+set -e
+
+disk_space_device="$1"
+
+df --output=pcent "$disk_space_device" | awk 'NR == 2 {print $1}'
diff --git a/bin/khatus_sensor_energy b/bin/khatus_sensor_energy
new file mode 100755 (executable)
index 0000000..f91155f
--- /dev/null
@@ -0,0 +1,12 @@
+#! /bin/sh
+
+set -e
+
+upower -e \
+| grep battery \
+| xargs upower -i \
+| awk '
+    /^ +percentage: +/ { percentage=$2 }
+    /^ +state: +/      { state=$2 }
+    END                { print(state, percentage) }
+    '
diff --git a/bin/khatus_sensor_fan b/bin/khatus_sensor_fan
new file mode 100755 (executable)
index 0000000..12db7b6
--- /dev/null
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+set -e
+
+fan_path="$1"
+
+cat "$fan_path"
diff --git a/bin/khatus_sensor_loadavg b/bin/khatus_sensor_loadavg
new file mode 100755 (executable)
index 0000000..283d032
--- /dev/null
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+set -e
+
+cat /proc/loadavg
diff --git a/bin/khatus_sensor_memory b/bin/khatus_sensor_memory
new file mode 100755 (executable)
index 0000000..0b79722
--- /dev/null
@@ -0,0 +1,5 @@
+#! /bin/sh
+
+set -e
+
+free | awk '$1 == "Mem:" {print $2, $3}'
diff --git a/bin/khatus_sensor_mpd_song b/bin/khatus_sensor_mpd_song
new file mode 100755 (executable)
index 0000000..49f7f15
--- /dev/null
@@ -0,0 +1,36 @@
+#! /bin/sh
+
+set -e
+
+echo 'currentsong' \
+| nc 127.0.0.1 6600 \
+| awk '
+    /^OK/ {
+        next
+    }
+
+    {
+        key = $1
+        sub("^" key " +", "")
+        val = $0
+        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 = ""
+        }
+        print out
+    }
+    '
diff --git a/bin/khatus_sensor_mpd_state b/bin/khatus_sensor_mpd_state
new file mode 100755 (executable)
index 0000000..b5c9b08
--- /dev/null
@@ -0,0 +1,53 @@
+#! /bin/sh
+
+set -e
+
+echo 'status' \
+| nc 127.0.0.1 6600 \
+| awk '
+    {
+        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 = "~"
+        }
+    }
+
+    END {
+        state = status["state:"]
+
+        if (state == "play") {
+            symbol = "▶"
+        } else if (state == "pause") {
+            symbol = "❚❚"
+        } else if (state == "stop") {
+            symbol = "⬛"
+        } else {
+            symbol = "--"
+        }
+
+        printf(\
+            "%s %s %s\n",
+            status["state:"], current_time, current_percentage\
+        )
+    }
+    '
diff --git a/bin/khatus_sensor_net_addr_io b/bin/khatus_sensor_net_addr_io
new file mode 100755 (executable)
index 0000000..48b9b07
--- /dev/null
@@ -0,0 +1,40 @@
+#! /bin/sh
+
+set -e
+
+ip -s addr \
+| awk '
+    /^[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"]
+                print(interface, addrs[interface], curr_write, curr_read)
+            } else {
+                print(interface)
+            }
+        }
+    }'
diff --git a/bin/khatus_sensor_net_wifi_status b/bin/khatus_sensor_net_wifi_status
new file mode 100755 (executable)
index 0000000..de7fd58
--- /dev/null
@@ -0,0 +1,15 @@
+#! /bin/sh
+
+set -e
+
+nmcli \
+    -f ACTIVE,SSID,SIGNAL \
+    -t \
+    d wifi \
+| awk \
+    -F ':' \
+    '
+    BEGIN       {wifi_status = "--"}
+    $1 == "yes" {wifi_status =  $2 ":" $3 "%"}
+    END         {print wifi_status}
+    '
diff --git a/bin/khatus_sensor_screen_brightness b/bin/khatus_sensor_screen_brightness
new file mode 100755 (executable)
index 0000000..7628987
--- /dev/null
@@ -0,0 +1,10 @@
+#! /bin/sh
+
+set -e
+
+screen_brightness_device_path="$1"
+# TODO: single cat
+echo "\
+    $(cat $screen_brightness_device_path/max_brightness) \
+    $(cat $screen_brightness_device_path/brightness)\
+"
diff --git a/bin/khatus_sensor_temperature b/bin/khatus_sensor_temperature
new file mode 100755 (executable)
index 0000000..6f9bd23
--- /dev/null
@@ -0,0 +1,7 @@
+#! /bin/sh
+
+set -e
+
+thermal_zone="$1"
+
+cat "/sys/class/thermal/thermal_zone${thermal_zone}/temp"
diff --git a/bin/khatus_sensor_volume b/bin/khatus_sensor_volume
new file mode 100755 (executable)
index 0000000..ec09274
--- /dev/null
@@ -0,0 +1,24 @@
+#! /bin/sh
+
+set -e
+
+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") {
+            print("x")
+        } else {
+            print("%s %s\n", left, right)
+        }
+    }
+    '
diff --git a/bin/khatus_sensor_weather b/bin/khatus_sensor_weather
new file mode 100755 (executable)
index 0000000..340175d
--- /dev/null
@@ -0,0 +1,24 @@
+#! /bin/sh
+
+set -e
+
+weather_station_id="$1"
+
+metar -d "$weather_station_id" 2>&1 \
+| awk '
+    /METAR pattern not found in NOAA data/ {
+        failures++
+    }
+
+    /^Temperature/ {
+        celsius = $3;
+        fahrenheit = (celsius * (9 / 5)) + 32;
+        temperature = fahrenheit
+    }
+
+    END {
+        if (failures > 0) {
+            temperature = "--"
+        }
+        print temperature "°F"
+    }'
This page took 0.070884 seconds and 4 git commands to generate.