5 # - global, builtin : ALLCAPS
6 # - global, public : Camel_Snake_Man_Bear_Pig
7 # - global, private : _snake_case_prefixed_underscore
10 # - global, public : snake_case
13 FS = msg_fs ? msg_fs
: "|"
14 OFS = msg_fs ? msg_fs
: "|"
15 Kfs = key_fs ? key_fs
: ":"
16 GC_Interval = GC_Interval ? GC_Interval
: 3600 # seconds
18 _total_to_diff
["khatus_sensor_net_addr_io", "bytes_read" ] =
1
19 _total_to_diff
["khatus_sensor_net_addr_io", "bytes_written" ] =
1
20 _total_to_diff
["khatus_sensor_disk_io" , "sectors_read" ] =
1
21 _total_to_diff
["khatus_sensor_disk_io" , "sectors_written"] =
1
25 # (x * bytes_per_sector) / bytes_per_mb = x * scaling_factor
26 # ==> scaling_factor = bytes_per_sector / bytes_per_mb
27 _bytes_per_sector =
512
28 _bytes_per_mb =
1024 * 1024
29 _scale
["khatus_sensor_disk_io", "sectors_written"] = _bytes_per_sector
/ _bytes_per_mb
30 _scale
["khatus_sensor_disk_io", "sectors_read" ] = _bytes_per_sector
/ _bytes_per_mb
33 # x / bytes_per_mb = x * scaling_factor
34 # ==> scaling_factor = 1 / bytes_per_mb
35 _scale
["khatus_sensor_net_addr_io", "bytes_written"] =
1 / _bytes_per_mb
36 _scale
["khatus_sensor_net_addr_io", "bytes_read" ] =
1 / _bytes_per_mb
39 # -----------------------------------------------------------------------------
41 # -----------------------------------------------------------------------------
47 $
2 ==
"khatus_sensor_datetime" {
48 # Code for make_status_bar definition is expected to be passed as an
49 # additional source file, using -f flag.
50 print_msg_ok
("status_bar", make_status_bar
())
53 # -----------------------------------------------------------------------------
55 # -----------------------------------------------------------------------------
57 function cache_update
( src
, key
, val
, len_line
, len_head
, len_val
, time
) {
60 # Not just using $4 for val - because an unstructured value (like name of a
61 # song) might contain a character identical to FS
63 len_head =
length($
1 FS $
2 FS $
3 FS)
64 len_val = len_line
- len_head
65 val =
substr($
0, len_head
+ 1, len_val
)
66 val = cache_maybe_total_to_diff
(src
, key
, val
)
67 val = cache_maybe_scale
(src
, key
, val
)
68 _cache
[src
, key
] = val
69 time = cache_get_time
()
70 _cache_mtime
[src
, key
] = time
71 if (time % GC_Interval ==
0) {
76 function cache_get
(result
, src
, key
, ttl
, time
, age
, is_expired
) {
77 time = cache_get_time
()
78 _cache_atime
[src
, key
] = time
79 age = time
- _cache_mtime
[src
, key
]
80 result
["is_expired"] = ttl
&& age
> ttl
# ttl = 0 => forever
81 result
["value"] = _cache
[src
, key
]
84 function cache_res_fmt_or_def
(result
, format
, default
) {
85 return result
["is_expired"] ? default
: sprintf(format
, result
["value"])
88 function cache_get_fmt_def
(src
, key
, ttl
, format
, default
, result
) {
89 default = default ? default
: "--"
90 cache_get
(result
, src
, key
, ttl
)
91 return cache_res_fmt_or_def
(result
, format
, default
)
94 function cache_get_time
( src
, key
, time
) {
95 src =
"khatus_sensor_datetime"
97 time = _cache
[src
, key
]
98 _cache_atime
[src
, key
] = time
102 function cache_gc
( src_and_key
, parts
, src
, key
, unused_for
) {
103 for (src_and_key in _cache
) {
104 split(src_and_key
, parts
, SUBSEP
)
107 val = _cache
[src
, key
]
108 unused_for = cache_get_time
() - _cache_atime
[src
, key
]
109 if (unused_for
> GC_Interval
) {
113 "Deleting unused data SRC=%s KEY=%s VAL=%s",
117 delete _cache
[src
, key
]
122 function cache_maybe_total_to_diff
(src
, key
, val
, key_parts
) {
123 split(key
, key_parts
, Kfs
)
124 if (_total_to_diff
[src
, key_parts
[1]]) {
125 _prev
[src
, key
] = _curr
[src
, key
]
126 _curr
[src
, key
] = val
127 return (_curr
[src
, key
] - _prev
[src
, key
])
133 function cache_maybe_scale
(src
, key
, val
, key_parts
) {
134 split(key
, key_parts
, Kfs
)
135 if ((src SUBSEP key_parts
[1]) in _scale
) {
136 return val
* _scale
[src
, key_parts
[1]]
142 # -----------------------------------------------------------------------------
144 # -----------------------------------------------------------------------------
146 function make_status_energy
( state
, charge
, direction_of_change
) {
147 cache_get
(state
, "khatus_sensor_energy", "battery_state" , 0)
148 cache_get
(charge
, "khatus_sensor_energy", "battery_percentage", 0)
150 if (state
["value"] ==
"discharging") {
151 direction_of_change =
"<"
152 } else if (state
["value"] ==
"charging") {
153 direction_of_change =
">"
155 direction_of_change =
"="
158 return sprintf("E%s%d%%", direction_of_change
, charge
["value"])
161 function make_status_mem
( total
, used
, percent
, status
) {
162 cache_get
(total
, "khatus_sensor_memory", "total", 5)
163 cache_get
(used
, "khatus_sensor_memory", "used" , 5)
164 # Checking total["value"] to avoid division by zero when data is missing
165 if (!total
["is_expired"] && \
166 !used
["is_expired"] && \
169 percent = round
((used
["value"] / total
["value"]) * 100)
170 status =
sprintf("%d%%", percent
)
174 return sprintf("M=%s", status
)
177 function make_status_procs
() {
179 # D uninterruptible sleep (usually IO)
180 # R running or runnable (on run queue)
181 # S interruptible sleep (waiting for an event to complete)
182 # T stopped by job control signal
183 # t stopped by debugger during the tracing
184 # W paging (not valid since the 2.6.xx kernel)
185 # X dead (should never be seen)
186 # Z defunct ("zombie") process, terminated but not reaped by its parent
188 # Additionally, not documented in ps man page:
191 src =
"khatus_sensor_procs"
192 all = cache_get_fmt_def
(src
, "total_procs" , 15, "%d")
193 r = cache_get_fmt_def
(src
, "total_per_state" Kfs
"R", 15, "%d", "0")
194 d = cache_get_fmt_def
(src
, "total_per_state" Kfs
"D", 15, "%d", "0")
195 t = cache_get_fmt_def
(src
, "total_per_state" Kfs
"T", 15, "%d", "0")
196 i = cache_get_fmt_def
(src
, "total_per_state" Kfs
"I", 15, "%d", "0")
197 z = cache_get_fmt_def
(src
, "total_per_state" Kfs
"Z", 15, "%d", "0")
198 return sprintf("P=[%s %sr %sd %st %si %sz]", all
, r
, d
, t
, i
, z
)
201 function make_status_cpu
( l
, t
, f
) {
202 l_src =
"khatus_sensor_loadavg"
203 t_src =
"khatus_sensor_temperature"
204 f_src =
"khatus_sensor_fan"
205 l = cache_get_fmt_def
(l_src
, "load_avg_1min", 5, "%4.2f")
206 t = cache_get_fmt_def
(t_src
, "temp_c" , 5, "%d" )
207 f = cache_get_fmt_def
(f_src
, "speed" , 5, "%4d" )
208 return sprintf("C=[%s %s°C %srpm]", l
, t
, f
)
211 function make_status_disk
( u
, w
, r
, src_u
, src_io
) {
212 src_u =
"khatus_sensor_disk_space"
213 src_io =
"khatus_sensor_disk_io"
214 u = cache_get_fmt_def
(src_u
, "disk_usage_percentage", 10, "%s")
215 w = cache_get_fmt_def
(src_io
, "sectors_written" , 5, "%0.3f")
216 r = cache_get_fmt_def
(src_io
, "sectors_read" , 5, "%0.3f")
217 return sprintf("D=[%s%% %s▲ %s▼]", u
, w
, r
)
220 function make_status_net
( \
221 number_of_net_interfaces_to_show
, \
222 net_interfaces_to_show
, \
236 number_of_net_interfaces_to_show = \
237 split(Opt_Net_Interfaces_To_Show
, net_interfaces_to_show
, ",")
238 io =
"khatus_sensor_net_addr_io"
239 wi =
"khatus_sensor_net_wifi_status"
242 for (i = number_of_net_interfaces_to_show
; i
> 0; i
--) {
243 interface = net_interfaces_to_show
[i
]
244 label =
substr(interface
, 1, 1)
245 if (interface ~
"^w") {
246 wifi = cache_get_fmt_def
(wi
, "status" Kfs interface
, 10, "%s")
247 label = label
":" wifi
249 addr = cache_get_fmt_def
(io
, "addr" Kfs interface
, 5, "%s", "")
250 w = cache_get_fmt_def
(io
, "bytes_written" Kfs interface
, 5, "%0.3f")
251 r = cache_get_fmt_def
(io
, "bytes_read" Kfs interface
, 5, "%0.3f")
252 io_stat = addr ?
sprintf("%s▲ %s▼", w
, r
) : "--"
253 out = out sep label
":" io_stat
256 return sprintf("N[%s]", out
)
259 function make_status_bluetooth
( src
, key
) {
260 src =
"khatus_sensor_bluetooth_power"
262 return sprintf("B=%s", cache_get_fmt_def
(src
, key
, 10, "%s"))
265 function make_status_screen_brightness
( src
, key
) {
266 src =
"khatus_sensor_screen_brightness"
268 return sprintf("*%s%%", cache_get_fmt_def
(src
, key
, 5, "%d"))
271 function make_status_volume
( sink
, mu
, vl
, vr
, show
) {
272 sink = Opt_Pulseaudio_Sink
273 cache_get
(mu
, "khatus_sensor_volume", "mute" Kfs sink
, 5)
274 cache_get
(vl
, "khatus_sensor_volume", "vol_left" Kfs sink
, 5)
275 cache_get
(vr
, "khatus_sensor_volume", "vol_right" Kfs sink
, 5)
277 if (!mu
["is_expired"] && !vl
["is_expired"] && !vr
["is_expired"]) {
278 if (mu
["value"] ==
"yes") {show =
"X"}
279 else if (mu
["value"] ==
"no") {show = vl
["value"] " " vr
["value"]}
282 "make_status_volume", \
283 "Unexpected value for 'mute' field: " mu
["value"] \
287 return sprintf("(%s)", show
)
290 function make_status_mpd
( state
, status
) {
291 cache_get
(state
, "khatus_sensor_mpd", "state", 5)
292 if (!state
["is_expired"] && state
["value"]) {
293 if (state
["value"] ==
"play") {
294 status = make_status_mpd_state_known
("▶")
295 } else if (state
["value"] ==
"pause") {
296 status = make_status_mpd_state_known
("❚❚")
297 } else if (state
["value"] ==
"stop") {
298 status = make_status_mpd_state_known
("⬛")
302 "Unexpected value for 'state' field: " state
["value"] \
310 return sprintf("[%s]", status
)
313 function make_status_mpd_state_known
(symbol
, s
, song
, time
, percentage
) {
314 s =
"khatus_sensor_mpd"
315 song = cache_get_fmt_def
(s
, "song" , 5, "%s", "?")
316 time = cache_get_fmt_def
(s
, "play_time_minimal_units", 5, "%s", "?")
317 percent = cache_get_fmt_def
(s
, "play_time_percentage" , 5, "%s", "?")
318 song =
substr(song
, 1, Opt_Mpd_Song_Max_Chars
)
319 return sprintf("%s %s %s %s", symbol
, time
, percent
, song
)
322 function make_status_weather
( src
, hour
, t_f
) {
323 src =
"khatus_sensor_weather"
325 t_f = cache_get_fmt_def
(src
, "temperature_f", 3 * hour
, "%d")
326 return sprintf("%s°F", t_f
)
329 function make_status_datetime
( dt
) {
330 return cache_get_fmt_def
("khatus_sensor_datetime", "datetime", 5, "%s")
333 # -----------------------------------------------------------------------------
335 # -----------------------------------------------------------------------------
337 function print_msg_ok
(key
, val
) {
338 print_msg
("OK", key
, val
, "/dev/stdout")
341 function print_msg_info
(location
, msg
) {
342 print_msg
("INFO", location
, msg
, "/dev/stderr")
345 function print_msg_error
(location
, msg
) {
346 print_msg
("ERROR", location
, msg
, "/dev/stderr")
349 function print_msg
(status
, key
, val
, channel
) {
350 print(status
, "khatus_bar", key
, val
) > channel
353 # -----------------------------------------------------------------------------
355 # -----------------------------------------------------------------------------