mirror of
https://codeberg.org/dnkl/yambar.git
synced 2025-04-26 04:15:42 +02:00
modules: add temp module
This commit is contained in:
parent
4ff1c43669
commit
9bbe57a306
5 changed files with 292 additions and 0 deletions
|
@ -18,6 +18,7 @@
|
|||
(https://codeberg.org/dnkl/yambar/issues/139).
|
||||
* mem: a module handling system memory monitoring
|
||||
* cpu: a module offering cpu usage monitoring
|
||||
* temp: a module displaying the temperature of the thermal zones in the machine.
|
||||
|
||||
|
||||
### Changed
|
||||
|
|
50
doc/yambar-modules-temp.5.scd
Normal file
50
doc/yambar-modules-temp.5.scd
Normal file
|
@ -0,0 +1,50 @@
|
|||
yambar-modules-temp(5)
|
||||
|
||||
# NAME
|
||||
temp - This module displays the temperature of the thermal zones available on
|
||||
the system
|
||||
|
||||
# TAGS
|
||||
|
||||
[[ *Name*
|
||||
:[ *Type*
|
||||
:[ *Description*
|
||||
| temp
|
||||
: string
|
||||
: Current temperature of a given thermal zone
|
||||
|
||||
# CONFIGURATION
|
||||
|
||||
[[ *Name*
|
||||
:[ *Type*
|
||||
:[ *Req*
|
||||
:[ *Description*
|
||||
| interval
|
||||
: int
|
||||
: no
|
||||
: Refresh interval of the temperature in ms (default=500). Cannot be less then 500 ms
|
||||
| unit
|
||||
: string
|
||||
: no
|
||||
: Unit of the temperature. It can be Celsius (C) or Farenheit (F) (default=C)
|
||||
|
||||
| thermal_zone
|
||||
: int
|
||||
: yes
|
||||
: Identifier of the thermal zone to read
|
||||
|
||||
# EXAMPLES
|
||||
|
||||
```
|
||||
bar:
|
||||
left:
|
||||
- temp:
|
||||
interval: 1000
|
||||
thermal_zone: 0
|
||||
content:
|
||||
string: {text: "{temp}C"}
|
||||
```
|
||||
|
||||
# SEE ALSO
|
||||
|
||||
*yambar-modules*(5), *yambar-particles*(5), *yambar-tags*(5), *yambar-decorations*(5)
|
|
@ -19,6 +19,7 @@ mod_data = {
|
|||
'clock': [[], []],
|
||||
'cpu': [[], []],
|
||||
'mem': [[], []],
|
||||
'temp': [[], []],
|
||||
'i3': [['i3-common.c', 'i3-common.h'], [dynlist, json]],
|
||||
'label': [[], []],
|
||||
'network': [[], []],
|
||||
|
|
238
modules/temp.c
Normal file
238
modules/temp.c
Normal file
|
@ -0,0 +1,238 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <inttypes.h>
|
||||
#include <math.h>
|
||||
#include <poll.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#define LOG_MODULE "temp"
|
||||
#define LOG_ENABLE_DBG 0
|
||||
#define SMALLEST_INTERVAL 500
|
||||
#include "../bar/bar.h"
|
||||
#include "../config-verify.h"
|
||||
#include "../config.h"
|
||||
#include "../log.h"
|
||||
#include "../plugin.h"
|
||||
|
||||
enum temp_unit { TEMP_UNIT_INVALID, TEMP_UNIT_CELSIUS, TEMP_UNIT_FAHRENHEIT };
|
||||
|
||||
struct private
|
||||
{
|
||||
struct particle *label;
|
||||
uint16_t interval;
|
||||
uint16_t thermal_zone;
|
||||
enum temp_unit unit;
|
||||
};
|
||||
|
||||
static void
|
||||
destroy(struct module *mod)
|
||||
{
|
||||
struct private *m = mod->private;
|
||||
m->label->destroy(m->label);
|
||||
free(m);
|
||||
module_default_destroy(mod);
|
||||
}
|
||||
|
||||
static const char *
|
||||
description(struct module *mod)
|
||||
{
|
||||
return "temp";
|
||||
}
|
||||
|
||||
static bool
|
||||
get_temp(uint16_t thermal_zone, enum temp_unit unit, double *temp)
|
||||
{
|
||||
FILE *fp = NULL;
|
||||
char *line = NULL;
|
||||
size_t len = 0;
|
||||
int32_t read_temp = 0;
|
||||
bool res = false;
|
||||
|
||||
ssize_t filename_len = snprintf(NULL, 0, "/sys/class/thermal/thermal_zone%i/temp", thermal_zone);
|
||||
char *filename = malloc(filename_len + 1);
|
||||
snprintf(filename, filename_len + 1, "/sys/class/thermal/thermal_zone%i/temp", thermal_zone);
|
||||
|
||||
fp = fopen(filename, "r");
|
||||
if (NULL == fp) {
|
||||
LOG_ERRNO("unable to open /sys/class/thermal/thermal_zone%i/temp", thermal_zone);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (-1 == getline(&line, &len, fp)) {
|
||||
LOG_ERRNO("unable to get temperature for thermal zone %i", thermal_zone);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (1 != sscanf(line, "%" SCNi32, &read_temp)) {
|
||||
LOG_ERRNO("unable to get temperature for thermal zone %i", thermal_zone);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
switch (unit) {
|
||||
case TEMP_UNIT_CELSIUS:
|
||||
*temp = read_temp / 1000;
|
||||
break;
|
||||
case TEMP_UNIT_FAHRENHEIT:
|
||||
*temp = read_temp;
|
||||
*temp = (*temp * (9 / 5)) + 32;
|
||||
break;
|
||||
default:
|
||||
goto exit;
|
||||
break;
|
||||
}
|
||||
res = true;
|
||||
|
||||
exit:
|
||||
free(line);
|
||||
fclose(fp);
|
||||
|
||||
free(filename);
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct exposable *
|
||||
content(struct module *mod)
|
||||
{
|
||||
const struct private *p = mod->private;
|
||||
double temp = 0;
|
||||
|
||||
if (!get_temp(p->thermal_zone, p->unit, &temp)) {
|
||||
LOG_ERR("unable to retrieve the temperature");
|
||||
}
|
||||
|
||||
struct tag_set tags = {
|
||||
.tags = (struct tag *[]){tag_new_int(mod, "temp", round(temp))},
|
||||
.count = 1,
|
||||
};
|
||||
|
||||
struct exposable *exposable = p->label->instantiate(p->label, &tags);
|
||||
tag_set_destroy(&tags);
|
||||
return exposable;
|
||||
}
|
||||
|
||||
#include <pthread.h>
|
||||
static int
|
||||
run(struct module *mod)
|
||||
{
|
||||
const struct bar *bar = mod->bar;
|
||||
bar->refresh(bar);
|
||||
struct private *p = mod->private;
|
||||
while (true) {
|
||||
struct pollfd fds[] = {{.fd = mod->abort_fd, .events = POLLIN}};
|
||||
|
||||
int res = poll(fds, 1, p->interval);
|
||||
|
||||
if (res < 0) {
|
||||
if (EINTR == errno)
|
||||
continue;
|
||||
LOG_ERRNO("unable to poll abort fd");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (fds[0].revents & POLLIN)
|
||||
break;
|
||||
|
||||
bar->refresh(bar);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum temp_unit
|
||||
str_to_unit(const char *unit_str)
|
||||
{
|
||||
if (0 == strcasecmp(unit_str, "C")) {
|
||||
return TEMP_UNIT_CELSIUS;
|
||||
}
|
||||
|
||||
if (0 == strcasecmp(unit_str, "F")) {
|
||||
return TEMP_UNIT_FAHRENHEIT;
|
||||
}
|
||||
|
||||
return TEMP_UNIT_INVALID;
|
||||
}
|
||||
|
||||
static struct module *
|
||||
temp_new(uint16_t interval, uint16_t thermal_zone, enum temp_unit unit, struct particle *label)
|
||||
{
|
||||
struct private *p = calloc(1, sizeof(*p));
|
||||
p->label = label;
|
||||
p->interval = interval;
|
||||
p->unit = unit;
|
||||
|
||||
struct module *mod = module_common_new();
|
||||
mod->private = p;
|
||||
mod->run = &run;
|
||||
mod->destroy = &destroy;
|
||||
mod->content = &content;
|
||||
mod->description = &description;
|
||||
return mod;
|
||||
}
|
||||
|
||||
static struct module *
|
||||
from_conf(const struct yml_node *node, struct conf_inherit inherited)
|
||||
{
|
||||
const struct yml_node *interval = yml_get_value(node, "interval");
|
||||
const struct yml_node *unit = yml_get_value(node, "unit");
|
||||
const struct yml_node *thermal_zone = yml_get_value(node, "thermal_zone");
|
||||
const struct yml_node *c = yml_get_value(node, "content");
|
||||
|
||||
return temp_new(interval == NULL ? SMALLEST_INTERVAL : yml_value_as_int(interval), yml_value_as_int(thermal_zone),
|
||||
unit == NULL ? TEMP_UNIT_CELSIUS : str_to_unit(yml_value_as_string(unit)),
|
||||
conf_to_particle(c, inherited));
|
||||
}
|
||||
|
||||
static bool
|
||||
conf_verify_interval(keychain_t *chain, const struct yml_node *node)
|
||||
{
|
||||
if (!conf_verify_unsigned(chain, node))
|
||||
return false;
|
||||
|
||||
if (yml_value_as_int(node) < SMALLEST_INTERVAL) {
|
||||
LOG_ERR("%s: interval value cannot be less than %d ms", conf_err_prefix(chain, node), SMALLEST_INTERVAL);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
conf_verify_unit(keychain_t *chain, const struct yml_node *node)
|
||||
{
|
||||
if (!conf_verify_string(chain, node))
|
||||
return false;
|
||||
|
||||
enum temp_unit unit = str_to_unit(yml_value_as_string(node));
|
||||
if (unit == TEMP_UNIT_INVALID) {
|
||||
LOG_ERR("%s: invalid unit, must be C or F", conf_err_prefix(chain, node));
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
verify_conf(keychain_t *chain, const struct yml_node *node)
|
||||
{
|
||||
static const struct attr_info attrs[] = {
|
||||
{"interval", false, &conf_verify_interval},
|
||||
{"thermal_zone", true, &conf_verify_unsigned},
|
||||
{"unit", false, &conf_verify_unit},
|
||||
MODULE_COMMON_ATTRS,
|
||||
};
|
||||
|
||||
return conf_verify_dict(chain, node, attrs);
|
||||
}
|
||||
|
||||
const struct module_iface module_temp_iface = {
|
||||
.verify_conf = &verify_conf,
|
||||
.from_conf = &from_conf,
|
||||
};
|
||||
|
||||
#if defined(CORE_PLUGINS_AS_SHARED_LIBRARIES)
|
||||
extern const struct module_iface iface __attribute__((weak, alias("module_temp_iface")));
|
||||
#endif
|
2
plugin.c
2
plugin.c
|
@ -51,6 +51,7 @@ EXTERN_MODULE(xkb);
|
|||
EXTERN_MODULE(xwindow);
|
||||
EXTERN_MODULE(cpu);
|
||||
EXTERN_MODULE(mem);
|
||||
EXTERN_MODULE(temp);
|
||||
|
||||
EXTERN_PARTICLE(empty);
|
||||
EXTERN_PARTICLE(list);
|
||||
|
@ -140,6 +141,7 @@ init(void)
|
|||
#endif
|
||||
REGISTER_CORE_MODULE(mem, mem);
|
||||
REGISTER_CORE_MODULE(cpu, cpu);
|
||||
REGISTER_CORE_MODULE(temp, temp);
|
||||
|
||||
REGISTER_CORE_PARTICLE(empty, empty);
|
||||
REGISTER_CORE_PARTICLE(list, list);
|
||||
|
|
Loading…
Add table
Reference in a new issue