This module displays the temperature from the thermal zones of the machine
modules: add temperature module #144
aacebedo/yambar:temp-module into master
Nice little module, thanks :)
Note that there's also a CI failure that needs to be fixed.
@ -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.
I'd suggest renaming the module (filename, in documentation - i.e. everywhere) to temperature, to avoid any confusion with e.g. temporary.
corrected
I let some variable named temp (read_temp or enum name for instance). Do you want it to be replaced by temperature too ? (I find temperature being quiet long)
No, that's fine, keep it that way.
@ -0,0 +26,4 @@
| unit
: string
: no
: Unit of the temperature. It can be Celsius (C) or Farenheit (F) (default=C)
I suggest allowing both the short versions, and the long versions:
- C
- Celsuis
- F
- Fahrenheit
corrected
@ -0,0 +42,4 @@
interval: 1000
thermal_zone: 0
content:
string: {text: "{temp}C"}
Let's get fancy and use °C (DEGREE CELSIUS) instead of a simple "C"
Corrected
@ -0,0 +78,4 @@
break;
case TEMP_UNIT_FAHRENHEIT:
*temp = read_temp;
*temp = (*temp * (9 / 5)) + 32;
The 9 / 5 part will be done as an integer division, thus always resulting in 1. This means the compiler will optimize this expression to *temp + 32, which obviously isn't correct.
You need to use floats here instead: 9.0 / 5.0.
My bad I thought the type would have bin infered from the variable type but forgot the parenthesis would have been evaluated before.
Corrected
@ -0,0 +82,4 @@
break;
default:
goto exit;
break;
break not necessary here
corrected by simplify it
@ -0,0 +114,4 @@
return exposable;
}
#include <pthread.h>
Remove this :)
Corrected
@ -0,0 +221,4 @@
static const struct attr_info attrs[] = {
{"interval", false, &conf_verify_interval},
{"thermal_zone", true, &conf_verify_unsigned},
{"unit", false, &conf_verify_unit},
There's a conf_verify_enum() that I think would be more appropriate here (and maybe in the mem/cpu modules as well?)
See the i3 module for an example.
Corrected
f1fa539bb7
9a4062db7c
See comments below.
@ -0,0 +44,4 @@
thermal_zone: 0
content:
string: {text: "{temperature}°C (DEGREE CELSIUS)"}
```
I think we can skip the "(DEGREE CELSIUS)" part... yes? I just mentioned it because it's the name of the Unicode codepoint.
@ -0,0 +97,4 @@
}
struct tag_set tags = {
.tags = (struct tag *[]){tag_new_int(mod, "temperature", round(temperature))},
Wouldn't a float tag be better here?
If it's about presentation, i.e. to be able to display it without decimals, perhaps we should add an :int formatter? Then you could do {string: {text: "{temperature:int}"}}.
Or even better, a way to specify the number of decimals to use. Perhaps {tag:.1}, for 1 decimal?
In fact I was thinking about improving the current system to specify a format and was wondering if you would be ok with it.
Should we let a way to change the entire format string when printing the values ? Or shall we limit the format to the precision ?
I think we could have a security issue if the format given by the user in the tag is directly used in the sprintf function in the *_as_string functions.
For float I am wondering if the %g format specifier is able to add the decimal part depending on the value of it (for .00 it shall not appear).
I don't think allowing a generic printf format string is a good idea. One, we must make sure it's limited to a single argument/value. And two, we need to parse/recognize the formatter, to know whether to call as_int(), as_float() or as_string().
However, a limited set of printf formatters is a good idea. Then we could, optionally, deprecate/remove the current hex and oct formatters.
So, perhaps the right solution is to accept integer, float and string formatters, but not pass them directly to sprintf()? For example, the user shouldn't have to use the correct length modifier. I.e. %d should be enough for an integer (and not %ld).
I think what we'll end up with is:
- Integer formatters: decimal, hex, octal (d, u, o, x, X)
- Float formatters: e, E, f, F, g, G
- String formatters: s
- Flag characters1
- Field width
- Precision modifiers
Now that we have a way of specifying how many digits a float should use, I believe temperature should just be a normal float.
I agree :)
I have been revisiting this, since currently the temperature module is the only thing left in my configuration that's still not a built-in module.
Looking at this implementation, @aacebedo is reading from /sys/class/thermal/thermal_zone*/temp. The issue I have with that is that the thermal_zone only specifies a sort of mysterious "temperature", that we can't easily associate with anything.
I would like to propose that instead, we implement the temperature module based on the hardware monitors: /sys/class/hwmon/hwmon*/.
Those directories contain a lot of things that will be much more helpful to the end user, imo, such as:
- The name of which device is doing the measurement (so you can easily distinguish between
cpu,gpu,nvme, etc. - The critical temperature of each sensor.
This lets us easily offer to the user a lot more configuration. For example:
- we can use a
conditionsto only get the sensors we want. - we can calculate how close a sensor is to its critical temperature, and offer it as a percentage (we must take care in the implementation, since this can technically go over 100%)
- we can calculate which sensor is the closest to its critical temperature, and offer it as a special tag, so people can chose only to display the most heated sensor at a time (I really want this hehehe)
- we can get the fans speed through
fan*_input* - we can get the amount of power being drawn with
power*_average*
And probably more stuff I am not aware of.
At this point, however, I am not sure we should call this new module temperature. Perhaps we should call it hwmon, for "hardware monitor".
What do you think, @dnkl?
- Note these depend on the driver actually offering us that information, which, not all of them do.
I found that in the elixir linux documentation, of all places, we have a pretty good description of everything we can get with hwmon. We don't have to implement everything, to be sure (especially since I personally wouldn't even be able to test everything), but it is good to know nevertheless.
EDIT: ok, I also finally found the official kernel documentation as well: https://www.kernel.org/doc/Documentation/hwmon/sysfs-interface
Apologies for spaming this thread, but I've cooked up a very simple example just to show what the output could look like. Here's what I got in my machine:
nvme
temp1_alarm: 0.000000
temp1_crit: 84850.000000
temp1_input: 45850.000000
temp1_label: 0.000000
temp1_max: 79850.000000
temp1_min: -40150.000000
temp2_input: 59850.000000
temp2_label: 0.000000
temp2_max: 65261848.000000
temp2_min: -273150.000000
temp3_input: 45850.000000
temp3_label: 0.000000
temp3_max: 65261848.000000
temp3_min: -273150.000000
acpitz
temp1_crit: 20800.000000
temp1_input: 16800.000000
temp2_crit: 119000.000000
temp2_input: 27800.000000
coretemp
temp1_crit: 100000.000000
temp1_crit_alarm: 0.000000
temp1_input: 33000.000000
temp1_label: 0.000000
temp1_max: 84000.000000
temp2_crit: 100000.000000
temp2_crit_alarm: 0.000000
temp2_input: 33000.000000
temp2_label: 0.000000
temp2_max: 84000.000000
temp3_crit: 100000.000000
temp3_crit_alarm: 0.000000
temp3_input: 32000.000000
temp3_label: 0.000000
temp3_max: 84000.000000
temp4_crit: 100000.000000
temp4_crit_alarm: 0.000000
temp4_input: 33000.000000
temp4_label: 0.000000
temp4_max: 84000.000000
temp5_crit: 100000.000000
temp5_crit_alarm: 0.000000
temp5_input: 31000.000000
temp5_label: 0.000000
temp5_max: 84000.000000
temp6_crit: 100000.000000
temp6_crit_alarm: 0.000000
temp6_input: 33000.000000
temp6_label: 0.000000
temp6_max: 84000.000000
temp7_crit: 100000.000000
temp7_crit_alarm: 0.000000
temp7_input: 31000.000000
temp7_label: 0.000000
temp7_max: 84000.000000
amdgpu
temp1_crit: 94000.000000
temp1_crit_hyst: -273150.000000
temp1_input: 58000.000000
temp1_label: 0.000000
I used a regex to only get the temperature information. Of course, implementing this well and correctly would be actually a lot more work than the module being proposed in this PR, but, overall, I still think it is worth it (note that i.e. in my silly example temp*_label is being read as a float, not a string, like it should).
@Horus I agree, this would be super nice to have. Can you open a new issue for this? Instead of hijacking this PR...
hwmon seems like a reasonable name. I haven't looked at the details, of what it can offer, but all your suggestions make sense so far.
Hi there. Any update on this? I was hoping to add a temperature module to my yambar.
In case anyone is interested, I created a temperature module for Yambar: yambar-temperature.
It's very basic and just polls the temperatures using libsensors.
This looks sensible to me. One thing I'd request on top of the existing review is to just expose temperature_f and temperature_c tags instead of a configuration to flip between them. If you're interested, feel free to submit to maybar.
- CHANGELOG.md
- modules/meson.build
- plugin.c
View command line instructions
Manual merge helper
Use this merge commit message when completing the merge manually.
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.No due date set.
No dependencies set.
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?