2 * Copyright (C) 2010-2014 jeanfi@gmail.com
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or (at your option) any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
24 #define _(str) gettext(str)
30 #include <temperature.h>
32 struct psensor *psensor_create(char *id,
36 int values_max_length)
38 struct psensor *psensor;
40 psensor = (struct psensor *)malloc(sizeof(struct psensor));
45 psensor->min = UNKNOWN_DBL_VALUE;
46 psensor->max = UNKNOWN_DBL_VALUE;
50 psensor->values_max_length = values_max_length;
51 psensor->measures = measures_dbl_create(values_max_length);
53 psensor->alarm_high_threshold = 0;
54 psensor->alarm_low_threshold = 0;
56 psensor->cb_alarm_raised = NULL;
57 psensor->cb_alarm_raised_data = NULL;
58 psensor->alarm_raised = 0;
60 psensor->color = NULL;
62 psensor->provider_data = NULL;
63 psensor->provider_data_free_fct = &free;
68 void psensor_values_resize(struct psensor *s, int new_size)
70 struct measure *new_ms, *cur_ms;
73 cur_size = s->values_max_length;
75 new_ms = measures_dbl_create(new_size);
80 for (i = 0; i < new_size - 1 && i < cur_size - 1; i++)
81 measure_copy(&cur_ms[cur_size - i - 1],
82 &new_ms[new_size - i - 1]);
84 measures_free(s->measures);
87 s->values_max_length = new_size;
91 void psensor_free(struct psensor *s)
96 log_debug("Cleanup %s", s->id);
107 measures_free(s->measures);
109 if (s->provider_data && s->provider_data_free_fct)
110 s->provider_data_free_fct(s->provider_data);
115 void psensor_list_free(struct psensor **sensors)
117 struct psensor **sensor_cur;
120 sensor_cur = sensors;
122 while (*sensor_cur) {
123 psensor_free(*sensor_cur);
134 int psensor_list_size(struct psensor **sensors)
137 struct psensor **sensor_cur;
143 sensor_cur = sensors;
145 while (*sensor_cur) {
152 struct psensor **psensor_list_add(struct psensor **sensors,
153 struct psensor *sensor)
156 struct psensor **result;
158 size = psensor_list_size(sensors);
160 result = malloc((size + 1 + 1) * sizeof(struct psensor *));
163 memcpy(result, sensors, size * sizeof(struct psensor *));
165 result[size] = sensor;
166 result[size + 1] = NULL;
171 void psensor_list_append(struct psensor ***sensors, struct psensor *sensor)
173 struct psensor **tmp;
178 tmp = psensor_list_add(*sensors, sensor);
180 if (tmp != *sensors) {
187 struct psensor *psensor_list_get_by_id(struct psensor **sensors, const char *id)
189 struct psensor **sensors_cur = sensors;
191 while (*sensors_cur) {
192 if (!strcmp((*sensors_cur)->id, id))
201 int is_temp_type(unsigned int type)
203 return type & SENSOR_TYPE_TEMP;
207 psensor_value_to_str(unsigned int type, double value, int use_celsius)
213 * should not be possible to exceed 20 characters with temp or
214 * rpm values the .x part is never displayed
218 unit = psensor_type_to_unit_str(type, use_celsius);
220 if (is_temp_type(type) && !use_celsius)
221 value = celsius_to_fahrenheit(value);
223 sprintf(str, "%.0f%s", value, unit);
229 psensor_measure_to_str(const struct measure *m,
231 unsigned int use_celsius)
233 return psensor_value_to_str(type, m->value, use_celsius);
236 void psensor_set_current_value(struct psensor *sensor, double value)
240 if (gettimeofday(&tv, NULL) != 0)
243 psensor_set_current_measure(sensor, value, tv);
246 void psensor_set_current_measure(struct psensor *s, double v, struct timeval tv)
250 (s->values_max_length - 1) * sizeof(struct measure));
252 s->measures[s->values_max_length - 1].value = v;
253 s->measures[s->values_max_length - 1].time = tv;
255 if (s->min == UNKNOWN_DBL_VALUE || v < s->min)
258 if (s->max == UNKNOWN_DBL_VALUE || v > s->max)
261 if (v > s->alarm_high_threshold || v < s->alarm_low_threshold) {
262 if (!s->alarm_raised && s->cb_alarm_raised) {
263 s->alarm_raised = true;
264 s->cb_alarm_raised(s, s->cb_alarm_raised_data);
267 s->alarm_raised = false;
271 double psensor_get_current_value(const struct psensor *sensor)
273 return sensor->measures[sensor->values_max_length - 1].value;
276 struct measure *psensor_get_current_measure(struct psensor *sensor)
278 return &sensor->measures[sensor->values_max_length - 1];
282 Returns the minimal value of a given 'type' (SENSOR_TYPE_TEMP or
285 static double get_min_value(struct psensor **sensors, int type)
287 double m = UNKNOWN_DBL_VALUE;
288 struct psensor **s = sensors;
291 struct psensor *sensor = *s;
293 if (sensor->type & type) {
297 for (i = 0; i < sensor->values_max_length; i++) {
298 t = sensor->measures[i].value;
300 if (t == UNKNOWN_DBL_VALUE)
303 if (m == UNKNOWN_DBL_VALUE || t < m)
314 Returns the maximal value of a given 'type' (SENSOR_TYPE_TEMP or
317 double get_max_value(struct psensor **sensors, int type)
319 double m = UNKNOWN_DBL_VALUE;
320 struct psensor **s = sensors;
323 struct psensor *sensor = *s;
325 if (sensor->type & type) {
329 for (i = 0; i < sensor->values_max_length; i++) {
330 t = sensor->measures[i].value;
332 if (t == UNKNOWN_DBL_VALUE)
335 if (m == UNKNOWN_DBL_VALUE || t > m)
345 double get_min_temp(struct psensor **sensors)
347 return get_min_value(sensors, SENSOR_TYPE_TEMP);
350 double get_min_rpm(struct psensor **sensors)
352 return get_min_value(sensors, SENSOR_TYPE_FAN);
355 double get_max_rpm(struct psensor **sensors)
357 return get_max_value(sensors, SENSOR_TYPE_FAN);
360 double get_max_temp(struct psensor **sensors)
362 return get_max_value(sensors, SENSOR_TYPE_TEMP);
365 const char *psensor_type_to_str(unsigned int type)
367 if (type & SENSOR_TYPE_NVCTRL) {
368 if (type & SENSOR_TYPE_TEMP)
369 return "Temperature";
370 else if (type & SENSOR_TYPE_GRAPHICS)
371 return "Graphics usage";
372 else if (type & SENSOR_TYPE_VIDEO)
373 return "Video usage";
374 else if (type & SENSOR_TYPE_MEMORY)
375 return "Memory usage";
376 else if (type & SENSOR_TYPE_PCIE)
382 if (type & SENSOR_TYPE_ATIADL) {
383 if (type & SENSOR_TYPE_TEMP)
384 return "AMD GPU Temperature";
385 else if (type & SENSOR_TYPE_RPM)
386 return "AMD GPU Fan Speed";
387 /*else type & SENSOR_TYPE_USAGE */
388 return "AMD GPU Usage";
391 if ((type & SENSOR_TYPE_HDD_TEMP) == SENSOR_TYPE_HDD_TEMP)
392 return "HDD Temperature";
394 if ((type & SENSOR_TYPE_CPU_USAGE) == SENSOR_TYPE_CPU_USAGE)
397 if (type & SENSOR_TYPE_TEMP)
398 return "Temperature";
400 if (type & SENSOR_TYPE_RPM)
403 if (type & SENSOR_TYPE_CPU)
406 if (type & SENSOR_TYPE_REMOTE)
409 if (type & SENSOR_TYPE_MEMORY)
416 const char *psensor_type_to_unit_str(unsigned int type, int use_celsius)
418 if (is_temp_type(type)) {
422 } else if (type & SENSOR_TYPE_RPM) {
424 } else if (type & SENSOR_TYPE_PERCENT) {
430 void psensor_log_measures(struct psensor **sensors)
432 if (log_level == LOG_DEBUG)
434 log_debug("Measure: %s %.2f",
436 psensor_get_current_value(*sensors));
442 struct psensor **psensor_list_copy(struct psensor **sensors)
444 struct psensor **result;
447 n = psensor_list_size(sensors);
448 result = malloc((n+1) * sizeof(struct psensor *));
449 for (i = 0; i < n; i++)
450 result[i] = sensors[i];
457 psensor_current_value_to_str(const struct psensor *s, unsigned int use_celsius)
459 return psensor_value_to_str(s->type,
460 psensor_get_current_value(s),