X-Git-Url: https://git.madduck.net/etc/awesome.git/blobdiff_plain/7a4d6f5ffa594603ef83bc8b0e9945d12e082490..fc5974a9c2838efa8dedbd350d9623e193ab71a3:/widgets/net.lua

diff --git a/widgets/net.lua b/widgets/net.lua
index f361146..0b19f0b 100644
--- a/widgets/net.lua
+++ b/widgets/net.lua
@@ -7,147 +7,119 @@
                                                   
 --]]
 
-local markup       = require("lain.util.markup")
 local helpers      = require("lain.helpers")
-
-local awful        = require("awful")
-local beautiful    = require("beautiful")
+local naughty      = require("naughty")
 local wibox        = require("wibox")
-
-local io           = io
-local tostring     = tostring
-local string       = { format = string.format }
-
+local string       = { format = string.format,
+                       match  = string.match }
 local setmetatable = setmetatable
 
 -- Network infos
 -- lain.widgets.net
-local net = {
-    send = "0",
-    recv = "0",
-    last_t = {},
-    last_r = {}
-}
-
-local unit = {
-    ["b"] = 1,
-    ["kb"] = 1024,
-    ["mb"] = 1024^2,
-    ["gb"] = 1024^3
-}
-
-function net.get_device()
-    f = io.popen("ip link show | cut -d' ' -f2,9")
-    ws = f:read("*all")
-    f:close()
-    ws = ws:match("%w+: UP")
-    if ws ~= nil then
-        return ws:gsub(": UP", "")
-    else
-        return ""
-    end
-end
 
-function worker(args)
-    local args = args or {}
-    local iface = args.iface or net.get_device()
-    local delta = args.refresh_timeout or 2
-    local unit = args.unit or unit["kb"]
-    local spr = args.spr or " "
-    local header = args.header or iface
-    local header_color = args.header_color or beautiful.fg_normal or "#FFFFFF"
-    local color_up = args.color_up or beautiful.fg_focus or header_color
-    local color_down = args.color_down or beautiful.fg_focus or header_color
-    local app = args.app or "sudo wifi-menu"
-
-    helpers.set_map(iface, true)
-    helpers.set_map("carrier", 0)
-
-    local mynet = wibox.widget.textbox()
-
-    local mynetupdate = function()
-        if iface == "" then
-            iface = net.get_device()
-            header = iface
-        end
+local function worker(args)
+    local net = helpers.make_widget_textbox()
+    net.last_t = 0
+    net.last_r = 0
+    net.devices = {}
+
+    local args       = args or {}
+    local timeout    = args.timeout or 2
+    local units      = args.units or 1024 --kb
+    local notify     = args.notify or "on"
+    local screen     = args.screen or 1
+    local settings   = args.settings or function() end
+
+    -- Compatibility with old API where iface was a string corresponding to 1 interface
+    net.iface = (args.iface and (type(args.iface) == "string" and {args.iface}) or
+                (type(args.iface) == "table" and args.iface)) or {}
+
+    function net.get_device()
+        helpers.async(string.format("ip link show", device_cmd), function(ws)
+            ws = ws:match("(%w+): <BROADCAST,MULTICAST,.-UP,LOWER_UP>")
+            net.iface = ws and { ws } or {}
+        end)
+    end
 
-        local carrier = helpers.first_line('/sys/class/net/' .. iface ..
-                                           '/carrier') or ""
-        local state = helpers.first_line('/sys/class/net/' .. iface ..
-                                           '/operstate')
-        local now_t = helpers.first_line('/sys/class/net/' .. iface ..
-                                           '/statistics/tx_bytes')
-        local now_r = helpers.first_line('/sys/class/net/' .. iface ..
-                                           '/statistics/rx_bytes')
-        local text = '<span color="' .. header_color .. '">' .. header .. '</span> '
-
-        if carrier ~= "1"
-        then
-            if helpers.get_map(iface)
-            then
-                n_title = iface
-                if n_title == "" then
-                    n_title = "network"
-                    header = "Net"
-                end
-                naughty.notify({ title = n_title, text = "no carrier",
-                                 timeout = 7,
-                                 position = "top_left",
-                                 icon = beautiful.lain_no_net_notify or
-                                        helpers.icons_dir .. "no_net.png",
-                                 fg = beautiful.fg_focus or "#FFFFFF" })
-
-                mynet:set_markup(markup(header_color, header) .. markup(color_up, " Off"))
-                helpers.set_map(iface, false)
+    if #net.iface == 0 then net.get_device() end
+
+    function update()
+        -- These are the totals over all specified interfaces
+        net_now = {
+            -- New api - Current state of requested devices
+            devices  = {},
+            -- Bytes since last iteration
+            sent     = 0,
+            received = 0
+        }
+
+        -- Total bytes transfered
+        local total_t = 0
+        local total_r = 0
+
+        for i, dev in ipairs(net.iface) do
+            local dev_now    = {}
+            local dev_before = net.devices[dev] or { last_t = 0, last_r = 0 }
+            local now_t      = tonumber(helpers.first_line(string.format("/sys/class/net/%s/statistics/tx_bytes", dev)) or 0)
+            local now_r      = tonumber(helpers.first_line(string.format("/sys/class/net/%s/statistics/rx_bytes", dev)) or 0)
+
+            dev_now.carrier  = helpers.first_line(string.format("/sys/class/net/%s/carrier", dev)) or "0"
+            dev_now.state    = helpers.first_line(string.format("/sys/class/net/%s/operstate", dev)) or "down"
+
+            dev_now.sent     = (now_t - dev_before.last_t) / timeout / units
+            dev_now.received = (now_r - dev_before.last_r) / timeout / units
+
+            net_now.sent     = net_now.sent     + dev_now.sent
+            net_now.received = net_now.received + dev_now.received
+
+            dev_now.sent     = string.format('%.1f', dev_now.sent)
+            dev_now.received = string.format('%.1f', dev_now.received)
+
+            dev_now.last_t   = now_t
+            dev_now.last_r   = now_r
+
+            -- This will become dev_before in the next update/iteration
+            net.devices[dev] = dev_now
+
+            total_t  = total_t + now_t
+            total_r  = total_r + now_r
+
+            -- Notify only once when connection is loss
+            if string.match(dev_now.carrier, "0") and notify == "on" and helpers.get_map(dev) then
+                naughty.notify({
+                    title    = dev,
+                    text     = "no carrier",
+                    icon     = helpers.icons_dir .. "no_net.png",
+                    screen   = screen
+                })
+                helpers.set_map(dev, false)
+            elseif string.match(dev_now.carrier, "1") then
+                helpers.set_map(dev, true)
             end
-            return
-        else
-            helpers.set_map(iface, true)
-        end
 
-        if state == 'down' or not now_t or not now_r
-        then
-            mynet:set_markup(' ' .. text .. '-' .. ' ')
-            return
+            -- Old api compatibility
+            net_now.carrier      = dev_now.carrier
+            net_now.state        = dev_now.state
+            -- And new api
+            net_now.devices[dev] = dev_now
+            -- With the new api new_now.sent and net_now.received will be the
+            -- totals across all specified devices
         end
 
-        if net.last_t[iface] and net.last_t[iface]
-        then
-            net.send = tostring((now_t - net.last_t[iface]) / delta / unit)
-            net.recv = tostring((now_r - net.last_r[iface]) / delta / unit)
-
-            text = text
-                   .. '<span color="' .. color_up .. '">'
-                   .. string.format('%.1f', net.send)
-                   .. '</span>'
-                   ..  spr
-                   .. '<span color="' .. color_down .. '">'
-                   .. string.format('%.1f', net.recv)
-                   .. '</span>'
-
-            mynet:set_markup(' ' .. text .. ' ')
-        else
-            mynet:set_markup(' ' .. text .. '-' .. ' ')
+        if total_t ~= net.last_t or total_r ~= net.last_r then
+            net_now.sent     = string.format('%.1f', net_now.sent)
+            net_now.received = string.format('%.1f', net_now.received)
+            net.last_t       = total_t
+            net.last_r       = total_r
         end
 
-        net.last_t[iface] = now_t
-        net.last_r[iface] = now_r
+        widget = net.widget
+        settings()
     end
 
-    local mynettimer = timer({ timeout = delta })
-    mynettimer:connect_signal("timeout", mynetupdate)
-    mynettimer:start()
-    mynettimer:emit_signal("timeout")
-
-    mynet:buttons(awful.util.table.join(
-            awful.button({}, 0, function()
-                helpers.run_in_terminal(app)
-                mynetupdate()
-            end)))
-
-    net.widget = mynet
+    helpers.newtimer("network", timeout, update)
 
     return setmetatable(net, { __index = net.widget })
 end
 
-return setmetatable(net, { __call = function(_, ...) return worker(...) end })
+return setmetatable({}, { __call = function(_, ...) return worker(...) end })