1031 lines
31 KiB
Lua
1031 lines
31 KiB
Lua
-- HorlogeSkynet's Lua script (for Conky)
|
|
-- https://git.forestier.app/HorlogeSkynet/SimpleConkyScript.git
|
|
|
|
|
|
local signal = require('posix.signal')
|
|
|
|
-----------------------------------------------------------------------------------------
|
|
|
|
-- Little gaps between screen borders and Conky surface.
|
|
local GAP_X, GAP_Y = 10, 10
|
|
|
|
-- Width of the two 'columns' which will contain all the elements.
|
|
local COLUMNS_WIDTH = 310
|
|
|
|
-- Global x-padding for elements displayed.
|
|
local GLOBAL_CELL_BORDER = 10
|
|
|
|
-- Width of our 'graph' objects.
|
|
local GRAPH_WIDTH = COLUMNS_WIDTH - GLOBAL_CELL_BORDER
|
|
|
|
-- Number of top process to display.
|
|
local MAX_TOP_PROCESS = 5
|
|
|
|
-- Temperature unit.
|
|
-- You can set an 'F' (Fahrenheit), but don't forget to adapt the temperature objects thresholds.
|
|
local TEMPERATURE_UNIT = 'C'
|
|
|
|
-- Font used everywhere.
|
|
-- /!\ Some special characters used here CAN'T BE displayed with certain fonts...
|
|
local FONT_FAMILY = 'Mono'
|
|
|
|
-- Global font size.
|
|
local FONT_SIZE = 15
|
|
|
|
-- Only begin effective loading only once this number of updates have passed.
|
|
local STARTUP_THRESHOLD = 5
|
|
|
|
-----------------------------------------------------------------------------------------
|
|
|
|
|
|
-- Count the number of available package updates.
|
|
local package_updates = {
|
|
-- Careful, the command below WILL BE executed anyhow.
|
|
-- Additional information : On "recent" Debian, a systemd timer run `aptitude update` regularly.
|
|
-- On older system (and or other GNU/Linux distributions), you may wanna run it manually.
|
|
command = "aptitude search \'~U\' | wc -l",
|
|
-- Only execute the command above each `interval` iterations.
|
|
interval = 240,
|
|
-- This element will store the effective number of updates.
|
|
value = nil
|
|
}
|
|
|
|
-- Retrieves your public IP address on the WWW.
|
|
local public_ip = {
|
|
-- Careful, the command below WILL BE executed anyhow.
|
|
command = "wget -qO- https://ident.me/",
|
|
-- Only execute the command above each `interval` iterations.
|
|
interval = 240,
|
|
-- This element will store the effective public IP.
|
|
ip = nil,
|
|
-- Special flag for IPv6 addresses...
|
|
is_v6 = false
|
|
}
|
|
|
|
-- Computes the brightness level of your screen.
|
|
local brightness_level = {
|
|
-- File paths towards brightness levels.
|
|
files = {
|
|
cur_brightness = "/sys/class/backlight/intel_backlight/actual_brightness",
|
|
max_brightness = "/sys/class/backlight/intel_backlight/max_brightness"
|
|
},
|
|
interval = 10,
|
|
value = nil
|
|
}
|
|
|
|
-- Determines the GNU/Linux distribution.
|
|
local distribution = {
|
|
-- Careful, the command below WILL BE executed anyhow.
|
|
command = "lsb_release -sirc",
|
|
-- Only execute the command above each `interval` iterations.
|
|
interval = 240,
|
|
-- This element will store the effective distribution information.
|
|
value = nil
|
|
}
|
|
|
|
|
|
local text_host = {
|
|
name = 'nodename',
|
|
arg = '',
|
|
display_name = 'Hostname'
|
|
}
|
|
|
|
local text_kernel = {
|
|
name = 'kernel',
|
|
arg = '',
|
|
display_name = 'Kernel'
|
|
}
|
|
|
|
local text_architecture = {
|
|
name = 'machine',
|
|
arg = '',
|
|
display_name = 'Architecture'
|
|
}
|
|
|
|
local text_uptime = {
|
|
name = 'uptime',
|
|
arg = '',
|
|
display_name = 'Uptime'
|
|
}
|
|
|
|
local bar_cpu_0 = {
|
|
name = 'cpu',
|
|
arg = 'cpu0',
|
|
display_name = 'CPU0'
|
|
}
|
|
|
|
local bar_cpu_1 = {
|
|
name = 'cpu',
|
|
arg = 'cpu1',
|
|
display_name = 'CPU1'
|
|
}
|
|
|
|
local bar_cpu_2 = {
|
|
name = 'cpu',
|
|
arg = 'cpu2',
|
|
display_name = 'CPU2'
|
|
}
|
|
|
|
local bar_cpu_3 = {
|
|
name = 'cpu',
|
|
arg = 'cpu3',
|
|
display_name = 'CPU3'
|
|
}
|
|
|
|
local bar_ram = {
|
|
name = 'memperc',
|
|
arg = '',
|
|
display_name = 'RAM'
|
|
}
|
|
|
|
local bar_swap = {
|
|
name = 'swapperc',
|
|
arg = '',
|
|
display_name = 'SWAP'
|
|
}
|
|
|
|
local bar_entropy = {
|
|
name = 'entropy_perc',
|
|
arg = '',
|
|
display_name = 'Entropy'
|
|
}
|
|
|
|
local bar_disk_home = {
|
|
name = 'fs_used_perc',
|
|
arg = '/home/',
|
|
display_name = "/home/ usage"
|
|
}
|
|
|
|
local bar_disk_root = {
|
|
name = 'fs_used_perc',
|
|
arg = '/',
|
|
display_name = "/ usage"
|
|
}
|
|
|
|
local graph_disk_read_write = {
|
|
graph_read = {
|
|
name = 'diskio_read',
|
|
arg = '/dev/sda',
|
|
values = {}
|
|
},
|
|
graph_write = {
|
|
name = 'diskio_write',
|
|
arg = '/dev/sda',
|
|
values = {}
|
|
},
|
|
display_name = '/dev/sda'
|
|
}
|
|
|
|
local bar_battery = {
|
|
name = 'battery_percent',
|
|
arg = 'BAT0',
|
|
display_name = 'Battery'
|
|
}
|
|
|
|
local text_running_process = {
|
|
name = 'running_processes',
|
|
arg = '',
|
|
display_name = 'Running processes'
|
|
}
|
|
|
|
local text_process = {
|
|
name = 'processes',
|
|
arg = '',
|
|
display_name = 'Idle processes'
|
|
}
|
|
|
|
local text_running_thread = {
|
|
name = 'running_threads',
|
|
arg = '',
|
|
display_name = 'Running threads'
|
|
}
|
|
|
|
local text_thread = {
|
|
name = 'threads',
|
|
arg = '',
|
|
display_name = 'Idle threads'
|
|
}
|
|
|
|
local text_temperatures = {
|
|
temp_cores = {
|
|
{
|
|
id = '0',
|
|
display_name = 'Core_0',
|
|
threshold = 70,
|
|
value = nil
|
|
},
|
|
{
|
|
id = '1',
|
|
display_name = 'Core_1',
|
|
threshold = 70,
|
|
value = nil
|
|
}
|
|
},
|
|
temp_hdds = {
|
|
{
|
|
name = '/dev/sda',
|
|
display_name = "Hard Disk",
|
|
threshold = 50,
|
|
value = nil
|
|
}
|
|
}
|
|
}
|
|
|
|
local graph_network_interface_1 = {
|
|
graph_download = {
|
|
name = 'downspeedf',
|
|
arg = 'enp0s25',
|
|
values = {}
|
|
},
|
|
graph_upload = {
|
|
name = 'upspeedf',
|
|
arg = 'enp0s25',
|
|
values = {}
|
|
},
|
|
display_name = 'Eth0'
|
|
}
|
|
|
|
local graph_network_interface_2 = {
|
|
graph_download = {
|
|
name = 'downspeedf',
|
|
arg = 'wlo1',
|
|
values = {}
|
|
},
|
|
graph_upload = {
|
|
name = 'upspeedf',
|
|
arg = 'wlo1',
|
|
values = {}
|
|
},
|
|
display_name = 'Wlan0'
|
|
}
|
|
|
|
-----------------------------------------------------------------------------------------
|
|
|
|
local SimpleConkyScript = {}
|
|
|
|
|
|
-- Internal variable, for performance purposes.
|
|
local conky_updates = nil
|
|
|
|
|
|
-- One little function to get the screen definition in only one call !
|
|
function SimpleConkyScript.get_screen_definition()
|
|
local handle = io.popen("xdpyinfo | grep dimensions")
|
|
local width, height = string.match(
|
|
handle:read('*all'),
|
|
"%s*dimensions:%s*(%d+)x(%d+).*")
|
|
io.close(handle)
|
|
|
|
return tonumber(width), tonumber(height)
|
|
end
|
|
|
|
|
|
-- Another one little function to retrieve the gaps set within this module !
|
|
function SimpleConkyScript.get_gaps()
|
|
return GAP_X, GAP_Y
|
|
end
|
|
|
|
|
|
-- The IPv6 addresses are too long for this column size, here is a function to make them "stream" on the screen.
|
|
local function _stream_ipv6_address(address)
|
|
local quantum = string.len(address) / 2
|
|
local cycle = conky_updates % 2
|
|
|
|
local ip
|
|
if cycle ~= 0 then ip = "< " else ip = " " end
|
|
ip = ip .. string.sub(address, cycle * quantum + cycle, (cycle + 1) * quantum)
|
|
if cycle == 0 then ip = ip .. " >" end
|
|
|
|
return ip
|
|
end
|
|
|
|
|
|
-- Generic function to draw our 'graph' object
|
|
local function _draw_graph(display, data, x_pos, y_pos, width)
|
|
local height = 25
|
|
local line_width = 4
|
|
local number_max_values = 25
|
|
|
|
local current_x_pos = x_pos + width - line_width / 2.
|
|
local difference = (width - line_width) / (number_max_values - 1)
|
|
|
|
local count = table.getn(data['values'])
|
|
|
|
if count == 0 then return y_pos + height end
|
|
|
|
if count > number_max_values then
|
|
table.remove(data['values'], 1)
|
|
count = count - 1
|
|
end
|
|
|
|
local max_of_value = data['values'][1]
|
|
|
|
for i = 2, count do
|
|
if data['values'][i] > max_of_value then max_of_value = data['values'][i] end
|
|
end
|
|
|
|
if max_of_value == 0 then max_of_value = 1 end
|
|
|
|
cairo_set_line_width(display, line_width)
|
|
cairo_set_line_cap(display, CAIRO_LINE_CAP_BUTT)
|
|
|
|
local value
|
|
for i = 1, count do
|
|
value = data['values'][count - i + 1]
|
|
|
|
cairo_move_to(
|
|
display, current_x_pos, y_pos + (1 - value / max_of_value) * height)
|
|
cairo_line_to(display, current_x_pos, y_pos + height)
|
|
|
|
current_x_pos = current_x_pos - difference
|
|
end
|
|
|
|
cairo_stroke(display)
|
|
|
|
return y_pos + height
|
|
end
|
|
|
|
|
|
-- Generic function to draw our 'text' object
|
|
local function _draw_text(display, text, x_pos, y_pos)
|
|
local height = 25
|
|
local space = (height - FONT_SIZE) / 2.
|
|
|
|
cairo_move_to(display, x_pos, y_pos + FONT_SIZE + space)
|
|
cairo_show_text(display, text)
|
|
cairo_stroke(display)
|
|
|
|
return y_pos + height
|
|
end
|
|
|
|
|
|
-- Generic function to draw our 'bar' object
|
|
local function _draw_bar(display, data, x_pos, y_pos, value)
|
|
local height = conky_window.height * (5 / 100.)
|
|
local line_width = 5
|
|
local cursor_height = 10
|
|
local cursor_width = 5
|
|
local space_text_bar = 5
|
|
local space = (
|
|
height - FONT_SIZE - space_text_bar - line_width / 2. - cursor_height) / 2.
|
|
|
|
cairo_move_to(display, x_pos, y_pos + FONT_SIZE + space)
|
|
cairo_show_text(display, data['display_name'])
|
|
cairo_stroke(display)
|
|
|
|
local line_y = y_pos + space + FONT_SIZE + space_text_bar + line_width / 2
|
|
local begin_x, cursor_x, end_x =
|
|
x_pos, x_pos + cursor_width / 2. + value * (GRAPH_WIDTH - cursor_width),
|
|
x_pos + GRAPH_WIDTH
|
|
|
|
cairo_set_line_width(display, line_width)
|
|
cairo_set_line_cap(display, CAIRO_LINE_CAP_BUTT)
|
|
|
|
-- Beginning of the line
|
|
cairo_move_to(display, begin_x, line_y)
|
|
cairo_line_to(display, cursor_x, line_y)
|
|
cairo_stroke(display)
|
|
|
|
-- Ending of the line
|
|
cairo_set_source_rgba(display, 0.4, 0.4, 0.4, 1)
|
|
cairo_move_to(display, cursor_x, line_y)
|
|
cairo_line_to(display, end_x, line_y)
|
|
cairo_stroke(display)
|
|
|
|
-- Just get back to 'white'
|
|
cairo_set_source_rgba(display, 1, 1, 1, 1)
|
|
|
|
-- Cursor
|
|
cairo_set_line_width(display, cursor_width)
|
|
cairo_move_to(display, cursor_x, line_y - line_width / 2.)
|
|
cairo_line_to(display, cursor_x, line_y + cursor_height)
|
|
cairo_stroke(display)
|
|
|
|
return y_pos + height
|
|
end
|
|
|
|
|
|
-- Specific function to draw our section separation
|
|
local function _draw_section_separation(display, x_pos, y_pos)
|
|
local height = conky_window.height * (2 / 100.)
|
|
local line_width = 3
|
|
local horizontal_space = 100
|
|
|
|
local line_y = y_pos + height / 2.
|
|
local begin_x, end_x =
|
|
x_pos + horizontal_space,
|
|
x_pos + GRAPH_WIDTH - horizontal_space
|
|
|
|
cairo_set_line_width(display, line_width)
|
|
cairo_set_line_cap(display, CAIRO_LINE_CAP_BUTT)
|
|
|
|
cairo_move_to(display, begin_x, line_y)
|
|
cairo_line_to(display, end_x, line_y)
|
|
cairo_stroke(display)
|
|
|
|
return y_pos + height
|
|
end
|
|
|
|
|
|
-- Specific function to draw time & date
|
|
local function _draw_time_date(display, x_pos, y_pos)
|
|
-- Clock for the current time
|
|
local clock_radius = 60
|
|
local clock_border_width = 2
|
|
local clock_center_x = x_pos + COLUMNS_WIDTH / 2. - GLOBAL_CELL_BORDER / 2.
|
|
local clock_center_y = y_pos + clock_radius + clock_border_width
|
|
local gap_border_hour_marks = 5
|
|
local mark_length = 10
|
|
local mark_width = 3
|
|
local second_hand_length = 50
|
|
local second_hand_width = 1
|
|
local minute_hand_length = 50
|
|
local minute_hand_width = 3
|
|
local hour_hand_length = 30
|
|
local hour_hand_width = 5
|
|
|
|
cairo_set_line_width(display, clock_border_width)
|
|
cairo_arc(display, clock_center_x, clock_center_y, clock_radius, 0, 2 * math.pi)
|
|
cairo_stroke(display)
|
|
|
|
local mark_end_rad = clock_radius - gap_border_hour_marks
|
|
local mark_start_rad = mark_end_rad - mark_length
|
|
|
|
cairo_set_line_cap(display, CAIRO_LINE_CAP_ROUND)
|
|
cairo_set_line_width(display, mark_width)
|
|
|
|
local point, radius, x, y
|
|
for i = 1, 12 do
|
|
point = (math.pi / 180.) * ((i - 1) * 30)
|
|
|
|
radius = mark_start_rad
|
|
x, y = radius * math.sin(point), -radius * math.cos(point)
|
|
|
|
cairo_move_to(display, clock_center_x + x, clock_center_y + y)
|
|
|
|
radius = mark_end_rad
|
|
x, y = radius * math.sin(point), -radius * math.cos(point)
|
|
|
|
cairo_line_to(display, clock_center_x + x, clock_center_y + y)
|
|
|
|
cairo_stroke(display)
|
|
end
|
|
|
|
local hours = tonumber(os.date('%I'))
|
|
local hours_to_second = hours * 60 * 60
|
|
|
|
local minutes = tonumber(os.date('%M'))
|
|
local minutes_to_seconds = minutes * 60
|
|
|
|
local seconds = tonumber(os.date('%S'))
|
|
|
|
local hours_seconds = hours_to_second + minutes_to_seconds + seconds
|
|
local hours_seconds_degrees = hours_seconds * (360 / (60. * 60. * 12.))
|
|
|
|
cairo_move_to(display, clock_center_x, clock_center_y)
|
|
|
|
point = (math.pi / 180.) * hours_seconds_degrees
|
|
|
|
radius = hour_hand_length
|
|
x, y = radius * math.sin(point), -radius * math.cos(point)
|
|
|
|
cairo_line_to(display, clock_center_x + x, clock_center_y + y)
|
|
cairo_set_line_width(display, hour_hand_width)
|
|
cairo_set_line_cap(display, CAIRO_LINE_CAP_ROUND)
|
|
cairo_stroke(display)
|
|
|
|
local minutes_seconds = minutes_to_seconds + seconds
|
|
local minutes_seconds_degrees = minutes_seconds * 0.1
|
|
|
|
cairo_move_to(display, clock_center_x, clock_center_y)
|
|
|
|
point = (math.pi / 180.) * minutes_seconds_degrees
|
|
|
|
radius = minute_hand_length
|
|
x, y = radius * math.sin(point), -radius * math.cos(point)
|
|
|
|
cairo_line_to(display, clock_center_x + x, clock_center_y + y)
|
|
|
|
cairo_set_line_width(display, minute_hand_width)
|
|
cairo_set_line_cap(display, CAIRO_LINE_CAP_ROUND)
|
|
cairo_stroke(display)
|
|
|
|
local seconds_degrees = seconds * 6
|
|
|
|
cairo_move_to(display, clock_center_x, clock_center_y)
|
|
|
|
point = (math.pi / 180.) * seconds_degrees
|
|
|
|
radius = second_hand_length
|
|
x, y = radius * math.sin(point), -radius * math.cos(point)
|
|
|
|
cairo_line_to(display, clock_center_x + x, clock_center_y + y)
|
|
cairo_set_line_width(display,second_hand_width)
|
|
cairo_set_source_rgba(display, 1, 0, 0, 1)
|
|
cairo_set_line_cap(display, CAIRO_LINE_CAP_ROUND)
|
|
cairo_stroke(display)
|
|
|
|
-- Just get back to 'white'
|
|
cairo_set_source_rgba(display, 1, 1, 1, 1)
|
|
|
|
y_pos = y_pos + 2 * clock_radius + 2 * clock_border_width
|
|
|
|
-- Text for the current time & date
|
|
return _draw_text(display, os.date("%H:%M:%S, %A %d/%m/%Y"), x_pos, y_pos)
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------
|
|
|
|
-- Specific function to load the actual and maximum brightness values stored in files
|
|
local function _load_brightness(display, x_pos, y_pos)
|
|
local do_update = (
|
|
not brightness_level.value or
|
|
conky_updates % brightness_level.interval == 0)
|
|
if do_update then
|
|
local handle
|
|
|
|
handle = io.open(brightness_level.files.cur_brightness)
|
|
local cur_brightness = tonumber(handle:read('*all'))
|
|
io.close(handle)
|
|
|
|
handle = io.open(brightness_level.files.max_brightness)
|
|
local max_brightness = tonumber(handle:read('*all'))
|
|
io.close(handle)
|
|
|
|
brightness_level.value = cur_brightness / max_brightness
|
|
end
|
|
|
|
return _draw_bar(
|
|
display, {display_name = 'Brightness'},
|
|
x_pos, y_pos, brightness_level.value)
|
|
end
|
|
|
|
|
|
-- Specific function to load the number of updates available in a text file
|
|
local function _load_updates(display, x_pos, y_pos)
|
|
local do_update = (
|
|
not package_updates.value or
|
|
conky_updates % package_updates.interval == 0)
|
|
if do_update then
|
|
local handle = io.popen(package_updates.command)
|
|
if handle then
|
|
package_updates.value = tonumber(handle:read('*all'))
|
|
io.close(handle)
|
|
end
|
|
end
|
|
|
|
return _draw_text(
|
|
display, "Updates: " .. (package_updates.value or '∅') .. " available",
|
|
x_pos, y_pos)
|
|
end
|
|
|
|
|
|
--Specific function to load distribution information
|
|
local function _load_distribution(display, x_pos, y_pos)
|
|
local do_update = (not distribution.value or conky_updates % 1800 == 0)
|
|
if do_update then
|
|
local handle = io.popen(distribution.command)
|
|
distribution.value = string.gsub(handle:read('*all'), '\n', ' ')
|
|
io.close(handle)
|
|
end
|
|
|
|
return _draw_text(
|
|
display,
|
|
conky_parse(string.format('${sysname}')) .. ": " .. distribution.value,
|
|
x_pos, y_pos)
|
|
end
|
|
|
|
|
|
--Specific function to load the public IP address
|
|
local function _load_public_ip(display, x_pos, y_pos)
|
|
local tmp_ip
|
|
|
|
local do_update = (
|
|
(not public_ip.ip and conky_updates % (public_ip.interval / 2) == 0) or
|
|
conky_updates % public_ip.interval == 0)
|
|
if do_update then
|
|
local handle = io.popen(public_ip.command)
|
|
if handle then
|
|
tmp_ip = handle:read('*all')
|
|
io.close(handle)
|
|
|
|
local _, dotCountIPv4 = string.gsub(tmp_ip, '%.', '')
|
|
local _, dotCountIPv6 = string.gsub(tmp_ip, ':', '')
|
|
|
|
-- Little statements to check whether the string is an IPv4 or IPv6 address (maybe ?).
|
|
if dotCountIPv4 == 3 then
|
|
public_ip.ip = tmp_ip
|
|
public_ip.is_v6 = false
|
|
elseif dotCountIPv6 >= 2 and dotCountIPv6 <= 7 then
|
|
public_ip.ip = tmp_ip
|
|
public_ip.is_v6 = true
|
|
else
|
|
public_ip.ip = nil
|
|
end
|
|
end
|
|
else
|
|
tmp_ip = public_ip.ip
|
|
end
|
|
|
|
-- When dealing with an IPv6, let's make it "stream" on the screen a bit...
|
|
if public_ip.ip and public_ip.is_v6 then
|
|
tmp_ip = _stream_ipv6_address(tmp_ip)
|
|
end
|
|
|
|
return _draw_text(
|
|
display, "Public IP: " .. (tmp_ip or "No Address"),
|
|
x_pos, y_pos)
|
|
end
|
|
|
|
|
|
-- Specific function to load author & version text
|
|
local function _load_author_version(display, x_pos, y_pos)
|
|
return _draw_text(
|
|
display, "Horloge\'s script on Conky " .. conky_version,
|
|
x_pos, y_pos)
|
|
end
|
|
|
|
|
|
-- Specific function to load top process
|
|
local function _load_top_process(display, x_pos, y_pos)
|
|
y_pos = _draw_text(display, "NAME PID CPU MEM", x_pos, y_pos)
|
|
|
|
local args = {'name', 'pid', 'cpu', 'mem'}
|
|
|
|
local buffer
|
|
for i = 1, MAX_TOP_PROCESS <= 10 and MAX_TOP_PROCESS or 10 do
|
|
buffer = ""
|
|
for j = 1, #args do
|
|
buffer = buffer .. conky_parse(string.format('${top %s %d}', args[j], i))
|
|
end
|
|
y_pos = _draw_text(display, buffer, x_pos, y_pos)
|
|
end
|
|
|
|
return y_pos
|
|
end
|
|
|
|
|
|
-- Specific function to load different temperatures into 'text'
|
|
local function _load_temperatures(display, x_pos, y_pos)
|
|
local handle, buffer, sensors
|
|
-- We'll be effectively reading the temperature values each 5 iterations
|
|
local do_update = (conky_updates % 5 == 0)
|
|
|
|
-- For CPUs temperatures, we only run one time `sensors`...
|
|
if do_update then
|
|
handle = io.popen("sensors -A | grep \"Core\"")
|
|
sensors = handle:read('*all')
|
|
io.close(handle)
|
|
end
|
|
|
|
-- ... and iterates over each object specified above
|
|
for _, temp_core in pairs(text_temperatures['temp_cores']) do
|
|
if do_update then
|
|
temp_core['value'] = tonumber(string.match(
|
|
sensors, "Core " .. temp_core['id'] .. ":%s+[+|-](%d+.%d+)°.?.*"))
|
|
|
|
-- Manuel Fahrenheit conversion (because `-f` option of `sensors` is too slow...)
|
|
if temp_core['value'] and TEMPERATURE_UNIT == 'F' then
|
|
temp_core['value'] = (temp_core['value'] * 9 / 5.) + 32
|
|
end
|
|
end
|
|
|
|
buffer = "Temperature " .. temp_core['display_name'] .. ": "
|
|
|
|
if temp_core['value'] then
|
|
buffer = buffer .. temp_core['value'] .. '°' .. TEMPERATURE_UNIT
|
|
if temp_core['value'] > temp_core['threshold'] then
|
|
buffer = buffer .. ' /!\\'
|
|
end
|
|
else
|
|
buffer = buffer .. '∅'
|
|
end
|
|
|
|
y_pos = _draw_text(display, buffer, x_pos, y_pos)
|
|
end
|
|
|
|
-- HDD temperatures (with 'hddtemp' daemon running on its default IP & port)
|
|
for _, temp_hdd in pairs(text_temperatures['temp_hdds']) do
|
|
-- It it's the "good" iteration, we update EACH hard drive entry
|
|
if do_update then
|
|
handle = io.popen(
|
|
"hddtemp \"" .. temp_hdd['name'] .. "\" -n -u " .. TEMPERATURE_UNIT)
|
|
temp_hdd['value'] = tonumber(handle:read('*all'))
|
|
io.close(handle)
|
|
end
|
|
|
|
buffer = "Temperature " .. temp_hdd['display_name'] .. ": "
|
|
|
|
if temp_hdd['value'] then
|
|
buffer = buffer .. temp_hdd['value'] .. '°' .. TEMPERATURE_UNIT
|
|
if temp_hdd['value'] > temp_hdd['threshold'] then
|
|
buffer = buffer..' /!\\'
|
|
end
|
|
else
|
|
buffer = buffer .. '∅'
|
|
end
|
|
|
|
y_pos = _draw_text(display, buffer, x_pos, y_pos)
|
|
end
|
|
|
|
return y_pos
|
|
end
|
|
|
|
|
|
-- Generic function to load data in order to print them into 'graph'
|
|
local function _load_graph(display, data, x_pos, y_pos, width)
|
|
local value = tonumber(
|
|
conky_parse(string.format('${%s %s}', data['name'], data['arg'])))
|
|
|
|
-- Sometimes, at startup, the first non-zero 'value' is equal to 'math.mininteger' or 'math.maxinteger'
|
|
-- See issue Conky#340 (https://github.com/brndnmtthws/conky/issues/340)
|
|
-- The following statement is here to avoid a huge line drawn on 'graph' objects...
|
|
if math.abs(value) < 1.e+18 then table.insert(data['values'], value) end
|
|
|
|
return _draw_graph(display, data, x_pos, y_pos, width)
|
|
end
|
|
|
|
|
|
-- Generic function to load data in order to print them into 'text'
|
|
local function _load_text(display, data, x_pos, y_pos)
|
|
local value = conky_parse(string.format('${%s %s}', data['name'], data['arg']))
|
|
|
|
return _draw_text(display, data['display_name'] .. ": " .. value, x_pos, y_pos)
|
|
end
|
|
|
|
|
|
-- This function is here to load data of a hard disk ('graph' + 'text')
|
|
local function _load_read_write_disk(display, graph_disk_read_write, x_pos, y_pos)
|
|
local special_graph_width = GRAPH_WIDTH / 2 - GLOBAL_CELL_BORDER
|
|
local special_graph_x_pos = x_pos + special_graph_width + GLOBAL_CELL_BORDER
|
|
|
|
-- Writes down the interface name
|
|
y_pos = _draw_text(
|
|
display, graph_disk_read_write['display_name'] .. ": Read / Write",
|
|
x_pos, y_pos)
|
|
|
|
-- Set color to 'blue' for read 'graph'
|
|
cairo_set_source_rgba(display, 0 / 255., 127 / 255., 172 / 255., 1)
|
|
_load_graph(
|
|
display, graph_disk_read_write['graph_read'],
|
|
x_pos, y_pos, special_graph_width)
|
|
|
|
-- Set color to 'orange' for write 'graph'
|
|
cairo_set_source_rgba(display, 255 / 255., 114 / 255., 0 / 255., 1)
|
|
y_pos = _load_graph(
|
|
display, graph_disk_read_write['graph_write'],
|
|
special_graph_x_pos, y_pos, special_graph_width)
|
|
|
|
-- Just get back to 'white'
|
|
cairo_set_source_rgba(display, 1, 1, 1, 1)
|
|
|
|
return y_pos
|
|
end
|
|
|
|
|
|
-- This function is here to load data of a network interface ('graph' + 'text')
|
|
local function _load_network_interface(display, graph_network_interface, x_pos, y_pos)
|
|
local if_name = graph_network_interface['graph_download']['arg']
|
|
local if_up = (conky_parse(
|
|
string.format('${if_up %s}1${else}0${endif}', if_name)) == '1')
|
|
if if_up then
|
|
-- A little separation
|
|
y_pos = _draw_section_separation(display, x_pos, y_pos)
|
|
|
|
local special_graph_width = GRAPH_WIDTH / 2 - GLOBAL_CELL_BORDER
|
|
local special_graph_x_pos = x_pos + special_graph_width + GLOBAL_CELL_BORDER
|
|
|
|
-- Writes down the interface name
|
|
y_pos = _draw_text(
|
|
display,
|
|
graph_network_interface['display_name'] .. ": Download / Upload",
|
|
x_pos, y_pos)
|
|
|
|
-- Set color to 'blue' for download 'graph'
|
|
cairo_set_source_rgba(display, 0 / 255., 127 / 255., 172 / 255., 1)
|
|
_load_graph(
|
|
display, graph_network_interface['graph_download'],
|
|
x_pos, y_pos, special_graph_width)
|
|
|
|
-- Set color to 'orange' for upload 'graph'
|
|
cairo_set_source_rgba(display, 255 / 255., 114 / 255., 0 / 255., 1)
|
|
y_pos = _load_graph(
|
|
display, graph_network_interface['graph_upload'],
|
|
special_graph_x_pos, y_pos, special_graph_width)
|
|
|
|
-- Just get back to 'white'
|
|
cairo_set_source_rgba(display, 1, 1, 1, 1)
|
|
|
|
-- Now print the current speed values
|
|
_draw_text(
|
|
display,
|
|
conky_parse(string.format('${downspeedf %s}' .. " KiB", if_name)),
|
|
x_pos + (special_graph_width / 4.), y_pos)
|
|
y_pos = _draw_text(
|
|
display,
|
|
conky_parse(string.format('${upspeedf %s}' .. " KiB", if_name)),
|
|
special_graph_x_pos + (special_graph_width / 4.), y_pos)
|
|
|
|
-- Displays the current interface IP addresses
|
|
local IPv4 = conky_parse(string.format('${addrs %s}', if_name))
|
|
local IPv6 = conky_parse(string.format('${v6addrs %s}', if_name))
|
|
|
|
local addresses
|
|
if IPv4 then
|
|
if IPv4 ~= '0.0.0.0' then
|
|
addresses = string.gmatch(IPv4, '[0-9.]+')
|
|
for address in addresses do
|
|
y_pos = _draw_text(display, "IPv4: " .. address, x_pos, y_pos)
|
|
end
|
|
else
|
|
y_pos = _draw_text(display, "IPv4: No Address", x_pos, y_pos)
|
|
end
|
|
end
|
|
|
|
if IPv6 then
|
|
if IPv6 ~= 'No Address' then
|
|
addresses = string.gmatch(IPv6, '[a-zA-Z0-9:]+')
|
|
for address in addresses do
|
|
y_pos = _draw_text(
|
|
display, "IPv6: " .. _stream_ipv6_address(address),
|
|
x_pos, y_pos)
|
|
end
|
|
else
|
|
y_pos = _draw_text(display, "IPv6: " .. IPv6, x_pos, y_pos)
|
|
end
|
|
end
|
|
end
|
|
|
|
return y_pos
|
|
end
|
|
|
|
|
|
-- Generic function to load data in order to print them into 'bar'
|
|
local function _load_bar(display, data, x_pos, y_pos)
|
|
-- Value between 0 and 1 as we get percentage values from Conky variables
|
|
local value = tonumber(
|
|
conky_parse(string.format('${%s %s}', data['name'], data['arg']))) / 100.
|
|
|
|
return _draw_bar(display, data, x_pos, y_pos, value)
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------
|
|
|
|
|
|
-- THE function which call all the other loading and drawing functions
|
|
local function _load_everything(display)
|
|
-- Initial position, each call updates the `y_pos` in order to place the following elements
|
|
local x_pos = GLOBAL_CELL_BORDER
|
|
local y_pos = 0
|
|
|
|
-- Just set color to 'white'
|
|
cairo_set_source_rgba(display, 1, 1, 1, 1)
|
|
|
|
-- Set the font, and its size only one time
|
|
cairo_select_font_face(
|
|
display, FONT_FAMILY,
|
|
CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL)
|
|
cairo_set_font_size(display, FONT_SIZE)
|
|
|
|
-- Time & Date
|
|
y_pos = _draw_time_date(display, x_pos, y_pos)
|
|
|
|
-- A little separation
|
|
y_pos = _draw_section_separation(display, x_pos, y_pos)
|
|
|
|
-- Hostname
|
|
y_pos = _load_text(display, text_host, x_pos, y_pos)
|
|
-- Distribution details
|
|
y_pos = _load_distribution(display, x_pos, y_pos)
|
|
-- Kernel
|
|
y_pos = _load_text(display, text_kernel, x_pos, y_pos)
|
|
-- Architecture
|
|
y_pos = _load_text(display, text_architecture, x_pos, y_pos)
|
|
-- Uptime
|
|
y_pos = _load_text(display, text_uptime, x_pos, y_pos)
|
|
-- Updates available
|
|
y_pos = _load_updates(display, x_pos, y_pos)
|
|
|
|
-- A little separation
|
|
y_pos = _draw_section_separation(display, x_pos, y_pos)
|
|
|
|
-- Battery bar
|
|
y_pos = _load_bar(display, bar_battery, x_pos, y_pos)
|
|
-- Brightness bar
|
|
y_pos = _load_brightness(display, x_pos, y_pos)
|
|
-- Entropy bar
|
|
y_pos = _load_bar(display, bar_entropy, x_pos, y_pos)
|
|
|
|
-- A little separation
|
|
y_pos = _draw_section_separation(display, x_pos, y_pos)
|
|
|
|
-- Process & Threads
|
|
y_pos = _load_text(display, text_thread, x_pos, y_pos)
|
|
y_pos = _load_text(display, text_running_thread, x_pos, y_pos)
|
|
y_pos = _load_text(display, text_process, x_pos, y_pos)
|
|
y_pos = _load_text(display, text_running_process, x_pos, y_pos)
|
|
|
|
-- A little separation
|
|
y_pos = _draw_section_separation(display, x_pos, y_pos)
|
|
|
|
-- Top process
|
|
y_pos = _load_top_process(display, x_pos, y_pos)
|
|
|
|
-- The following elements will be set in the other column
|
|
x_pos = conky_window.width - COLUMNS_WIDTH
|
|
y_pos = 0
|
|
|
|
-- CPU bars
|
|
y_pos = _load_bar(display, bar_cpu_0, x_pos, y_pos)
|
|
y_pos = _load_bar(display, bar_cpu_1, x_pos, y_pos)
|
|
y_pos = _load_bar(display, bar_cpu_2, x_pos, y_pos)
|
|
y_pos = _load_bar(display, bar_cpu_3, x_pos, y_pos)
|
|
-- RAM bar
|
|
y_pos = _load_bar(display, bar_ram, x_pos, y_pos)
|
|
-- SWAP bar
|
|
y_pos = _load_bar(display, bar_swap, x_pos, y_pos)
|
|
|
|
-- A little separation
|
|
y_pos = _draw_section_separation(display, x_pos, y_pos)
|
|
|
|
-- Disk bars
|
|
y_pos = _load_bar(display, bar_disk_home, x_pos, y_pos)
|
|
y_pos = _load_bar(display, bar_disk_root, x_pos, y_pos)
|
|
-- Flow disk
|
|
y_pos = _load_read_write_disk(display, graph_disk_read_write, x_pos, y_pos)
|
|
|
|
-- A little separation
|
|
y_pos = _draw_section_separation(display, x_pos, y_pos)
|
|
|
|
-- Temperatures
|
|
y_pos = _load_temperatures(display, x_pos, y_pos)
|
|
|
|
-- A little separation
|
|
y_pos = _draw_section_separation(display, x_pos, y_pos)
|
|
|
|
-- Public IP address
|
|
y_pos = _load_public_ip(display, x_pos, y_pos)
|
|
|
|
-- First network interface
|
|
y_pos = _load_network_interface(display, graph_network_interface_1, x_pos, y_pos)
|
|
-- Second network interface
|
|
y_pos = _load_network_interface(display, graph_network_interface_2, x_pos, y_pos)
|
|
|
|
-- A little separation
|
|
y_pos = _draw_section_separation(display, x_pos, y_pos)
|
|
|
|
-- Author & Version
|
|
y_pos = _load_author_version(display, x_pos, y_pos)
|
|
end
|
|
|
|
-----------------------------------------------------------------------------------------
|
|
|
|
|
|
-- MAIN
|
|
function conky_main()
|
|
if not conky_window then return end
|
|
|
|
require('cairo')
|
|
|
|
local surface = cairo_xlib_surface_create(
|
|
conky_window.display, conky_window.drawable, conky_window.visual,
|
|
conky_window.width, conky_window.height)
|
|
if not surface then return end
|
|
|
|
local display = cairo_create(surface)
|
|
if not display then return end
|
|
|
|
conky_updates = tonumber(conky_parse('${updates}'))
|
|
|
|
-- Every 5 updates...
|
|
if conky_updates % 5 == 0 then
|
|
local screen_width, screen_height = SimpleConkyScript.get_screen_definition()
|
|
local border_width = conky_window.border_width + 2 * (
|
|
conky_window.border_inner_margin + conky_window.border_outer_margin)
|
|
|
|
-- ... we check whether the screen definition has changed in order to fetch and fit the new one
|
|
if conky_window.width + border_width ~= screen_width and
|
|
conky_window.height + border_width ~= screen_height then
|
|
-- Let's free the current display and surface
|
|
cairo_destroy(display)
|
|
cairo_surface_destroy(surface)
|
|
|
|
-- We may now make Conky reload its configuration
|
|
signal.raise(signal.SIGHUP)
|
|
|
|
-- We have to leave the main here to avoid a segmentation fault with the operations below
|
|
return
|
|
end
|
|
end
|
|
|
|
-- Loading of the whole list of elements, each update
|
|
if conky_updates > STARTUP_THRESHOLD then _load_everything(display) end
|
|
|
|
-- Delete display and surface before the next update
|
|
cairo_destroy(display)
|
|
cairo_surface_destroy(surface)
|
|
end
|
|
|
|
|
|
return SimpleConkyScript
|