]> 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:

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