----------------------------------------------------------------------------
--- Simple Network Widget
--
-- Depends: iproute2, iw
--
-- For more details check `man maim`
--
-- @author manilarome <gerome.matilla07@gmail.com>
-- @copyright 2020 manilarome
-- @widget network
----------------------------------------------------------------------------
local awful = require('awful')
local wibox = require('wibox')
local gears = require('gears')
local naughty = require('naughty')
local dpi = require('beautiful').xresources.apply_dpi
local apps = require('configuration.apps')
local clickable_container = require('widget.clickable-container')
local config_dir = gears.filesystem.get_configuration_dir()
local widget_icon_dir = config_dir .. 'widget/network/icons/'
local wlan_interface = 'wlp3s0'
local lan_interface = 'enp0s25'
local return_button = function()
local wifi_strength = nil
local connected_to_network = false
local conn_status = 'disconnected'
local essid = nil
local update_notify_no_access = true
local notify_no_access_quota = 0
local startup = true
local notify_new_wifi_conn = false
local net_speed = 'N/A'
local widget = wibox.widget {
{
id = 'icon',
image = widget_icon_dir .. 'wifi-strength-off' .. '.svg',
widget = wibox.widget.imagebox,
resize = true
},
layout = wibox.layout.align.horizontal
}
local widget_button = wibox.widget {
{
widget,
margins = dpi(7),
widget = wibox.container.margin
},
widget = clickable_container
}
widget_button:buttons(
gears.table.join(
awful.button(
{},
1,
nil,
function()
awful.spawn(apps.default.network_manager, false)
end
)
)
)
local notify_not_connected = function()
local message = 'The network has been disconnected'
local title = 'Connection Disconnected'
if conn_status == 'wireless' then
icon = widget_icon_dir .. 'wifi-strength-off.svg'
elseif conn_status == 'wired' then
icon = widget_icon_dir .. 'wired-off.svg'
else
icon = widget_icon_dir .. 'wifi-strength-off.svg'
end
naughty.notification({
message = message,
title = title,
app_name = 'System Notification',
icon = icon
})
conn_status = 'disconnected'
end
local update_disconnected = function()
if conn_status == 'wireless' or conn_status == 'wired' then
local widget_icon_name = nil
connected_to_network = false
notify_new_wifi_conn = true
essid = nil
update_notify_no_access = true
if conn_status == 'wireless' then
widget_icon_name = 'wifi-strength-off'
elseif conn_status == 'wired' then
widget_icon_name = 'wired-off'
end
notify_not_connected()
widget.icon:set_image(widget_icon_dir .. widget_icon_name .. '.svg')
end
end
local notify_no_access = function(strength)
if conn_status == 'wireless' or conn_status == 'wired' then
local message = 'Internet may not be available or it is too slow right now'
if conn_status == 'wireless' then
icon = widget_icon_dir .. 'wifi-strength-' .. tostring(strength) .. '-alert.svg'
elseif conn_status == 'wired' then
icon = widget_icon_dir .. 'wired-off.svg'
end
naughty.notification({
message = message,
title = 'Connection Status',
app_name = 'System Notification',
icon = icon
})
end
end
local update_no_access = function(strength)
if not update_notify_no_access then
return
end
local widget_icon_name = nil
if conn_status == 'wireless' then
widget_icon_name = 'wifi-strength-' .. tostring(strength) .. '-alert'
elseif conn_status == 'wired' then
widget_icon_name = 'wired-alert'
end
notify_no_access(strength)
widget.icon:set_image(widget_icon_dir .. widget_icon_name .. '.svg')
update_notify_no_access = false
end
local notify_wifi_conn = function()
if startup then
startup = false
return
end
if not notify_new_wifi_conn then
return
end
local message = "You are now connected to \"" .. essid .. "\""
local title = "Connection Established"
local app_name = "System Notification"
local icon = widget_icon_dir .. 'wifi.svg'
naughty.notification({
message = message,
title = title,
app_name = app_name,
icon = icon
})
notify_new_wifi_conn = false
end
local update_essid = function()
if not essid and connected_to_network == true then
awful.spawn.easy_async_with_shell(
[[
iw dev ]] .. wlan_interface .. [[ link
]],
function(stdout)
essid = stdout:match('SSID: (.-)\n')
if essid == nil then
essid = 'N/A'
end
notify_wifi_conn()
end
)
end
end
local check_internet_health = [[
status_curl=0
status_ping=0
ip="$(curl --connect-timeout 5 ifconfig.co)"
if expr "$ip" : '[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*\.[0-9][0-9]*$' >/dev/null;
then
status_curl=1
else
status_curl=0
fi
packets="$(ping -q -w4 -c4 1.1.1.1 | grep -o "100% packet loss")"
if [ ! -z "${packets}" ];
then
status_ping=0
else
status_ping=1
fi
if [ $status_ping -eq 0 ] && [ $status_curl -eq 0 ];
then
echo 'noaccess'
fi
]]
local update_net_speed = function()
awful.spawn.easy_async_with_shell(
'iw dev ' .. wlan_interface .. ' link',
function(stdout)
net_speed = stdout:match("tx bitrate: (.+/s)") or 'N/A'
end
)
end
local update_wireless = function()
conn_status = 'wireless'
connected_to_network = true
awful.spawn.easy_async_with_shell(
[[
awk 'NR==3 {printf "%3.0f" ,($3/70)*100}' /proc/net/wireless
]],
function(stdout)
if not tonumber(stdout) then
return
end
local widget_icon_name = 'wifi-strength'
wifi_strength = tonumber(stdout)
local wifi_strength_rounded = math.floor(wifi_strength / 25 + 0.5)
awful.spawn.easy_async_with_shell(
check_internet_health,
function(stdout)
local widget_icon_name = widget_icon_name .. '-' .. wifi_strength_rounded
if stdout:match('noaccess') then
update_no_access(wifi_strength_rounded)
return
else
update_net_speed()
if startup then
awesome.emit_signal('system::wifi_connected')
end
update_notify_no_access = true
end
widget.icon:set_image(widget_icon_dir .. widget_icon_name .. '.svg')
end
)
end
)
update_essid()
end
local update_wired = function()
conn_status = 'wired'
connected_to_network = true
awful.spawn.easy_async_with_shell(
check_internet_health,
function(stdout)
widget_icon_name = 'wired'
if stdout:match('fail') then
update_no_access()
return
else
if startup then
awesome.emit_signal('system::wifi_connected')
startup = false
end
update_notify_no_access = true
end
widget.icon:set_image(widget_icon_dir .. widget_icon_name .. '.svg')
end
)
end
awful.tooltip(
{
objects = {widget_button},
mode = 'outside',
align = 'right',
timer_function = function()
if connected_to_network then
if conn_status == 'wireless' then
return 'Wireless Interface: ' .. wlan_interface ..
'\nConnected to: ' .. (essid or "*LOADING...*") ..
'\nWiFi-Strength: ' .. tostring(wifi_strength) .. '%' ..
'\nBit rate: ' .. tostring(net_speed) .. ''
else
return 'Ethernet Interface: ' .. lan_interface
end
else
return 'Network is currently disconnected'
end
end,
preferred_positions = {'left', 'right', 'top', 'bottom'},
margin_leftright = dpi(8),
margin_topbottom = dpi(8)
}
)
gears.timer {
timeout = 9,
autostart = true,
call_now = true,
callback = function()
awful.spawn.easy_async_with_shell(
[[
net_status="$(ip route get 8.8.8.8 2>&1 >/dev/null)"
if ]] .. "[[ " .. [[ "$(echo ${net_status} | awk -F ": " '{print $2}')" == *'unreachable'* ]] .. " ]];" .. [[
then
echo 'No internet connection'
exit;
fi
net_status="$(ip route get 8.8.8.8 | grep -Po 'dev \K\w+' | grep -Ff - /proc/net/wireless)"
if [ ! -z "${net_status}" ]
then
echo 'wireless'
else
echo 'wired'
fi
]],
function(stdout)
if stdout:match('No internet connection') then
update_disconnected()
return
end
if stdout:match('wireless') then
update_wireless()
elseif stdout:match('wired') then
update_wired()
end
end
)
end
}
return widget_button
end
return return_button