1 /**
2 * This plug-in helps to monitor the GPS connected to a system.
3 * It reads the data comming from GPSd.
4 It look for the following parameters.
5 */
7 #include "collectd.h"
8 #include "common.h"
9 #include "plugin.h"
11 #if HAVE_GPS_H
12 #include <gps.h>
13 #endif
15 #if HAVE_LIBPTHREAD
16 #include <pthread.h>
17 #endif
19 typedef struct
20 {
21 char *host;
22 char *port;
23 int timeout;
24 } gps_definition_t;
25 static gps_definition_t gps_data_config;
27 typedef struct {
28 int satellites;
29 double vdop;
30 double hdop;
31 } gpsDATA_t;
32 static gpsDATA_t gps_data_read;
35 static const char *config_keys[] =
36 {
37 "Host",
38 "Port",
39 "Timeout"
40 };
41 static int config_keys_num = STATIC_ARRAY_SIZE (config_keys);
44 // Thread items:
45 static pthread_t connector = (pthread_t) 0;
46 static pthread_mutex_t data_mutex = PTHREAD_MUTEX_INITIALIZER;
49 /**
50 * Thread reading from GPSd.
51 */
52 static void * gps_collectd_thread (void * pData)
53 {
54 struct gps_data_t gps_data;
56 while (1)
57 {
58 if (gps_open(gps_data_config.host, gps_data_config.port, &gps_data) < 0)
59 {
60 printf ("cannot connect to: %s:%s", gps_data_config.host, gps_data_config.port);
61 sleep(60);
62 continue;
63 }
65 gps_stream(&gps_data, WATCH_ENABLE | WATCH_JSON, NULL);
67 while (1)
68 {
69 if (gps_waiting (&gps_data, gps_data_config.timeout))
70 {
71 if (gps_read (&gps_data) == -1)
72 {
73 WARNING ("incorrect data.\n");
74 }
75 else {
76 pthread_mutex_lock (&data_mutex);
78 // Dop data:
79 if (isnan(gps_data.dop.vdop) == 0)
80 {
81 gps_data_read.vdop = gps_data.dop.vdop;
82 }
83 if (isnan(gps_data.dop.hdop) == 0)
84 {
85 gps_data_read.hdop = gps_data.dop.hdop;
86 }
88 // Sat in view:
89 if ((gps_data.set & LATLON_SET))
90 {
91 gps_data_read.satellites = gps_data.satellites_used;
92 }
94 pthread_mutex_unlock (&data_mutex);
95 }
96 }
97 }
98 }
100 gps_stream(&gps_data, WATCH_DISABLE, NULL);
101 gps_close(&gps_data);
103 pthread_exit ((void *)0);
104 }
107 /**
108 * Submit the data.
109 */
110 static void gps_collectd_submit (const char *type, gauge_t value)
111 {
112 value_t values[1];
113 value_list_t vl = VALUE_LIST_INIT;
115 values[0].gauge = value;
117 vl.values = values;
118 vl.values_len = 1;
119 sstrncpy (vl.host, hostname_g, sizeof (vl.host));
120 sstrncpy (vl.plugin, "gps", sizeof (vl.plugin));
121 sstrncpy (vl.type, type, sizeof (vl.type));
122 sstrncpy (vl.type_instance, "gps", sizeof (vl.type_instance));
124 plugin_dispatch_values (&vl);
125 }
128 /**
129 * Read the data and submit.
130 */
131 static int gps_collectd_read ()
132 {
133 pthread_mutex_lock (&data_mutex);
134 gps_collectd_submit("gps_hdop", (gauge_t) gps_data_read.hdop);
135 gps_collectd_submit("gps_vdop", (gauge_t) gps_data_read.vdop);
136 gps_collectd_submit("gps_sat", (gauge_t) gps_data_read.satellites);
137 printf ("gps: hdop=%1.3f, vdop=%1.3f, sat=%02d.\n",
138 gps_data_read.hdop,
139 gps_data_read.vdop,
140 gps_data_read.satellites
141 );
142 pthread_mutex_unlock (&data_mutex);
143 return (0);
144 }
147 /**
148 * Read configuration.
149 */
150 static int gps_collectd_config (const char *key, const char *value)
151 {
152 if (strcasecmp (key, "Host") == 0) {
153 if (gps_data_config.host != NULL) free (gps_data_config.host);
154 gps_data_config.host = sstrdup (value);
155 }
156 if (strcasecmp (key, "Port") == 0) {
157 if (gps_data_config.port != NULL) free (gps_data_config.port);
158 gps_data_config.port = sstrdup (value);
159 }
160 if (strcasecmp (key, "Timeout") == 0) {
161 gps_data_config.timeout = (int) strtol (value, NULL, 1000);
162 }
163 return (0);
164 }
167 /**
168 * Init.
169 */
170 static int gps_collectd_init (void)
171 {
172 int err = 0;
174 printf ("gps: will use %s:%s with timeout %d.\n", gps_data_config.host, gps_data_config.port, gps_data_config.timeout);
176 err = plugin_thread_create (&connector, NULL, gps_collectd_thread, NULL);
178 if (err != 0) {
179 WARNING ("pthread_create() failed.");
180 return (-1);
181 }
183 return (0);
184 }
187 /**
188 * Shutdown.
189 */
190 static int gps_collectd_shutdown (void)
191 {
192 if (connector != ((pthread_t) 0)) {
193 pthread_kill (connector, SIGTERM);
194 connector = (pthread_t) 0;
195 }
197 sfree (gps_data_config.port);
198 sfree (gps_data_config.host);
200 return (0);
201 }
203 /**
204 * Register the module.
205 */
206 void module_register (void)
207 {
208 gps_data_config.host = sstrdup ("localhost");
209 gps_data_config.port = sstrdup ("2947");
210 gps_data_read.hdop = 0;
211 gps_data_read.vdop = 0;
212 gps_data_read.satellites = 0;
214 // Read the config params:
215 plugin_register_config ("gps", gps_collectd_config, config_keys, config_keys_num);
216 // Create the thread:
217 plugin_register_init ("gps", gps_collectd_init);
218 // Kill the thread and stop.
219 plugin_register_shutdown ("gps", gps_collectd_shutdown);
220 // Read plugin:
221 plugin_register_read ("gps", gps_collectd_read);
222 }