madduck's git repository

Every one of the projects in this repository is available at the canonical URL git://git.madduck.net/madduck/pub/<projectpath> — see each project's metadata for the exact URL.

All patches and comments are welcome. Please squash your changes to logical commits before using git-format-patch and git-send-email to patches@git.madduck.net. If you'd read over the Git project's submission guidelines and adhered to them, I'd be especially grateful.

SSH access, as well as push access can be individually arranged.

If you use my repositories frequently, consider adding the following snippet to ~/.gitconfig and using the third clone URL listed for each project:

[url "git://git.madduck.net/madduck/"]
  insteadOf = madduck:

Initial commit
[etc/awesome.git] / widgets / net.lua
1
2 --[[
3                                                   
4      Licensed under GNU General Public License v2 
5       * (c) 2013,      Luke Bonham                
6       * (c) 2010-2012, Peter Hofmann              
7                                                   
8 --]]
9
10 local markup       = require("lain.util.markup")
11 local helpers      = require("lain.helpers")
12
13 local awful        = require("awful")
14 local beautiful    = require("beautiful")
15 local wibox        = require("wibox")
16
17 local io           = io
18 local tostring     = tostring
19 local string       = { format = string.format }
20
21 local setmetatable = setmetatable
22
23 -- Network infos
24 -- lain.widgets.net
25 local net = {
26     send = "0",
27     recv = "0",
28     last_t = {},
29     last_r = {}
30 }
31
32 net.units = {
33     ["b"] = 1,
34     ["kb"] = 1024,
35     ["mb"] = 1024^2,
36     ["gb"] = 1024^3
37 }
38
39 function net.get_device()
40     f = io.popen("ip link show | cut -d' ' -f2,9")
41     ws = f:read("*all")
42     f:close()
43     ws = ws:match("%w+: UP")
44     if ws ~= nil then
45         return ws:gsub(": UP", "")
46     else
47         return ""
48     end
49 end
50
51 function worker(args)
52     local args = args or {}
53     local iface = args.iface or net.get_device()
54     local delta = args.refresh_timeout or 2
55     local units = args.units or net.units["kb"]
56     local spr = args.spr or " "
57     local header = args.header or iface
58     local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF"
59     local color_up = args.color_up or beautiful.fg_focus or "#FFFFFF"
60     local color_down = args.color_down or beautiful.fg_focus or "#FFFFFF"
61     local app = args.app or "sudo wifi-menu"
62
63     helpers.set_map(iface, true)
64     helpers.set_map("carrier", 0)
65
66     local mynet = wibox.widget.textbox()
67
68     local mynetupdate = function()
69         if iface == "" then
70             iface = net.get_device()
71             header = iface
72         end
73
74         local carrier = helpers.first_line('/sys/class/net/' .. iface ..
75                                            '/carrier') or ""
76         local state = helpers.first_line('/sys/class/net/' .. iface ..
77                                            '/operstate')
78         local now_t = helpers.first_line('/sys/class/net/' .. iface ..
79                                            '/statistics/tx_bytes')
80         local now_r = helpers.first_line('/sys/class/net/' .. iface ..
81                                            '/statistics/rx_bytes')
82         local text = '<span color="' .. header_color .. '">' .. header .. '</span> '
83
84         if carrier ~= "1"
85         then
86             if helpers.get_map(iface)
87             then
88                 n_title = iface
89                 if n_title == "" then
90                     n_title = "network"
91                     header = "Net"
92                 end
93                 naughty.notify({ title = n_title, text = "no carrier",
94                                  timeout = 7,
95                                  position = "top_left",
96                                  icon = beautiful.lain_no_net_notify or
97                                         helpers.icons_dir .. "no_net.png",
98                                  fg = beautiful.fg_focus or "#FFFFFF" })
99
100                 mynet:set_markup(markup(header_color, header) .. markup(color_up, " Off"))
101                 helpers.set_map(iface, false)
102             end
103             return
104         else
105             helpers.set_map(iface, true)
106         end
107
108         if state == 'down' or not now_t or not now_r
109         then
110             mynet:set_markup(' ' .. text .. '-' .. ' ')
111             return
112         end
113
114         if net.last_t[iface] and net.last_t[iface]
115         then
116             net.send = tostring((now_t - net.last_t[iface]) / delta / units)
117             net.recv = tostring((now_r - net.last_r[iface]) / delta / units)
118
119             text = text
120                    .. '<span color="' .. color_up .. '">'
121                    .. string.format('%.1f', net.send)
122                    .. '</span>'
123                    ..  spr
124                    .. '<span color="' .. color_down .. '">'
125                    .. string.format('%.1f', net.recv)
126                    .. '</span>'
127
128             mynet:set_markup(' ' .. text .. ' ')
129         else
130             mynet:set_markup(' ' .. text .. '-' .. ' ')
131         end
132
133         net.last_t[iface] = now_t
134         net.last_r[iface] = now_r
135     end
136
137     local mynettimer = timer({ timeout = delta })
138     mynettimer:connect_signal("timeout", mynetupdate)
139     mynettimer:start()
140     mynettimer:emit_signal("timeout")
141
142     mynet:buttons(awful.util.table.join(
143             awful.button({}, 0, function()
144                 helpers.run_in_terminal(app)
145                 mynetupdate()
146             end)))
147
148     net.widget = mynet
149
150     return setmetatable(net, { __index = net.widget })
151 end
152
153 return setmetatable(net, { __call = function(_, ...) return worker(...) end })