1 #include <sys/socket.h>
2 #include <sys/types.h>
3 #include <sys/time.h>
4 #include <asm/types.h>
5 #include <arpa/inet.h>
6 #include <linux/if_packet.h>
7 #include <linux/if_ether.h> /* The L2 protocols */
8 #include <linux/if_arp.h>
9
10 #include <libdev/packet_dev.h>
11 #include <link/link.h>
12 #include <medsensor.h>
13 #include <string.h>
14
15 // for db
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include "libpq-fe.h" // for libpq
19
20 // for options
21 #include <getopt.h>
22
23 // for my e-mail hack
24 #include <sys/time.h>
25 #include <time.h>
26
27 // local #defines
28 #define TEMP_BUFFER_SIZE 1024
29 #define DEFAULT_PROXY_LOCATION "Office, John"
30
31 typedef struct {
32 // for the database connection
33 char conninfo[TEMP_BUFFER_SIZE];
34 PGconn *conn;
35 PGresult *res;
36 char *database_name; // database name
37 char *proxy_location; // location of the proxy
38 } database_state_t;
39
40 typedef struct {
41 pd_client_context_t* pdc_ref; // to connect to packet device
42 status_context_t *status_ref; // status device context
43 database_state_t dbinfo; // information about the connection to the backend
44 char *iface_name; // pointer to the interface name
45 } medsensor_db_ctx_t;
46
47
48 static int medsensor_db_print(status_context_t *info, buf_t *buf);
49 static int medsensor_pktdev_recv(void *data, ssize_t len, pd_client_context_t *pd_client);
50 static char *get_mac_addr(char *iface_name, char *macaddr /* output addr */);
51 static char *get_ip(char *interface, char *ip_addr /* output addr */);
52
53 static void
54 exit_nicely(PGconn *conn)
55 {
56 PQfinish(conn);
57 exit(1);
58 }
59
60 // status device callbacks
61 static
62 int medsensor_db_print(status_context_t *info, buf_t *buf)
63 {
64 bufprintf(buf, "medsensor_dbconnect: alive\n");
65 return STATUS_MSG_COMPLETE;
66 }
67
68 /* TO RECEIVE data from the named packet device client */
69 static
70 int medsensor_pktdev_recv(void *data, ssize_t len, pd_client_context_t *pd_client)
71 {
72 medsensor_db_ctx_t *medsensor_db_state = (medsensor_db_ctx_t *) pdc_data(pd_client);
73 medsensor_temp_pkt_t *med_pkt = (medsensor_temp_pkt_t *) data;
74 database_state_t *dbinfo = &(medsensor_db_state->dbinfo);
75
76 PGconn *conn = dbinfo->conn;
77 PGresult *res;
78
79 char command[1024]; // more hardcoded stuff
80 char mac_addr[100]; // mac address
81 char ip_addr[100]; // mac address
82 char timebuf[100]; // for storing the time
83
84 /* // for timestamping */
85 /* static struct timeval curr_time, last_time, diff_time; */
86
87 /* // check the time */
88 /* curr_time = med_pkt->rcv_time; */
89 /* if(timerisset(&last_time)) { */
90 /* timersub(&curr_time, &last_time, &diff_time); */
91 /* elog(LOG_NOTICE, "seconds elapsed: %lu\n", diff_time.tv_sec); */
92 /* } else { */
93 /* last_time = curr_time; */
94 /* } */
95
96 /* // copy the data over into my local buffer */
97 /* // hardcoded hack */
98 strftime(timebuf, 100, "%F %T", localtime(&(med_pkt->rcv_time.tv_sec)));
99 sprintf(timebuf, "%s.%ld", timebuf, med_pkt->rcv_time.tv_usec);
100 char *proxy_time = &timebuf[0];
101
102 /* if(diff_time.tv_sec >= (30 * 60)) { */
103 /* FILE *remindfile; */
104 /* if((remindfile = fopen("remindfile", "w")) == NULL) { */
105 /* sprintf(temp_buf, "Could not open %s", "/root/remindfile"); */
106 /* perror(temp_buf); */
107 /* goto out; */
108 /* } */
109
110
111 /* fprintf(remindfile, "Time: %s\n", timebuf); */
112 /* fprintf(remindfile, "Sensor Type: Temp, "); */
113 /* fprintf(remindfile, "Sensor Value: %d, ", med_pkt->dataValue); */
114 /* fprintf(remindfile, "Sample Number: %d\n", med_pkt->sampleNumber); */
115 /* fprintf(remindfile, "Mote ID Number: %d\n", med_pkt->moteSrcId); */
116 /* fprintf(remindfile, "\nWhat were you doing during this sample?\n"); */
117 /* fclose(remindfile); */
118
119 /* // execute my script */
120 /* if(system("devel/mm/stream/testtabs/mail-remind.pl remindfile dcurtis@csail.mit.edu") < 0) { */
121 /* perror("mail-remind.pl failed"); */
122 /* goto out; */
123 /* } */
124 /* } */
125
126 /*
127 sensor_type text, -- a constant enum identifying sensor type
128 sensor_value integer, -- value returned by this sensor
129 sample_number integer, -- lets us know if samples were dropped
130 mote_id integer, -- id of the mote
131 proxy_id macaddr, -- MAC address of the device
132 proxy_time timestamp with time zone,
133 proxy_location text -- readable name of current location of proxy
134 */
135 // another hack, only send the data if the database and the sensor id's match
136
137 elog(LOG_NOTICE, "moteSrcId: %d, Database Name: %s\n", med_pkt->moteSrcId, dbinfo->database_name);
138
139 if((dbinfo->database_name != NULL) &&
140 ((med_pkt->moteSrcId < 100 &&
141 strcmp(dbinfo->database_name, "med_db0") == 0) ||
142 (med_pkt->moteSrcId >= 100 && med_pkt->moteSrcId < 200 &&
143 strcmp(dbinfo->database_name, "med_db1") == 0) ||
144 (med_pkt->moteSrcId >= 200 && med_pkt->moteSrcId < 300 &&
145 strcmp(dbinfo->database_name, "med_db2") == 0))) {
146
147 sprintf(command, "INSERT INTO rawtest0 (sensor_type, sensor_value,sample_number, mote_id, proxy_id, proxy_time, proxy_location, ip_addr) VALUES ('%s',%d,%d,%d,'%s','%s','%s', '%s');",
148 "Temp",
149 med_pkt->dataValue,
150 med_pkt->sampleNumber,
151 med_pkt->moteSrcId,
152 get_mac_addr(medsensor_db_state->iface_name, mac_addr),
153 proxy_time,
154 dbinfo->proxy_location,
155 get_ip(medsensor_db_state->iface_name, ip_addr)
156 );
157 elog(LOG_NOTICE, "Executing [%s]\n", command);
158
159 if(dbinfo->database_name != NULL) {
160 res = PQexec(conn, command);
161 if (PQresultStatus(res) != PGRES_COMMAND_OK) {
162 fprintf(stderr, "INSERT failed: %s", PQerrorMessage(conn));
163 PQclear(res);
164 exit_nicely(conn);
165 }
166 PQclear(res);
167 }
168 }
169
170 // out:
171 /* free buffer and packet */
172 free(data);
173 return EVENT_RENEW;
174 }
175
176 /*
177 * Shutdown handler
178 */
179 static
180 void medsensor_db_shutdown(void *data)
181 {
182 elog(LOG_NOTICE, " MedSensor DB Connect Client is shutting down\n");
183 exit(0);
184 }
185
186 void usage(const char *s)
187 {
188 fprintf(stderr,
189 "Usage: %s --interface <device it is using> --database <name of database> --location <device location>\n"
190 "\n",
191 s);
192 exit(1);
193 }
194
195 int
196 main(int argc, char *argv[])
197 {
198
199 // for the options
200 int c;
201 char *iface_name = NULL;
202 char *database_name = NULL;
203 char *location = NULL;
204
205 /* int digit_optind = 0; */
206
207 medsensor_db_ctx_t medsensor_db_state = {};
208 PGconn *conn;
209
210 /* emrun will trigger this callback to run on shutdown */
211 emrun_opts_t emrun_opts = {
212 shutdown: medsensor_db_shutdown,
213 data: &medsensor_db_state // don't know why this is here;
214 };
215
216 // process options
217 while(1) {
218 /* int this_option_optind = optind ? optind : 1; */
219 int option_index = 0;
220 static struct option long_options[] = {
221 {"database", 1, 0, 0},
222 {"interface", 1, 0, 0},
223 {"location", 1, 0, 0},
224 };
225
226 c = getopt_long(argc, argv, "d:i:l:", long_options, &option_index);
227 if (c == -1) {
228 break;
229 }
230
231 switch (c) {
232 case 'd':
233 database_name = optarg;
234 elog(LOG_NOTICE, "database = %s", optarg);
235 break;
236 case 'i':
237 iface_name = optarg;
238 elog(LOG_NOTICE, "interface = %s", optarg);
239 break;
240 case 'l':
241 location = optarg;
242 elog(LOG_NOTICE, "location = %s", optarg);
243 break;
244 default:
245 elog(LOG_CRIT, "unrecognized option 0%o ??\n", c);
246 exit(1);
247 }
248 }
249
250 if (optind < argc) {
251 elog(LOG_NOTICE, "unrecognized options: ");
252 while(optind < argc) {
253 elog(LOG_NOTICE, "%s", argv[optind++]);
254 }
255 usage(argv[0]);
256 }
257
258 if(iface_name == NULL) {
259 usage(argv[0]);
260 }
261
262 if(location == NULL) {
263 location = DEFAULT_PROXY_LOCATION;
264 elog(LOG_NOTICE, "location = %s", location);
265 }
266
267 // fill in the db_state data structure
268 medsensor_db_state.iface_name = iface_name;
269 medsensor_db_state.dbinfo.proxy_location = location;
270 medsensor_db_state.dbinfo.database_name = database_name;
271
272 if(database_name != NULL) {
273 sprintf(medsensor_db_state.dbinfo.conninfo, "host=18.31.0.20 dbname=%s user=med_user0 password=pcn13579", database_name);
274 medsensor_db_state.dbinfo.conn = PQconnectdb(medsensor_db_state.dbinfo.conninfo);
275 conn = medsensor_db_state.dbinfo.conn; // for convenience
276 // open the link to the database
277 elog(LOG_NOTICE, "Opening database connection, %s", medsensor_db_state.dbinfo.conninfo);
278
279 /* Check to see that the backend connection was successfully made */
280 if (PQstatus(conn) != CONNECTION_OK) {
281 fprintf(stderr, "Connection to database '%s' failed.\n", PQdb(conn));
282 fprintf(stderr, "%s", PQerrorMessage(conn));
283 exit_nicely(conn);
284 }
285 }
286
287 // setup the interface to the packet device
288 {
289 pd_client_opts_t pdc_opts = {
290 devname: MEDSENSOR_PACKET_DEV, // device name of the packet device?
291 receive: medsensor_pktdev_recv,
292 data: &medsensor_db_state
293 };
294
295 elog(LOG_NOTICE, "opening pktdev from client");
296
297 /* Open the link */
298 if (pd_client_open(&pdc_opts, &(medsensor_db_state.pdc_ref)) < 0) {
299 elog(LOG_CRIT, "Unable to open pktdev %s: %m", pdc_opts.devname);
300 exit(1);
301 }
302 }
303
304 // setup status device
305 {
306 status_dev_opts_t status_opts = {
307 device: {
308 devname: MEDSENSOR_DB_STATUS_DEV,
309 device_info: &medsensor_db_state
310 },
311 printable: medsensor_db_print
312 };
313
314 if(g_status_dev(&status_opts, &(medsensor_db_state.status_ref)) < 0) {
315 elog(LOG_CRIT, "Unable to create status device: %m");
316 exit(1);
317 }
318 }
319
320 emrun_init(&emrun_opts);
321 g_main();
322 elog(LOG_ALERT, "event system terminated abnormally");
323 return 1;
324
325 }
326
327 static char *
328 get_mac_addr(char *iface_name, char *mac_addr /* output addr */)
329 {
330 int s; // socket
331 struct ifreq buffer;
332 char tempbuf[TEMP_BUFFER_SIZE]; // temporary storage
333
334 s = socket(PF_INET, SOCK_DGRAM, 0);
335 if(s < 0) {
336 elog(LOG_CRIT, "Could not open socket!");
337 exit(1);
338 }
339
340 memset(&buffer, 0, sizeof(buffer));
341 snprintf(buffer.ifr_name, sizeof(buffer.ifr_name), "%s", iface_name);
342 if (ioctl(s, SIOCGIFHWADDR, &buffer) != 0) {
343 elog(LOG_CRIT, "ioctl(SIOCGIFHWADDR)");
344 sprintf(tempbuf, "%s\n", buffer.ifr_name);
345 perror(tempbuf);
346 close(s);
347 exit(1);
348 }
349
350 mac_addr[0] = 0;
351 close(s);
352 for(s = 0; s < 6; s++) { // length of mac address
353 sprintf(tempbuf, "%.2X:", (unsigned char)buffer.ifr_hwaddr.sa_data[s]);
354 strcat(mac_addr, tempbuf);
355 }
356 mac_addr[strlen(mac_addr) - 1] = 0; // get rid of last :
357
358 return mac_addr;
359 }
360
361
362 static
363 char* get_ip(char* interface, char* buf) {
364
365 int s;
366 struct ifreq ifr;
367
368 /* ----------------------------------------------- */
369 /* Check buffer sanity */
370 /* ----------------------------------------------- */
371 if ( !buf ) return 0;
372 buf[0] = 0;
373
374 /* ----------------------------------------------- */
375 /* Open a socket to get access to ioctl functions */
376 /* ----------------------------------------------- */
377 s = socket(AF_INET,SOCK_DGRAM,0);
378 if(s < 0) {
379 elog(LOG_CRIT, "Could not open socket!");
380 exit(1);
381 }
382
383 /* ----------------------------------------------- */
384 /* Grab the eth0 interface info */
385 /* ----------------------------------------------- */
386 bzero((void*)(&ifr.ifr_name),sizeof(ifr.ifr_name));
387 strncpy(ifr.ifr_name,interface,sizeof(ifr.ifr_name));
388 if ( ioctl(s,SIOCGIFADDR,&ifr) != 0 ) {
389 close(s);
390 return 0;
391 }
392 close(s);
393
394 strcpy(buf,inet_ntoa((*(struct sockaddr_in *)&ifr.ifr_addr).sin_addr));
395
396 return buf;
397 }
398
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.