a1c5e28b3be81a7e49d80b8e94a548f30963d495
[collectd.git] / src / battery.c
1 /**
2  * collectd - src/battery.c
3  * Copyright (C) 2006  Florian octo Forster
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License as published by the
7  * Free Software Foundation; either version 2 of the License, or (at your
8  * option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License along
16  * with this program; if not, write to the Free Software Foundation, Inc.,
17  * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
18  *
19  * Authors:
20  *   Florian octo Forster <octo at verplant.org>
21  **/
22
23 #include "collectd.h"
24 #include "common.h"
25 #include "plugin.h"
26
27 #define MODULE_NAME "battery"
28 #define BUFSIZE 512
29
30 #if defined(KERNEL_LINUX)
31 # define BATTERY_HAVE_READ 1
32 #else
33 # define BATTERY_HAVE_READ 0
34 #endif
35
36 static char *battery_current_file = "battery-%s/current.rrd";
37 static char *battery_voltage_file = "battery-%s/voltage.rrd";
38 static char *battery_charge_file  = "battery-%s/charge.rrd";
39
40 static char *ds_def_current[] =
41 {
42         "DS:current:GAUGE:25:0:U",
43         NULL
44 };
45 static int ds_num_current = 1;
46
47 static char *ds_def_voltage[] =
48 {
49         "DS:voltage:GAUGE:25:0:U",
50         NULL
51 };
52 static int ds_num_voltage = 1;
53
54 static char *ds_def_charge[] =
55 {
56         "DS:charge:GAUGE:25:0:U",
57         NULL
58 };
59 static int ds_num_charge = 1;
60
61 static int   battery_pmu_num = 0;
62 static char *battery_pmu_file = "/proc/pmu/battery_%i";
63
64 static void battery_init (void)
65 {
66 #if BATTERY_HAVE_READ
67         int len;
68         char filename[BUFSIZE];
69
70         for (battery_pmu_num = 0; ; battery_pmu_num++)
71         {
72                 len = snprintf (filename, BUFSIZE, battery_pmu_file, battery_pmu_num);
73
74                 if ((len >= BUFSIZE) || (len < 0))
75                         break;
76
77                 if (access (filename, R_OK))
78                         break;
79         }
80 #endif
81
82         return;
83 }
84
85 static void battery_current_write (char *host, char *inst, char *val)
86 {
87         rrd_update_file (host, battery_current_file, val,
88                         ds_def_current, ds_num_current);
89 }
90
91 static void battery_voltage_write (char *host, char *inst, char *val)
92 {
93         rrd_update_file (host, battery_voltage_file, val,
94                         ds_def_voltage, ds_num_voltage);
95 }
96
97 static void battery_charge_write (char *host, char *inst, char *val)
98 {
99         rrd_update_file (host, battery_charge_file, val,
100                         ds_def_charge, ds_num_charge);
101 }
102
103 #if BATTERY_HAVE_READ
104 static void battery_submit (int batnum, double current, double voltage, double charge)
105 {
106         int len;
107         char buffer[BUFSIZE];
108         char batnum_str[BUFSIZE];
109
110         len = snprintf (batnum_str, BUFSIZE, "%i", batnum);
111         if ((len >= BUFSIZE) || (len < 0))
112                 return;
113
114         if (current > 0.0)
115         {
116                 len = snprintf (buffer, BUFSIZE, "N:%.3f", current);
117
118                 if ((len > 0) && (len < BUFSIZE))
119                         plugin_submit ("battery_current", batnum_str, buffer);
120         }
121
122         if (voltage > 0.0)
123         {
124                 len = snprintf (buffer, BUFSIZE, "N:%.3f", voltage);
125
126                 if ((len > 0) && (len < BUFSIZE))
127                         plugin_submit ("battery_voltage", batnum_str, buffer);
128         }
129
130         if (charge > 0.0)
131         {
132                 len = snprintf (buffer, BUFSIZE, "N:%.3f", charge);
133
134                 if ((len > 0) && (len < BUFSIZE))
135                         plugin_submit ("battery_charge", batnum_str, buffer);
136         }
137 }
138
139 static void battery_read (void)
140 {
141 #ifdef KERNEL_LINUX
142         FILE *fh;
143         char buffer[BUFSIZE];
144         char filename[BUFSIZE];
145         
146         char *fields[8];
147         int numfields;
148
149         int i;
150         int len;
151
152         for (i = 0; i < battery_pmu_num; i++)
153         {
154                 double current = 0.0;
155                 double voltage = 0.0;
156                 double charge  = 0.0;
157
158                 len = snprintf (filename, BUFSIZE, battery_pmu_file, i);
159
160                 if ((len >= BUFSIZE) || (len < 0))
161                         continue;
162
163                 if ((fh = fopen (filename, "r")) == NULL)
164                         continue;
165
166                 while (fgets (buffer, BUFSIZE, fh) != NULL)
167                 {
168                         numfields = strsplit (buffer, fields, 8);
169
170                         if (numfields < 3)
171                                 continue;
172
173                         if (strcmp ("current", fields[0]) == 0)
174                                 current = atof (fields[2]) / 1000;
175                         else if (strcmp ("voltage", fields[0]) == 0)
176                                 voltage = atof (fields[2]) / 1000;
177                         else if (strcmp ("charge", fields[0]) == 0)
178                                 charge = atof (fields[2]) / 1000;
179                 }
180
181                 if ((current != 0.0) || (voltage != 0.0) || (charge != 0.0))
182                         battery_submit (i, current, voltage, charge);
183
184                 fclose (fh);
185                 fh = NULL;
186         }
187 #endif /* KERNEL_LINUX */
188 }
189 #else
190 # define battery_read NULL
191 #endif /* BATTERY_HAVE_READ */
192
193 void module_register (void)
194 {
195         plugin_register (MODULE_NAME, battery_init, battery_read, NULL);
196         plugin_register ("battery_current", NULL, NULL, battery_current_write);
197         plugin_register ("battery_voltage", NULL, NULL, battery_voltage_write);
198         plugin_register ("battery_charge",  NULL, NULL, battery_charge_write);
199 }
200
201 #undef BUFSIZE
202 #undef MODULE_NAME