normalize constants naming
[psensor.git] / src / lib / psensor.c
1 /*
2     Copyright (C) 2010-2011 jeanfi@gmail.com
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
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
17     02110-1301 USA
18 */
19
20 #include <stdlib.h>
21 #include <string.h>
22
23 #include <locale.h>
24 #include <libintl.h>
25 #define _(str) gettext(str)
26
27 #include "hdd.h"
28 #include "psensor.h"
29 #include "lmsensor.h"
30
31 struct psensor *psensor_create(char *id, char *name,
32                                unsigned int type, int values_max_length)
33 {
34         struct psensor *psensor
35             = (struct psensor *)malloc(sizeof(struct psensor));
36
37         psensor->id = id;
38         psensor->name = name;
39         psensor->enabled = 1;
40         psensor->min = UNKNOWN_DBL_VALUE;
41         psensor->max = UNKNOWN_DBL_VALUE;
42
43         psensor->type = type;
44
45         psensor->values_max_length = values_max_length;
46         psensor->measures = measures_dbl_create(values_max_length);
47
48         psensor->alarm_limit = 0;
49
50         psensor->cb_alarm_raised = NULL;
51         psensor->cb_alarm_raised_data = NULL;
52         psensor->alarm_raised = 0;
53
54         psensor->alarm_enabled = 0;
55
56         psensor->url = NULL;
57
58         psensor->color = NULL;
59
60         return psensor;
61 }
62
63 void psensor_values_resize(struct psensor *s, int new_size)
64 {
65         struct measure *new_ms, *cur_ms;
66         int cur_size;
67
68         cur_size = s->values_max_length;
69         cur_ms = s->measures;
70         new_ms = measures_dbl_create(new_size);
71
72         if (cur_ms) {
73                 int i;
74                 for (i = 0; i < new_size - 1 && i < cur_size - 1; i++)
75                         measure_copy(&cur_ms[cur_size - i - 1],
76                                      &new_ms[new_size - i - 1]);
77
78                 measures_free(s->measures);
79         }
80
81         s->values_max_length = new_size;
82         s->measures = new_ms;
83 }
84
85 void psensor_free(struct psensor *sensor)
86 {
87         if (sensor) {
88                 free(sensor->name);
89                 free(sensor->id);
90
91                 if (sensor->color)
92                         free(sensor->color);
93
94                 measures_free(sensor->measures);
95
96                 free(sensor->url);
97
98                 free(sensor);
99         }
100 }
101
102 void psensor_list_free(struct psensor **sensors)
103 {
104         struct psensor **sensor_cur;
105
106         if (sensors) {
107                 sensor_cur = sensors;
108
109                 while (*sensor_cur) {
110                         psensor_free(*sensor_cur);
111
112                         sensor_cur++;
113                 }
114
115                 free(sensors);
116
117                 sensors = NULL;
118         }
119 }
120
121 int psensor_list_size(struct psensor **sensors)
122 {
123         int size;
124         struct psensor **sensor_cur;
125
126         if (!sensors)
127                 return 0;
128
129         size = 0;
130         sensor_cur = sensors;
131
132         while (*sensor_cur) {
133                 size++;
134                 sensor_cur++;
135         }
136         return size;
137 }
138
139 int psensor_list_contains_type(struct psensor **sensors, unsigned int type)
140 {
141         struct psensor **s;
142
143         if (!sensors)
144                 return 0;
145
146         s = sensors;
147         while (*s) {
148                 if ((*s)->type == type)
149                         return 1;
150                 s++;
151         }
152
153         return 0;
154 }
155
156 struct psensor **psensor_list_add(struct psensor **sensors,
157                                   struct psensor *sensor)
158 {
159         int size = psensor_list_size(sensors);
160
161         struct psensor **result
162             = malloc((size + 1 + 1) * sizeof(struct psensor *));
163
164         if (sensors)
165                 memcpy(result, sensors, size * sizeof(struct psensor *));
166
167         result[size] = sensor;
168         result[size + 1] = NULL;
169
170         return result;
171 }
172
173 struct psensor *psensor_list_get_by_id(struct psensor **sensors, const char *id)
174 {
175         struct psensor **sensors_cur = sensors;
176
177         while (*sensors_cur) {
178                 if (!strcmp((*sensors_cur)->id, id))
179                         return *sensors_cur;
180
181                 sensors_cur++;
182         }
183
184         return NULL;
185 }
186
187 int is_temp_type(unsigned int type)
188 {
189         return type & SENSOR_TYPE_TEMP;
190 }
191
192 int is_fan_type(unsigned int type)
193 {
194         return type & SENSOR_TYPE_FAN;
195 }
196
197 char *psensor_value_to_string(unsigned int type, double value)
198 {
199         /* should not be possible to exceed 20 characters with temp or
200            rpm values the .x part is never displayed */
201         char *str = malloc(20);
202
203         char *unit;
204
205         if (is_temp_type(type))
206                 unit = "C";
207         else
208                 unit = "";
209
210         sprintf(str, "%.0f%s", value, unit);
211
212         return str;
213 }
214
215 void psensor_set_current_value(struct psensor *sensor, double value)
216 {
217         struct timeval tv;
218
219         if (gettimeofday(&tv, NULL) != 0)
220                 timerclear(&tv);
221
222         psensor_set_current_measure(sensor, value, tv);
223 }
224
225 void
226 psensor_set_current_measure(struct psensor *s,
227                             double v, struct timeval tv)
228 {
229         memmove(s->measures,
230                 &s->measures[1],
231                 (s->values_max_length - 1) * sizeof(struct measure));
232
233         s->measures[s->values_max_length - 1].value.d_num = v;
234         s->measures[s->values_max_length - 1].time = tv;
235
236         if (s->min == UNKNOWN_DBL_VALUE || v < s->min)
237                 s->min = v;
238
239         if (s->max == UNKNOWN_DBL_VALUE || v > s->max)
240                 s->max = v;
241
242         if (s->alarm_limit && s->alarm_enabled) {
243                 if (v > s->alarm_limit) {
244                         if (!s->alarm_raised && s->cb_alarm_raised)
245                                 s->cb_alarm_raised(s,
246                                                    s->cb_alarm_raised_data);
247
248                         s->alarm_raised = 1;
249                 } else {
250                         s->alarm_raised = 0;
251                 }
252         }
253 }
254
255 double psensor_get_current_value(struct psensor *sensor)
256 {
257         return sensor->measures[sensor->values_max_length - 1].value.d_num;
258 }
259
260 struct measure *psensor_get_current_measure(struct psensor *sensor)
261 {
262         return &sensor->measures[sensor->values_max_length - 1];
263 }
264
265 /*
266   Returns the minimal value of a given 'type' (SENSOR_TYPE_TEMP or
267   SENSOR_TYPE_FAN)
268  */
269 double get_min_value(struct psensor **sensors, int type)
270 {
271         double m = UNKNOWN_DBL_VALUE;
272         struct psensor **s = sensors;
273
274         while (*s) {
275                 struct psensor *sensor = *s;
276
277                 if (sensor->enabled && (sensor->type & type)) {
278                         int i;
279                         double t;
280
281                         for (i = 0; i < sensor->values_max_length; i++) {
282                                 t = sensor->measures[i].value.d_num;
283
284                                 if (t == UNKNOWN_DBL_VALUE)
285                                         continue;
286
287                                 if (m == UNKNOWN_DBL_VALUE || t < m)
288                                         m = t;
289                         }
290                 }
291                 s++;
292         }
293
294         return m;
295 }
296
297 /*
298   Returns the maximal value of a given 'type' (SENSOR_TYPE_TEMP or
299   SENSOR_TYPE_FAN)
300  */
301 static double get_max_value(struct psensor **sensors, int type)
302 {
303         double m = UNKNOWN_DBL_VALUE;
304         struct psensor **s = sensors;
305
306         while (*s) {
307                 struct psensor *sensor = *s;
308
309                 if (sensor->enabled && (sensor->type & type)) {
310                         int i;
311                         double t;
312                         for (i = 0; i < sensor->values_max_length; i++) {
313                                 t = sensor->measures[i].value.d_num;
314
315                                 if (t == UNKNOWN_DBL_VALUE)
316                                         continue;
317
318                                 if (m == UNKNOWN_DBL_VALUE || t > m)
319                                         m = t;
320                         }
321                 }
322                 s++;
323         }
324
325         return m;
326 }
327
328 double
329 psensor_get_max_current_value(struct psensor **sensors, unsigned int type)
330 {
331         double m = UNKNOWN_DBL_VALUE;
332         struct psensor **s_cur = sensors;
333
334         while (*s_cur) {
335                 struct psensor *s = *s_cur;
336
337                 if (s->enabled && (s->type & type)) {
338                         double v = psensor_get_current_value(s);
339
340                         if (m == UNKNOWN_DBL_VALUE || v > m)
341                                 m = v;
342                 }
343
344                 s_cur++;
345         }
346
347         return m;
348 }
349
350 double get_min_temp(struct psensor **sensors)
351 {
352         return get_min_value(sensors, SENSOR_TYPE_TEMP);
353 }
354
355 double get_min_rpm(struct psensor **sensors)
356 {
357         return get_min_value(sensors, SENSOR_TYPE_FAN);
358 }
359
360 double get_max_rpm(struct psensor **sensors)
361 {
362         return get_max_value(sensors, SENSOR_TYPE_FAN);
363 }
364
365 double get_max_temp(struct psensor **sensors)
366 {
367         return get_max_value(sensors, SENSOR_TYPE_TEMP);
368 }
369
370 struct psensor **get_all_sensors(int values_max_length)
371 {
372         struct psensor **psensors = NULL;
373         struct psensor **tmp_psensors;
374
375         psensors = lmsensor_psensor_list_add(NULL, values_max_length);
376
377         tmp_psensors = hdd_psensor_list_add(psensors, values_max_length);
378
379         if (tmp_psensors != psensors) {
380                 free(psensors);
381                 psensors = tmp_psensors;
382         }
383
384         if (!psensors) {        /* there is no detected sensors */
385                 psensors = malloc(sizeof(struct psensor *));
386                 *psensors = NULL;
387         }
388
389         return psensors;
390 }
391
392 const char *psensor_type_to_str(unsigned int type)
393 {
394         if (type & SENSOR_TYPE_REMOTE)
395                 return "Remote";
396
397         if (type & SENSOR_TYPE_LMSENSOR_TEMP)
398                 return "Temperature";
399
400         if (type & SENSOR_TYPE_LMSENSOR_FAN)
401                 return "Fan";
402
403         if (type & SENSOR_TYPE_NVIDIA_TEMP)
404                 return "NVidia GPU Temperature";
405
406         if (type & SENSOR_TYPE_AMD_TEMP)
407                 return "AMD GPU Temperature";
408
409         if (type & SENSOR_TYPE_AMD_FAN)
410                 return "AMD GPU Fan Speed";
411
412         if (type & SENSOR_TYPE_HDD_TEMP)
413                 return "HDD Temperature";
414
415         return "N/A";           /* should not be possible */
416 }
417
418
419 const char *psensor_type_to_unit_str(unsigned int type)
420 {
421         if (type & SENSOR_TYPE_TEMP)
422                 return _("C");
423
424         if (type & SENSOR_TYPE_FAN)
425                 return _("RPM");
426
427         return "N/A";
428 }
429
430 void psensor_list_update_measures(struct psensor **sensors)
431 {
432         lmsensor_psensor_list_update(sensors);
433
434         if (psensor_list_contains_type(sensors, SENSOR_TYPE_HDD_TEMP))
435                 hdd_psensor_list_update(sensors);
436 }
437
438 void psensor_init()
439 {
440         lmsensor_init();
441 }
442
443 void psensor_cleanup()
444 {
445         lmsensor_cleanup();
446 }