X-Git-Url: https://git.madduck.net/etc/awesome.git/blobdiff_plain/fb3da82d1066e9c734f5c0dc4275713e388af31a..1c43f4df29de9e15f629a7f0beaa355875305916:/widgets/net.lua?ds=sidebyside

diff --git a/widgets/net.lua b/widgets/net.lua
index 18727f1..1883168 100644
--- a/widgets/net.lua
+++ b/widgets/net.lua
@@ -7,147 +7,138 @@
                                                   
 --]]
 
-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,
+                       gsub   = string.gsub,
+                       match  = string.match }
 
 local setmetatable = setmetatable
 
 -- Network infos
 -- lain.widgets.net
-local net = {
-    send = "0",
-    recv = "0",
-    last_t = {},
-    last_r = {}
-}
-
-net.units = {
-    ["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", "")
+
+local function worker(args)
+    local net = { last_t = 0, last_r = 0, devices = {} }
+
+    function net.get_first_device()
+        local ws = helpers.read_pipe("ip link show | cut -d' ' -f2,9")
+        ws = ws:match("%w+: UP") or ws:match("ppp%w+: UNKNOWN")
+        if ws then return { ws:match("(%w+):") }
+        else return {} end
+    end
+
+    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
+    local iface    = args.iface or net.get_first_device()
+
+    net.widget = wibox.widget.textbox('')
+
+    -- Compatibility with old API where iface was a string corresponding to 1 interface
+    if type(iface) == "string" then
+        iftable = {iface}
     else
-        return ""
+        iftable = iface
     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 units = args.units or net.units["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 "#FFFFFF"
-    local color_down = args.color_down or beautiful.fg_focus or "#FFFFFF"
-    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
+    -- Mark all devices as initially online/active
+    for i, dev in ipairs(iftable) do
+        helpers.set_map(dev, true)
+    end
+
+    function update()
+        -- This check is required to ensure we keep looking for one device if
+        -- none is found by net.get_first_device() at startup (i.e. iftable = {})
+        if next(iftable) == nil then
+            iftable = net.get_first_device()
         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)
+        -- 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(iftable) do
+            local dev_now = {}
+            local dev_before = net.devices[dev] or { last_t = 0, last_r = 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'
+
+            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.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.gsub(string.format('%.1f', dev_now.sent), ',', '.')
+            dev_now.received = string.gsub(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
-        end
+            -- 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
 
-        if net.last_t[iface] and net.last_t[iface]
-        then
-            net.send = tostring((now_t - net.last_t[iface]) / delta / units)
-            net.recv = tostring((now_r - net.last_r[iface]) / delta / units)
-
-            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 .. '-' .. ' ')
         end
 
-        net.last_t[iface] = now_t
-        net.last_r[iface] = now_r
-    end
+        if total_t ~= net.last_t or total_r ~= net.last_r then
+            -- Convert to a string to round the digits after the float point
+            net_now.sent     = string.gsub(string.format('%.1f', net_now.sent), ',', '.')
+            net_now.received = string.gsub(string.format('%.1f', net_now.received), ',', '.')
 
-    local mynettimer = timer({ timeout = delta })
-    mynettimer:connect_signal("timeout", mynetupdate)
-    mynettimer:start()
-    mynettimer:emit_signal("timeout")
+            net.last_t = total_t
+            net.last_r = total_r
+        end
 
-    mynet:buttons(awful.util.table.join(
-            awful.button({}, 0, function()
-                helpers.run_in_terminal(app)
-                mynetupdate()
-            end)))
+        widget = net.widget
+        settings()
+    end
 
-    net.widget = mynet
+    helpers.newtimer(iface, timeout, update)
 
     return setmetatable(net, { __index = net.widget })
 end
 
-return setmetatable(net, { __call = function(_, ...) return worker(...) end })
+return setmetatable({}, { __call = function(_, ...) return worker(...) end })