2 * collectd - src/apple_sensors.c
3 * Copyright (C) 2006 Florian octo Forster
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.
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.
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
20 * Florian octo Forster <octo at verplant.org>
26 #include "utils_debug.h"
28 #define MODULE_NAME "apple_sensors"
34 #if HAVE_MACH_MACH_TYPES_H
35 # include <mach/mach_types.h>
37 #if HAVE_MACH_MACH_INIT_H
38 # include <mach/mach_init.h>
40 #if HAVE_MACH_MACH_ERROR_H
41 # include <mach/mach_error.h>
43 #if HAVE_MACH_MACH_PORT_H
44 # include <mach/mach_port.h>
46 #if HAVE_COREFOUNDATION_COREFOUNDATION_H
47 # include <CoreFoundation/CoreFoundation.h>
49 #if HAVE_IOKIT_IOKITLIB_H
50 # include <IOKit/IOKitLib.h>
52 #if HAVE_IOKIT_IOTYPES_H
53 # include <IOKit/IOTypes.h>
56 #if HAVE_IOKIT_IOKITLIB_H
57 # define IOKIT_HAVE_READ 1
59 # define IOKIT_HAVE_READ 0
62 #if HAVE_IOKIT_IOKITLIB_H
63 static mach_port_t io_master_port = MACH_PORT_NULL;
66 static char *temperature_file = "apple_sensors/temperature-%s.rrd";
67 static char *fanspeed_file = "apple_sensors/fanspeed-%s.rrd";
69 static char *ds_def[] =
71 "DS:value:GAUGE:"COLLECTD_HEARTBEAT":U:U",
74 static int ds_num = 1;
76 static void as_init (void)
81 if (io_master_port != MACH_PORT_NULL)
83 mach_port_deallocate (mach_task_self (),
85 io_master_port = MACH_PORT_NULL;
88 status = IOMasterPort (MACH_PORT_NULL, &io_master_port);
89 if (status != kIOReturnSuccess)
91 syslog (LOG_ERR, "IOMasterPort failed: %s",
92 mach_error_string (status));
93 io_master_port = MACH_PORT_NULL;
96 #endif /* IOKIT_HAVE_READ */
101 static void as_write (char *host, char *inst, char *val, const char *template)
106 status = snprintf (filename, 256, template, inst);
107 if ((status < 1) || (status >= 256))
110 rrd_update_file (host, filename, val, ds_def, ds_num);
113 static void temperature_write (char *host, char *inst, char *val)
115 as_write (host, inst, val, temperature_file);
118 static void fanspeed_write (char *host, char *inst, char *val)
120 as_write (host, inst, val, fanspeed_file);
124 static void as_submit (char *type, char *inst, double value)
128 if (snprintf (buf, 1024, "%u:%f", (unsigned int) curtime,
132 plugin_submit (type, inst, buf);
135 static void as_read (void)
137 kern_return_t status;
138 io_iterator_t iterator;
140 CFMutableDictionaryRef prop_dict;
149 if (!io_master_port || (io_master_port == MACH_PORT_NULL))
152 status = IOServiceGetMatchingServices (io_master_port,
153 IOServiceNameMatching("IOHWSensor"),
155 if (status != kIOReturnSuccess)
157 syslog (LOG_ERR, "IOServiceGetMatchingServices failed: %s",
158 mach_error_string (status));
162 while ((io_obj = IOIteratorNext (iterator)))
165 status = IORegistryEntryCreateCFProperties (io_obj,
169 if (status != kIOReturnSuccess)
171 DBG ("IORegistryEntryCreateCFProperties failed: %s",
172 mach_error_string (status));
176 /* Copy the sensor type. */
178 if (!CFDictionaryGetValueIfPresent (prop_dict,
182 if (CFGetTypeID (property) != CFStringGetTypeID ())
184 if (!CFStringGetCString (property,
186 kCFStringEncodingASCII))
190 /* Copy the sensor location. This will be used as `instance'. */
192 if (!CFDictionaryGetValueIfPresent (prop_dict,
196 if (CFGetTypeID (property) != CFStringGetTypeID ())
198 if (!CFStringGetCString (property,
200 kCFStringEncodingASCII))
203 for (i = 0; i < 128; i++)
207 else if (isalnum (inst[i]))
208 inst[i] = (char) tolower (inst[i]);
213 /* Get the actual value. Some computation, based on the `type'
216 if (!CFDictionaryGetValueIfPresent (prop_dict,
217 CFSTR ("current-value"),
220 if (CFGetTypeID (property) != CFNumberGetTypeID ())
222 if (!CFNumberGetValue (property,
227 /* Found e.g. in the 1.5GHz PowerBooks */
228 if (strcmp (type, "temperature") == 0)
230 value_double = ((double) value_int) / 65536.0;
231 strncpy (type, "apple_temperature", 128);
233 else if (strcmp (type, "temp") == 0)
235 value_double = ((double) value_int) / 10.0;
236 strncpy (type, "apple_temperature", 128);
238 else if (strcmp (type, "fanspeed") == 0)
240 value_double = ((double) value_int) / 65536.0;
241 strncpy (type, "apple_fanspeed", 128);
243 else if (strcmp (type, "voltage") == 0)
245 /* Leave this to the battery plugin. */
248 else if (strcmp (type, "adc") == 0)
250 value_double = ((double) value_int) / 10.0;
251 strncpy (type, "apple_temperature", 128);
255 DBG ("apple_sensors: Read unknown sensor type: %s",
257 value_double = (double) value_int;
260 as_submit (type, inst, value_double);
262 CFRelease (prop_dict);
263 IOObjectRelease (io_obj);
264 } /* while (iterator) */
266 IOObjectRelease (iterator);
269 # define as_read NULL
270 #endif /* IOKIT_HAVE_READ */
272 void module_register (void)
274 plugin_register (MODULE_NAME, as_init, as_read, NULL);
275 plugin_register ("apple_temperature", NULL, NULL, temperature_write);
276 plugin_register ("apple_fanspeed", NULL, NULL, fanspeed_write);