diff options
Diffstat (limited to 'widgets/network.lua')
| -rw-r--r-- | widgets/network.lua | 181 |
1 files changed, 0 insertions, 181 deletions
diff --git a/widgets/network.lua b/widgets/network.lua deleted file mode 100644 index 20b0573..0000000 --- a/widgets/network.lua +++ /dev/null @@ -1,181 +0,0 @@ --- Network: throughput as two lines on one chart, with the LAN and public --- addresses. --- --- The rates come from the interface's own byte counters, read every draw: two --- file reads, no subprocess. The public address comes from a cache file, --- because a network call in the draw hook would freeze the dashboard when it --- hung. - -local card = require 'lib.card' -local data = require 'lib.data' - -local M = {} - --- The interface to graph. br0 is this host's bridge, matching the old text --- config. --- --- Note what this means: a bridge carries VM-to-host traffic that never reaches --- the router, so a local copy spikes the graph. That was true of the old --- config too and is accepted; this constant is the one edit that changes it. -local IFACE = 'br0' - -local CACHE = (os.getenv('XDG_CACHE_HOME') or (os.getenv('HOME') .. '/.cache')) - .. '/udt/pubip.txt' - --- A public address older than this is not shown. Eight sampling intervals: by --- then the sampler has failed repeatedly, and an address that may no longer be --- yours displayed with confidence is worse than '--'. -local STALE_AFTER = 4 * 3600 - -local STAT = '/sys/class/net/' .. IFACE .. '/statistics/' - --- Module state: the history outlives the frame, which is the whole point. --- It does not outlive a conky restart, so the chart starts empty and fills --- left to right. -local rx_counter, tx_counter -local rx_hist, tx_hist = {}, {} -local hist_len = 0 -local lan_addr = nil - --- Sampled every ~2s whatever the draw rate, so the chart keeps one point per --- sample rather than per draw. 1.9 not 2: draws jitter by a few ms. -local gate = data.new_gate(1.9) -local down, up = nil, nil - --- Append to a fixed-length history, dropping the oldest. A plain array with --- table.remove(1) rather than a circular buffer with an index: the lengths --- here are a few hundred at most and the draw is every two seconds, so the --- O(n) shift is free and the array is already in draw order. -local function push(hist, v, len) - hist[#hist + 1] = v - while #hist > len do table.remove(hist, 1) end -end - -local function read_counter(file) - local s = data.slurp(STAT .. file) - if not s then return nil end - return tonumber(s:match('^%s*(%d+)')) -end - --- Bytes per second to a short string. Deliberately not card.human: a rate --- wants a '/s' and one decimal at most, and reusing card.human would put a --- suffix meant for capacity onto a speed. -local function rate_str(bps) - if not bps then return '--' end - local units = { 'B', 'K', 'M', 'G' } - local n, i = bps, 1 - while n >= 1024 and i < #units do n = n / 1024; i = i + 1 end - if i == 1 then return string.format('%d%s/s', math.floor(n), units[i]) end - if n >= 100 then return string.format('%.0f%s/s', n, units[i]) end - return string.format('%.1f%s/s', n, units[i]) -end - -function M.draw(cr, rect, colors) - local inner = card.card(cr, rect, colors) - local function clamp(v, lo, hi) return math.max(lo, math.min(hi, v)) end - - local interval = (conky_info and conky_info.update_interval) or 2 - rx_counter = rx_counter or data.new_rate_counter(interval) - tx_counter = tx_counter or data.new_rate_counter(interval) - - local sampled, now = gate() - if sampled then - down = rx_counter:sample(read_counter('rx_bytes'), now) - up = tx_counter:sample(read_counter('tx_bytes'), now) - end - - -- Fluid type, as every other card does: one base size S drives everything, - -- taken as the smaller of a height budget and a measured width fit. - local LABEL_F, BIG_F, ROW_F = 0.30, 1.0, 0.30 - local groups = { - { { card.title_str(card.ICON.network, 'NET'), card.FONT_MONO, LABEL_F }, - { '888.8M/s', card.FONT_HEAVY, BIG_F } }, - { { '\u{F0318} 192.000.000.000', card.FONT_MONO, ROW_F } }, - { { '\u{F01DA} 888.8M/s', card.FONT_MONO, ROW_F }, - { '\u{F0552} 888.8M/s', card.FONT_MONO, ROW_F } }, - } - local fixed_units = 1.0 + ROW_F * 2.2 * 3 - local S = clamp(math.min(inner.h * 0.96 / (fixed_units + 1.2), - card.fit_unit(cr, inner.w * 0.96, groups, 100)), 10, 72) - local label_size = S * LABEL_F - local row_size = S * ROW_F - - -- Header: the label left, the download rate as the big value at the right. - -- Download is the headline because it is the number that moves. - card.font(cr, card.FONT_HEAVY, S * BIG_F, false) - card.rgba(cr, colors.body) - card.text_right(cr, inner.x + inner.w, inner.y + S * BIG_F, rate_str(down)) - - card.font(cr, card.FONT_MONO, label_size, false) - card.title(cr, inner.x, inner.y + label_size, card.ICON.network, 'NET', colors) - - local ey = inner.y + S * BIG_F + row_size * 1.4 - local step = row_size * 2.2 - - -- The addresses. LAN is memoized on first success and retried while nil: a - -- bridge may not be up when conky starts. - lan_addr = lan_addr or data.iface_addr(IFACE) - card.font(cr, card.FONT_MONO, row_size, false) - card.rgba(cr, colors.label) - card.text(cr, inner.x, ey, '\u{F0318}') -- LAN - card.rgba(cr, colors.value) - card.text_right(cr, inner.x + inner.w, ey, lan_addr or '--') - ey = ey + step - - local pub = data.kv_parse(data.slurp(CACHE) or '') - local fetched = tonumber(pub.fetched) - local pub_txt = '--' - if pub.ip and fetched and (os.time() - fetched) < STALE_AFTER then - pub_txt = pub.ip - end - card.rgba(cr, colors.label) - card.text(cr, inner.x, ey, '\u{F059F}') -- globe - card.rgba(cr, pub_txt == '--' and colors.label or colors.value) - card.text_right(cr, inner.x + inner.w, ey, pub_txt) - ey = ey + step * 1.1 - - -- The chart takes the room left between the addresses and the rate row. - local rate_row_h = row_size * 2.4 - local chart_top = ey - local chart_h = (inner.y + inner.h) - chart_top - rate_row_h - if chart_h > 12 then - -- One sample per pixel column, so the chart never interpolates. The - -- buffer is resized when the card is, keeping what it can: a moved card - -- should not clear the history. - local want = math.max(8, math.floor(inner.w)) - if want ~= hist_len then - hist_len = want - while #rx_hist > hist_len do table.remove(rx_hist, 1) end - while #tx_hist > hist_len do table.remove(tx_hist, 1) end - end - if sampled and down then push(rx_hist, down, hist_len) end - if sampled and up then push(tx_hist, up, hist_len) end - - -- One ceiling for both series. Scaled independently they would lie about - -- their relative size, which is the entire reason to draw them together. - local peak = 0 - for _, v in ipairs(rx_hist) do if v > peak then peak = v end end - for _, v in ipairs(tx_hist) do if v > peak then peak = v end end - - card.plot(cr, inner.x, chart_top, inner.w, chart_h, { - { values = rx_hist, colour = colors.ok }, - { values = tx_hist, colour = colors.highlight }, - }, peak, colors) - - -- The peak, so a full-height line means something in absolute terms. - card.font(cr, card.FONT_MONO, row_size * 0.85, false) - card.rgba(cr, colors.label) - card.text(cr, inner.x, chart_top + row_size * 0.85, rate_str(peak)) - end - - -- The live rates, each in its series colour so the line and the number are - -- unmistakably the same thing. - local ry = inner.y + inner.h - row_size * 0.4 - card.font(cr, card.FONT_MONO, row_size, false) - card.rgba(cr, colors.ok) - card.text(cr, inner.x, ry, '\u{F01DA} ' .. rate_str(down)) - card.rgba(cr, colors.highlight) - card.text_right(cr, inner.x + inner.w, ry, '\u{F0552} ' .. rate_str(up)) -end - -return M |
