]> git.madduck.net Git - etc/awesome.git/blob - widgets/net.lua

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:

18831685d1a11c73aab9f6ab757e7c54e2e7fd35
[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 helpers      = require("lain.helpers")
11 local naughty      = require("naughty")
12 local wibox        = require("wibox")
13
14 local string       = { format = string.format,
15                        gsub   = string.gsub,
16                        match  = string.match }
17
18 local setmetatable = setmetatable
19
20 -- Network infos
21 -- lain.widgets.net
22
23 local function worker(args)
24     local net = { last_t = 0, last_r = 0, devices = {} }
25
26     function net.get_first_device()
27         local ws = helpers.read_pipe("ip link show | cut -d' ' -f2,9")
28         ws = ws:match("%w+: UP") or ws:match("ppp%w+: UNKNOWN")
29         if ws then return { ws:match("(%w+):") }
30         else return {} end
31     end
32
33     local args     = args or {}
34     local timeout  = args.timeout or 2
35     local units    = args.units or 1024 --kb
36     local notify   = args.notify or "on"
37     local screen   = args.screen or 1
38     local settings = args.settings or function() end
39     local iface    = args.iface or net.get_first_device()
40
41     net.widget = wibox.widget.textbox('')
42
43     -- Compatibility with old API where iface was a string corresponding to 1 interface
44     if type(iface) == "string" then
45         iftable = {iface}
46     else
47         iftable = iface
48     end
49
50     -- Mark all devices as initially online/active
51     for i, dev in ipairs(iftable) do
52         helpers.set_map(dev, true)
53     end
54
55     function update()
56         -- This check is required to ensure we keep looking for one device if
57         -- none is found by net.get_first_device() at startup (i.e. iftable = {})
58         if next(iftable) == nil then
59             iftable = net.get_first_device()
60         end
61
62         -- These are the totals over all specified interfaces
63         net_now = {
64             -- New api - Current state of requested devices
65             devices  = {},
66             -- Bytes since last iteration
67             sent     = 0,
68             received = 0
69         }
70
71         -- Total bytes transfered
72         local total_t = 0
73         local total_r = 0
74
75         for i, dev in ipairs(iftable) do
76             local dev_now = {}
77             local dev_before = net.devices[dev] or { last_t = 0, last_r = 0 }
78
79             dev_now.carrier  = helpers.first_line(string.format('/sys/class/net/%s/carrier', dev)) or '0'
80             dev_now.state    = helpers.first_line(string.format('/sys/class/net/%s/operstate', dev)) or 'down'
81
82             local now_t      = tonumber(helpers.first_line(string.format('/sys/class/net/%s/statistics/tx_bytes', dev)) or 0)
83             local now_r      = tonumber(helpers.first_line(string.format('/sys/class/net/%s/statistics/rx_bytes', dev)) or 0)
84
85             dev_now.sent     = (now_t - dev_before.last_t) / timeout / units
86             dev_now.received = (now_r - dev_before.last_r) / timeout / units
87
88             net_now.sent     = net_now.sent     + dev_now.sent
89             net_now.received = net_now.received + dev_now.received
90
91             dev_now.sent     = string.gsub(string.format('%.1f', dev_now.sent), ',', '.')
92             dev_now.received = string.gsub(string.format('%.1f', dev_now.received), ',', '.')
93
94             dev_now.last_t   = now_t
95             dev_now.last_r   = now_r
96
97             -- This will become dev_before in the next update/iteration
98             net.devices[dev] = dev_now
99
100             total_t  = total_t + now_t
101             total_r  = total_r + now_r
102
103             -- Notify only once when connection is loss
104             if string.match(dev_now.carrier, "0") and notify == "on" and helpers.get_map(dev) then
105                 naughty.notify({
106                     title    = dev,
107                     text     = "no carrier",
108                     icon     = helpers.icons_dir .. "no_net.png",
109                     screen   = screen
110                 })
111                 helpers.set_map(dev, false)
112             elseif string.match(dev_now.carrier, "1") then
113                 helpers.set_map(dev, true)
114             end
115
116             -- Old api compatibility
117             net_now.carrier      = dev_now.carrier
118             net_now.state        = dev_now.state
119             -- And new api
120             net_now.devices[dev] = dev_now
121             -- With the new api new_now.sent and net_now.received will be the
122             -- totals across all specified devices
123
124         end
125
126         if total_t ~= net.last_t or total_r ~= net.last_r then
127             -- Convert to a string to round the digits after the float point
128             net_now.sent     = string.gsub(string.format('%.1f', net_now.sent), ',', '.')
129             net_now.received = string.gsub(string.format('%.1f', net_now.received), ',', '.')
130
131             net.last_t = total_t
132             net.last_r = total_r
133         end
134
135         widget = net.widget
136         settings()
137     end
138
139     helpers.newtimer(iface, timeout, update)
140
141     return setmetatable(net, { __index = net.widget })
142 end
143
144 return setmetatable({}, { __call = function(_, ...) return worker(...) end })