451 lines
18 KiB
Markdown
451 lines
18 KiB
Markdown
# SimpleConkyScript
|
|
|
|
> A fully-customizable Conky script entirely built in Lua
|
|
|
|
![Horloge's Desktop](https://samuel.forestier.app/img/blog/a-laide-du-lua-mon-script-conky-revu-en-beaute.png?v3.0)
|
|
|
|
## Installation
|
|
|
|
```bash
|
|
# Debian (>= 9) example procedure
|
|
sudo apt install conky-all hddtemp lm-sensors lsb-release x11-utils luarocks
|
|
sudo luarocks install luaposix
|
|
sudo luarocks install lua-cjson
|
|
# Note for Debian >= 11 (Lua 5.3), you may wanna freeze version 2.1.0-1 (see <mpx/lua-cjson#56>)
|
|
sudo luarocks install lua-cjson 2.1.0-1
|
|
|
|
sudo sensors-detect --auto
|
|
sudo systemctl enable --now hddtemp.service
|
|
|
|
# Universal section
|
|
mkdir ~/.conky/
|
|
cd ~/.conky/
|
|
git clone https://git.forestier.app/HorlogeSkynet/SimpleConkyScript.git
|
|
cd SimpleConkyScript/
|
|
cp config.json.dist config.json
|
|
```
|
|
|
|
## Usage
|
|
|
|
```bash
|
|
conky -c ~/.conky/SimpleConkyScript/conky.lua
|
|
```
|
|
|
|
## Static Analysis
|
|
|
|
```bash
|
|
sudo luarocks install luacheck
|
|
luacheck .
|
|
```
|
|
|
|
## Configuration Documentation
|
|
|
|
This project is fully-customizable from configuration. It means that you can _safely_ pull latest changes without tweaking any Lua code ( :sunglasses: ).
|
|
The main idea is to describe the content of "columns" displayed on your screen (please refer to the screen-shot above).
|
|
To achieve this, you can either use pre-defined types of entity (detailed below) or tweak global settings.
|
|
|
|
<details>
|
|
<summary>Comprehensive documentation of the `config.json` file</summary>
|
|
<p>
|
|
|
|
The configuration file **must** contain (at least) the `settings` (as long as *all* its children) and the `content` objects.
|
|
|
|
<!-- JS syntax to allow comments in JSON ;-) -->
|
|
|
|
```javascript
|
|
{
|
|
"settings": {
|
|
"conky": {
|
|
// Specific settings related to Conky itself.
|
|
// You can read further information about them here : <https://github.com/brndnmtthws/conky/wiki/Configurations#settings>.
|
|
// Entries present by default are mostly mine, working against a Cinnamon setup.
|
|
},
|
|
// Below objects (as long as their associated entries) are all REQUIRED.
|
|
"timers": {
|
|
// Number of iterations to wait before drawing anything on the screen.
|
|
// It allows Conky to initialize its internals and gather some data before rendering anything.
|
|
// You MAY lower this value at your own risks.
|
|
"startup_threshold": 3,
|
|
|
|
// Number of iterations to wait before checking the user configuration (and reloading Conky if it changed).
|
|
// Use `null` to disable this behavior (default).
|
|
"config_autoreload": null,
|
|
|
|
// Number of iterations to wait before gathering current screen resolutions (and reloading Conky if it changed).
|
|
// This option is very useful if you are used to plug your laptop on a dock or play with multiple screens.
|
|
"resolution_autodetect": null
|
|
},
|
|
"display": {
|
|
// The width (in pixels) of the columns drawn on screen.
|
|
// You MAY lower this value, but don't forget about very long content that could be displayed (i.e. IPv6 addresses).
|
|
"columns_width": 460,
|
|
|
|
// The number of pixels to automatically add between two entities.
|
|
"entity_padding": 7,
|
|
|
|
// A subcommand to be run in order to retrieve the current screen dimensions (output MUST be formatted as `${WIDTH}x${HEIGHT}`).
|
|
"resolution_exec": "xdpyinfo | grep dimensions | tr -s ' ' | cut -d ' ' -f 3"
|
|
},
|
|
"font": {
|
|
// The font size and family to be used when writing down text on the screen.
|
|
// The font family SHOULD be a "Monospaced" one (see <https://en.wikipedia.org/wiki/Monospaced_font>).
|
|
"size": 15,
|
|
"family": "Consolas"
|
|
},
|
|
"colors": {
|
|
// Below colors are defined as RGBA values.
|
|
// Keys speak for themselves.
|
|
"default": [1, 1, 1, 1],
|
|
"clock_second_hand": [1, 0, 0, 1],
|
|
"bar_background": [0.4, 0.4, 0.4, 1],
|
|
"graph_in": [0, 0.5, 0.66, 1],
|
|
"graph_out": [1, 0.5, 0, 1]
|
|
},
|
|
"temperature": {
|
|
// The temperature unit that will be employed.
|
|
// You can either specify `F` for Fahrenheit or `C` for Celsius (default).
|
|
"unit": "C",
|
|
|
|
// The degree symbol that should be set before the unit.
|
|
// Please be careful, the one set by default required you to use a font family supporting Unicode.
|
|
"degree": "°",
|
|
|
|
// The string that will be added to any temperature exceeding the threshold set (see `drive_temperature` & `sensor` entities below).
|
|
"warning": "/!\\"
|
|
}
|
|
},
|
|
"content": {
|
|
// Entities are represented by a list of JSON objects.
|
|
// This first list will describe entities set within the left column.
|
|
"left": [
|
|
{
|
|
// An entity is an object containing at the very least a `type` key.
|
|
// You will find below an exhaustive list of supported `type`.
|
|
//
|
|
// You MAY temporary "hide" any entity by setting the `disabled` key to `true`.
|
|
// This is pretty handy to avoid cutting/pasting content in your JSON.
|
|
//
|
|
// One more important note about configuration values :
|
|
// Only omitting a key or setting its value to `false` would make the option evaluate to `false` in Lua.
|
|
"type": "...",
|
|
"disabled": false
|
|
},
|
|
{
|
|
// This entity will display a clock, as present on the screen-shot above.
|
|
"type": "clock"
|
|
},
|
|
{
|
|
// This entity will render the current date-time and output it as a 'text' object.
|
|
// This is a regular 'text' object underly, so you MAY tweak the `align_center` setting (see `text` entity below).
|
|
// You can check available `format` tokens here : <https://www.lua.org/pil/22.1.html>.
|
|
"type": "date_time",
|
|
"format": "%H:%M:%S, %A %d/%m/%Y",
|
|
"align_center": true
|
|
},
|
|
{
|
|
// This entity will display an horizontal line, allowing you to separate entities and thus creating "blocks".
|
|
// `width` allows you to change the line horizontal dimension, proportionally to the `columns_width` value (fully-optional and defaults to 50%).
|
|
"type": "separator",
|
|
"width": 0.5
|
|
},
|
|
{
|
|
// A typical entity that would evaluate `var` and `arg` through Conky and show the result as a 'text' object.
|
|
// For example, the lines below would produce : "Hostname: ${nodename}".
|
|
//
|
|
// `arg` is fully-optional and MAY be omitted.
|
|
//
|
|
// `align_center` is fully-optional and defaults to `false`.
|
|
"type": "text",
|
|
"var": "nodename",
|
|
"arg": "",
|
|
"name": "Hostname",
|
|
"align_center": false
|
|
},
|
|
{
|
|
// A typical entity that would evaluate `var` and `arg` through Conky and show the result as a 'bar' object.
|
|
// `arg` is fully-optional and MAY be omitted.
|
|
//
|
|
// `show_percent` allows you to add the numerical percentage value next to the `name` of your 'bar' object (disabled by default).
|
|
//
|
|
// You MAY use `bar` with any variable evaluating to a valid percentage.
|
|
"type": "bar",
|
|
"var": "battery_percent",
|
|
"arg": "",
|
|
"name": "Battery",
|
|
"show_percent": false
|
|
},
|
|
{
|
|
// A typical entity that would evaluate `var` and `arg` through Conky and show the result as a 'graph' object.
|
|
// `arg` is fully-optional and MAY be omitted.
|
|
//
|
|
// This entity is really strong, you can actually provide _any_ data to it, as long as it is consistent across time.
|
|
"type": "graph",
|
|
"name": "CPU activity",
|
|
"var": "cpu",
|
|
"arg": "cpu0"
|
|
},
|
|
{
|
|
// This is the most powerful entity currently available.
|
|
// It allows you to execute (synchronously though) a subcommand and show the (STDOUT) result as a 'text' object.
|
|
// For example, on Debian, the lines below MIGHT produce : "Updates: 42 available".
|
|
//
|
|
// `interval` represents the number of iterations to wait before executing the command again (the output is cached).
|
|
// Please be careful, with `update_interval` Conky setting set to 2 seconds, such a command would be executed each 3600 * 2 seconds, or 2 hours.
|
|
// You MAY set `interval` to `null` to completely disable value update (the first obtained output would be kept until reload).
|
|
// Inversely, you MAY set `interval` to `0` (or even omit the entry) to update it during each iteration (use at your own risks).
|
|
//
|
|
// `pre_text` and `post_text` (fully-optional values) allow you to respectively set some texts before and after obtained output.
|
|
// `align_center` acts as described above for `text` entities.
|
|
//
|
|
// When the command fails, `on_error` content will be displayed.
|
|
"type": "command",
|
|
"exec": "apt list --upgradable -qq 2> /dev/null | wc -l",
|
|
"name": "Updates",
|
|
"interval": 3600,
|
|
"pre_text": "",
|
|
"post_text": " available",
|
|
"align_center": false,
|
|
"on_error": "Not detected"
|
|
},
|
|
{
|
|
// `brightness` is a very specific entity.
|
|
// Through `cur_file` and `max_file`, it computes a brightness percentage ratio and produces a 'bar' object.
|
|
// You SHOULD specify an `interval` to avoid opening and reading two files during each iteration.
|
|
//
|
|
// For this entity, `name` is fully-optional and defaults to "Brightness" when not specified.
|
|
//
|
|
// `show_percent` is also available and MAY be tweaked.
|
|
//
|
|
// Please be careful, distributed file paths MAY NOT work on your system.
|
|
// You MAY run `ls -l /sys/class/backlight/` to check what is actually available on your system.
|
|
"type": "brightness",
|
|
"name": "Brightness",
|
|
"cur_file": "/sys/class/backlight/intel_backlight/actual_brightness",
|
|
"max_file": "/sys/class/backlight/intel_backlight/max_brightness",
|
|
"interval": 10,
|
|
"show_percent": false
|
|
},
|
|
{
|
|
// This entity allows you to show a 'top'-like output for processes, based on their CPU usage.
|
|
// `max_processes` MAY be set between `1` and `10` (defaults to `10`).
|
|
"type": "top_processes",
|
|
"max_processes": 5
|
|
},
|
|
{
|
|
/* ... */
|
|
}
|
|
],
|
|
// This second list will describe entities set within the middle column.
|
|
"middle": [
|
|
{
|
|
/* ... */
|
|
}
|
|
],
|
|
// This third list will describe entities set within the right column.
|
|
"right": [
|
|
{
|
|
// This entity relies entirely on the LM-SENSORS program.
|
|
// It underly uses a `sensors` call to retrieve temperature information from a chip.
|
|
// The identifier of the `chip` to prompt MUST be specified and could be found by manually running `sensors -A`.
|
|
// The final displayed value corresponds to the chip temperature input(s) average.
|
|
//
|
|
// `is_fan` is fully-optional and defaults to `false`.
|
|
//
|
|
// `interval` acts as described for `command` type entity (see above).
|
|
//
|
|
// `threshold` represents the maximum temperature value that could be reached before adding the symbol specified in `settings.temperature.warning` (see above).
|
|
// You can either specify a Celsius or Fahrenheit value, as long as it is consistent to the unit specified in `settings.temperature.unit` (see above too).
|
|
//
|
|
// When no temperature could be retrieved or computed, `on_error` will be displayed.
|
|
"type": "sensor",
|
|
"name": "CPUs",
|
|
"chip": "coretemp-isa-0000",
|
|
"is_fan": false,
|
|
"interval": 5,
|
|
"threshold": 70,
|
|
"on_error": "Not detected"
|
|
},
|
|
{
|
|
// On the same idea, you may provide a fan speed control `chip` as long as `is_fan` is set to `true`.
|
|
// The final displayed value corresponds to the chip fan speed input(s) average, in RPM (Revolutions per minute).
|
|
//
|
|
// `threshold` represents the maximum fan speed value that could be reached before adding the symbol specified in `settings.temperature.warning` (see above).
|
|
//
|
|
// When no fan speed could be retrieved or computed, `on_error` will be displayed.
|
|
"type": "sensor",
|
|
"name": "Dell SMM",
|
|
"chip": "dell_smm-virtual-0",
|
|
"is_fan": true,
|
|
"interval": 5,
|
|
"threshold": 5400,
|
|
"on_error": "Not detected"
|
|
},
|
|
{
|
|
// This entity works as the `sensor` above, but relies on the HDDTEMP program.
|
|
// You'll have to specify the path to the targeted `drive`.
|
|
//
|
|
// `wake_up` allows you to force drive wake up (when needed) to measure its temperature (disabled by default).
|
|
//
|
|
// `interval`, `threshold` and `on_error` acts as described for the `sensor` type entity (see above).
|
|
"type": "drive_temperature",
|
|
"drive": "/dev/sda",
|
|
"wake_up": false,
|
|
"interval": 5,
|
|
"threshold": 60,
|
|
"on_error": "Not detected"
|
|
},
|
|
{
|
|
// This entity is a handy wrapper to the 'bar' entity.
|
|
// By specifying any partition `mount_point`, it will display a 'bar' representing its usage.
|
|
// `show_percent` acts as described above for `bar` entities.
|
|
"type": "partition_usage",
|
|
"mount_point": "/home",
|
|
"show_percent": false
|
|
},
|
|
{
|
|
// This entity will display two graphs representing the I/O rate of the specified `drive`.
|
|
// To set graphs colors, please refer to `settings.colors.graph_{in,out}`.
|
|
"type": "drive_io",
|
|
"drive": "/dev/sda"
|
|
},
|
|
{
|
|
// This entity will display two graphs representing the I/O rate of the specified network `interface`.
|
|
// As `drive_io` above, please refer to `settings.colors.graph_{in,out}` to set graphs colors.
|
|
//
|
|
// Please be careful, such an entity will be skipped when the interface is down (see `if_up_strictness` for further information).
|
|
"type": "network_interface_io",
|
|
"interface": "enp0s25"
|
|
},
|
|
{
|
|
// This entity will display each IP addresses associated to the specified network `interface`.
|
|
// `hide_v6` allows you to hide any IPv6 address (disabled by default).
|
|
//
|
|
// Please be careful, such an entity will be skipped when the interface is down (see `if_up_strictness` for further information).
|
|
"type": "network_interface_addr",
|
|
"interface": "enp0s25",
|
|
"hide_v6": false
|
|
},
|
|
{
|
|
// This entity is a disguised 'text' object.
|
|
// It allows you to show Conky version, with `{pre,post}_text` (acting as with the `command` entity).
|
|
// It could be very useful to give you credits on screen-shot for instance.
|
|
//
|
|
// `align_center` is available and acts as described above.
|
|
"type": "version",
|
|
"pre_text": "Horloge's script on ",
|
|
"post_text": "",
|
|
"align_center": true
|
|
},
|
|
{
|
|
/* ... */
|
|
}
|
|
]
|
|
}
|
|
}
|
|
```
|
|
|
|
</p>
|
|
</details>
|
|
|
|
## Frequently asked questions
|
|
|
|
### My Conky does not work, it \[insert your very specific issue details here\]. What should I do ?
|
|
|
|
Please, refer to the [official Conky's FAQ](https://github.com/brndnmtthws/conky/wiki/FAQ) first.
|
|
If you can't find anything helpful, please [contact me](mailto:samuel+dev@forestier.app) with your configuration and Conky terminal output attached.
|
|
|
|
### Your script is cool but I'd like to install it elsewhere. How could I achieve that ?
|
|
|
|
You'll have to tweak your `conky` execution with an additional environment variable :
|
|
|
|
```bash
|
|
CONKY_PATH="/another/script/location" conky -c "${CONKY_PATH}/conky.lua"
|
|
```
|
|
|
|
> Rationale : There is no way to fetch the project location from the configuration file itself (`conky.lua`).
|
|
> Fortunately for us, we may read Conky environment variables directly from Lua !
|
|
|
|
A simple Bash wrapper is also packaged :
|
|
|
|
```bash
|
|
bash run_scs.sh
|
|
```
|
|
|
|
### How can I get the same background image ?
|
|
|
|
Sorry, it has been deleted [upstream](https://unsplash.com/photos/44t1AZNIMIE) by its [owner](https://unsplash.com/@vanschneider).
|
|
I'm not sure if I am allowed to redistribute copy of it now :confused:
|
|
|
|
### My device drive temperature is not displayed !
|
|
|
|
Yeah it happens sometimes when the `hddtemp` daemon is not properly configured.
|
|
Simply run the command below to enable the SUID bit, and leave other options with their default value :
|
|
|
|
```bash
|
|
sudo dpkg-reconfigure hddtemp
|
|
```
|
|
|
|
### The console reads `sh: 1: hddtemp: not found`
|
|
|
|
Same as above.
|
|
|
|
### How can I contribute to this project ?
|
|
|
|
At the moment, **SimpleConkyScript** is not open to public contributions.
|
|
However, you may send patches to [samuel+dev@forestier.app](mailto:samuel+dev@forestier.app), I'll personally take the time to review them.
|
|
|
|
### What could I achieve from the configuration file ?
|
|
|
|
Well, the only limit is your imagination. Some examples :
|
|
|
|
#### Wanna ping and probe a Minecraft server for the current number of players ?
|
|
|
|
Sure, first run :
|
|
|
|
```bash
|
|
pip3 install mcstatus
|
|
```
|
|
|
|
... and then add a new entry block containing :
|
|
|
|
```json
|
|
{
|
|
"type": "command",
|
|
"exec": "python3 -c 'from mcstatus import MinecraftServer; server = MinecraftServer(\"YOUR.MINECRAFT.SERVER\"); status = server.status(); print(\"{}/{} ({} ms)\".format(status.players.online, status.players.max, server.ping()))'",
|
|
"name": "Minecraft server",
|
|
"interval": 300,
|
|
"on_error": "Can't be reached"
|
|
}
|
|
```
|
|
|
|
#### Wanna ping and probe a Mumble server for current number of users and bandwidth ?
|
|
|
|
> From: <https://github.com/mumble-voip/mumble-scripts/blob/master/Non-RPC/mumble-ping.py>
|
|
|
|
```json
|
|
{
|
|
"type": "command",
|
|
"exec": "python3 -c 'from datetime import datetime; from struct import pack, unpack; from socket import AF_INET, SOCK_DGRAM, socket; s = socket(AF_INET, SOCK_DGRAM); s.sendto(pack(\">iQ\", 0, datetime.now().microsecond), (\"YOUR.MUMBLE.SERVER\", 64738)); r, _ = s.recvfrom(1024); r = unpack(\">bbbbQiii\", r); t = (datetime.now().microsecond - r[4]) / 1000.0; print(\"{}/{} ({} ms, {} Kbits/s)\".format(r[5], r[6], round(t + (1000 if t < 0 else 0), 2), r[7] / 1000))'",
|
|
"name": "Mumble server",
|
|
"interval": 300,
|
|
"on_error": "Can't be reached"
|
|
}
|
|
```
|
|
|
|
#### Wanna display the number of unread RSS items from your News Nextcloud app ?
|
|
|
|
```json
|
|
{
|
|
"type": "command",
|
|
"exec": "python3 -c 'NC_ADDR = \"https://YOUR.NEXTCLOUD.SERVER/\"; NC_CREDS = (\"USERNAME\", \"PASSWORD\"); from json import loads; from base64 import b64encode; from urllib.parse import urljoin; from urllib.request import Request, urlopen; print(len(loads(urlopen(Request(url=urljoin(NC_ADDR, \"apps/news/api/v1-2/items?getRead=false\"), headers={\"Authorization\": \"Basic {}\".format(b64encode(\"{}:{}\".format(*NC_CREDS).encode()).decode())})).read().decode())[\"items\"]))'",
|
|
"name": "Unread RSS items",
|
|
"interval": 300,
|
|
"on_error": "Can't be reached"
|
|
},
|
|
```
|
|
|
|
## Acknowledgments
|
|
|
|
* To [NAERNON](https://github.com/NAERNON) for the code structure, design and ideas
|
|
* To [Nelis Oostens](https://github.com/brndnmtthws/conky/wiki/Using-Lua-scripts-(Part-12)%3A-Clock-and-circular-things) for his clock's code, and the Lua section of Conky's wiki
|