41
Distributed Rain Sensing Network Senior Capstone Design Final Report Professor Pompili Denis Poznykov Orestis Kotzias Walid Al Jabowbi Vladimir Samokhin May 9, 2012

Capstone Final Report RAIN SENSOR - WINLAB Home Pagecrose/capstone12/entries/RainNet_Final.pdf · Final Report Professor Pompili Denis Poznykov Orestis Kotzias ... that happens, a

  • Upload
    lammien

  • View
    216

  • Download
    0

Embed Size (px)

Citation preview

Distributed Rain Sensing Network

Senior Capstone Design Final Report

Professor Pompili

Denis Poznykov Orestis Kotzias Walid Al Jabowbi Vladimir Samokhin May 9, 2012

Project Description. This project is collaboration between department of electrical engineering and civil and environmental engineering on sensing and modeling extreme weather events. Such events have profound effects on the sustainability of urban centers. At the same time human activities are increasing the variability of the climate and increasing the frequency of these events; driving the need for more dynamic decision-making tools. The overall objective of this research is to address urban sustainability through the development of modeling methods suitable for forecasting environmental phenomena in a changing world, and through the development of technology that can enable autonomous infrastructure to adapt to rapidly evolving environmental conditions. This research will focus on rainfall estimation and measure success by the ability to provide accurate rainfall estimates at high resolutions. Professor David Hill from Civil and Environmental Engineering has proposed the research. We worked closely with the graduate student – Cagdas Karatas and were supervised by Dr. Dario Pompili. Motivation Currently all of the rainfall data is acquired either by radar or by satellite. The satellite presents an estimated precipitation by measuring the area of the cloud. Radar, on the contrary measures the falling rain dynamically. This technique has been successfully used for many years. However, both radar and satellite predict rainfall over large areas, and quite often the actual precipitation varies largely over that area. This low spatial resolution estimation does not provide the data necessary for flood predictions. One way to solve that problem and get an accurate data about precipitation is to develop portable and mobile rain gauges that are cost efficient and can operate for years with minimum maintenance. (Figure 1) Those rain sensors can provide very accurate high-resolution rainfall estimation and help in the early detections of flooding. They can also be utilized to dynamically calibrate the radar readings. Unfortunately with quality comes a high price tag. The proposed solution is to take advantage of ubiquitous rain sensors being used in every-day consumer products. Since 2006, many vehicles began integrating simple precipitation sensors to automatically turn on the wipers. Those sensors are cheap, however they are not very accurate. The idea however is to take advantage of the multitude of those sensors, being implemented on more and more vehicles every year. The high density of the sensors is expected to compensate for lack of precision, and still deliver useful data. Figure 1: Different methods of determining precipitation. As can be seen Satellite and Radar provide estimation, while rain sensors provide more accurate data.

Team’s Contributions The project consisted of three stages: Building a network, testing the network and modeling data, and utilizing the network to be more efficient. We have completed the first two stages of the project in which we have built a network of sensors. Each one includes an independent power source using solar cells and power storage. Each sensor will be able to collect, compute, and send data to its parent router, which is then sent up the hierarchy on the network for further processing. (Figure 2) We have tested 4 sensors on the initial stage and they are fully operational. The second stage of the project was to build a database for the data and a website to be able to model data. The website’s main interface consists of a map with locations of each sensor and a link to a graph of the data collected by that sensor. The current implementation uses Google maps to achieve this functionality. The third stage is to expand the network to more than 10 sensors and optimize the data collection algorithms by implementing the proposed SILENCE paper. This paper presents a data-centric approach to distributed adaptive sampling aimed at minimizing the communication and processing overhead in autonomic networked sensor- based systems. The proposed solution exploits the spatiotemporal correlation in sensed data and eliminates redundancy in transmitted data through selective representation without compromising on accuracy of reconstruction of the monitored phenomenon at a remote monitor node. In addition, the solution also exploits the same correlations for adaptive sleep scheduling aimed at saving energy in Wireless Sensor Networks (WSNs) while also providing a mechanism for ensuring connectivity to the monitor node. In order to Implement Silence, the network structure has to be reconstructed to utilize the Xbee MESH standard. This means more efficient power use and data collection algorithms.

Figure 2. Jennet Network follows a tree topology, which we utilize with our sensors.

Jennet framework modifications In this project we have been using rain sensors combined with Jennet JN5148 model microcontrollers. Those microcontrollers are highly adequate for the job due to their wireless communication and ability to control it. Another reason why those microcontrollers are optimal is because of their low power consumption. Those chips can operate with less than 3.6V using less than 32mA, not to mention this is in operation mode with wireless transmission and receiving. In sleep mode, the current use drops to less than 3µA. Using those nodes, allowed us for the initial acquisition and analysis of data. Jennet modules are run on Jennet Framework. This framework allows you to program all the end devices, routers and the coordinator. The original framework which was available at the Jennet website took care of most of our needs, however we still needed to add some changes to the code. After making some initial changes to the code, we were able to receive the readings from all the sensors, which include tick count from the rain sensor, humidity, temperature, and light data. Special hot keys were implemented which allows the user to easily turn on/off the needed sensor, for example turning off just the light sensor and keeping the rest on. Furthermore, the incoming data is now parsed to separate the reading from different sensors. This parsing is very helpful for visualizing data on the website. After the initial functions of our sensor network were met, we started thinking of ways to decrease power consumptions. Currently we are utilizing 6-volt batteries to

power the end devices. Each end device is also equipped with a solar panel mounted on top of the enclosure. Even though the solar panel should provide enough charge to keep the battery live for weeks, we realized that that was not the case in practice. Due to modules being constantly turned on, they would quickly drain the batteries, causing us to loose transmission when it was most needed. To solve this problem we added a sleeping function to the Jennet framework. The sleeping function allows the end devices to go to sleep and therefore conserve energy while data is not being collected. We found multiple ways to implement that function. A user can customize both the length and the frequency when the device goes to sleep. However, if the device is put to sleep for over 7 seconds, it needs to boot in cold start mode. Cold start means that once the device is turned on it needs to search for local router and coordinator and send requests to connect before it can initiate the data transfer. On the other hand if the device is only asleep for 7 seconds, it can boot in Warm Start Mode, allowing it instantaneously receive and send data packets to router/coordinator. Other than implementing the sleeping function, we also plan to decrease the frequency at which the end devices transmit data. Currently they transmit data every 2 seconds. That will be changed to transmitting once every 5 min, which should be sufficient to collect accurate data, while decreasing the power consumption significantly. Finally, we began work on implementing the SILENCE. After reading the paper and talking to the graduate students, the algorithm seems fairly simple. Basically, nodes will be able to communicate with each other, sending local control messages. Those messages will contain the actual data collected by individual node. Then, this data will be compared and each node will be able to decide its state and sleeping schedule independently based on correlation and similarity of its own sampled data with that of the neighbor nodes. If the correlation and similarity is within user specified parameters, only one of the nodes will be assigned as a Representative, while the rest will become Associates. Representative will collect and report data on behalf of the group, while associates will be able to go sleep, preserving their power. Associates would still wake up periodically to check if the correlation is still within the parameters. Figure 3 displays the sample network of 13 modules, as they will be distributed on Busch Campus. In an example of SILENCE concept, only the 3 magnified nodes are transmitting the data, while the neighboring nodes are sleeping. This protocol will be essential in allowing the nodes to be self sustained for prolonged periods of time, as it will be able to reduce power consumption without compromising the accuracy. However, one thing that is needed in order to write it and test it is a larger network, of perhaps 10 or so nodes, collecting actual data. Therefore, unfortunately we will not be able to complete that before the end of the semester. Figure 3. A proposed network of modules on Busch Campus

Encapsulation of hardware One of the initial problems that we ran into was not having proper encapsulation for our end device modules. The encapsulation had to be completely airtight to prevent any water from leaking in or humidifying inside. The box had to be big enough to fit the module itself (Figure 4), as well as the battery. The rain sensor and the solar panel were to be mounted outside the box. A tipping bucket sensor is used in this project. It works on a very simple principle. As the rain falls down, it is being caught in the head of the bucket and funneled onto a tipping scale. As one side of the scale fills up with liquid, it tips down and pours the water out, at the same time raising the other side of the scale. As that happens, a proximity sensor registers a tick, which the module records. (Figure 5) Each tick is equivalent to 0.01 inches of precipitation. The rain gauge being used is one of the most accurate ones available on the market. It can register precipitation on the scale from 0.01 to 100 inches per hour, and is ready to withstand prolonged exposure to the elements without corroding or malfunctioning. We were determined to find a proper enclosure for the module, which would be able to last as long as the rain gauge, once it is deployed. In the beginning we did not give much thought to this seemingly trivial problem and used simple plastic enclosures. After initial tests, and sad realization that the boxes were leaking, we decided to reinforce them with duck plaster, hot glue, and large amounts of tape. This process proved to be both inefficient, as it took hours to seal the box, and ineffective, as the box would still leak. Finally we were able to find and

purchase industrial airtight boxes, which, once we tested them proved to be completely water resistant! Another issue that we were faced with was the lack of consistent transmission. The Jennet devices come with 3 different wireless networking modules. Two of them are short-range modules, rated to have radius of 1 km, and long range modules designed for 4 km transmission. However, after testing the modules ourselves. We saw that the short-range modules work well only up to 200 m, while the long-range module was tested up to 700m. Even though those parameters are less than those advertised, that is not a problem, as we should still be able to cover our initial are of Busch Campus. The problem arises when the line of sight between router/coordinator and the end device is obstructed. Any small obstruction, such as tree branches, causes the signal to be lost. Initially, as the end devices will only be installed on rooftops, this should not pose any problems, but if those sensors will someday be deployed on the ground, this transmission issue would need to resolved. Figure 4. Jennet board with a long-range networking module

Figure 5. The tipping scale inside of the tipping bucket rain gauge

Visualization

The visualization of the rain sensors is web based allowing anyone with an Internet connection device to view the data acquired by the rain sensors and do their own analysis. The website – www.rurainnet.com is stored on and ran from a dedicated server. The home page of the web site is an interactive Google map which displays a marker for each sensor that are color coded based on the current rainfall at that location. (Figure 3) The user can scroll around the map, zoom in and out, and even see satellite imagery for the location. When the user clicks on one of the markers an information bubble pops up containing information about the sensor. (Figure 4) Precipitation rate, temperature, light intensity, and humidity from the last sample are displayed along with the time the sample was taken. Additionally the user can click the “historical data” link to go to a web page containing a graph of historical data at that sensor. The data is displayed using an interactive time line using Google Charts. The user can zoom in on a specific time period to study patterns. (Figure 5) Additionally the user can download a file containing the data, which can be imported into many programs such as Microsoft Excel and Mathworks Matlab to perform further analysis. Figure 6. The home page of the visualization website uses an interactive Google map which displays active sensors.

Figure 7. Clicking on the desired rain sensor can pull up the information bubble.

There are 3 modules for visualization: The data collector which interacts with the sensor network, a MySQL database which stores the data, the web-server which hosts the website, and, to a lesser extent, the end client's computer which renders data. These modules can all run on separate machines as long as they are all networked (either on a local network or even via the internet). The data collector module is a C program, which can be compiled for many different architectures in the Linux environment. If at any time, the user is allowed to add more sensors to the network. The script will prompt the user as it checks for additional sensors. It will also report an error back to the user if no additional sensor is found. This process can be reversed to remove any sensor desired by the user. The sensor network sends data to the collector using a RS 232 serial port and the data collector puts it into the MySQL database. It requires very little processor time and about 1kB of memory so any modern machine will be able to run it. The MySQL database keeps a record of all of the sensors and keeps track of every report generated by the sensors. The web-server is structure in PHP it gathers data from the database and sends a script to the client, which uses Google Maps and Google Charts to visualize data. As an error-checking feature, the web-server checks if variables exist or not whenever a function is executed. This is important so the web-server doesn’t freeze and notifies the user for errors. Only the last 3 weeks of data are visualized in order to keep server load

down. If desired the user can download all of the data in a file. Data files are generated on request by the server and deleted when the download completes.

Figure 8. Data displaying previous rainfalls can be accessed online and downloaded per user’s request.

Another step approaching serial communication is with Visual C-Sharp. With this, Visual creates windows based boxes and functions are that can control serial communication settings. Settings such as baud rate, stop bit, and data bits are set that control the incoming data’s structure. The baud rate is one of the most important, in which it controls the speed of serial communication. Less transmits essentially can use less energy. The stop bit is a bit that disconnects the communication from the network. The data bits the number of bits used to represent a character of data. This should vary for our tick sensor, which should be allowed to count a number in the thousands for precipitation rate. As for temperature, humidity, and light intensity these data bits can be set low because the incoming data should be a common scaled values. With Visual, the user can easily setup settings within seconds and save. Once done, the user is allowed to read in incoming data on a text screen and vice versa send data with only clicking buttons.

Future implementations For now, a larger network of modules needs to be constructed and deployed on Busch campus. Collecting more data will allow to work out all the challenges that we are still facing. Those include data loss due to obstruction in the line of sight, as well as preserving the battery power by decreasing transmission frequency and redundant data transfers. Once this test bed is fully operational, it can be easily scaled up as modules can be installed in different locations. The locations can be stationary, such as rooftops, or moving, such as on top of Rutgers’ busses. This would allow for collecting dynamic precipitation data of a high spatial resolution. Furthermore, this research can be then used to utilize new advances in ubiquitous sensing in order to improve our capability to monitor the weather. Small, low cost sensors that are being embedded in every-day consumer products, specifically automobile wipers, can be repurposed to provide information regarding the weather at the location of the sensor. Those sensors are not nearly as accurate as our tipping bucket rain gauge, as they only have 3-5 different levels of precipitation measurements. Even so, it seems very feasible to compensate for that lack of accuracy with very high density of deployment of the sensors. Hopefully this research can demonstrate feasibility and benefits of such systems and will entice both government interest and outside investors. We strongly believe that utilizing ubiquitous sensors will be very beneficial, cost efficient way of flood prediction and rain data accumulation! Summary This has a very interesting topic and research. We believe each one of us has worked hard and learned a lot! It gives us a great pleasure to actually have something tangible to show for our final semester as undergraduates. We have a number of working modules, which hopefully will be installed all over Busch campus and will help in continuation of this research. We also have a functioning website, which serves as a great demonstration of the capabilities of the rain sensing network. We are sure that this research will be carried on by other students, as there is still a lot to do, but we are very thankful for having had the opportunity to be the initial contributors! Project Personnel Denis Poznykov – [email protected] Walid Al Jabowbi – [email protected] Orestis Kotzias – [email protected] Vladimir Samokhin – [email protected] Capstone Section Ranking Sensor, Control and DSP Systems (Pompili -- 332:418) Teammate Qualifications Denis Poznykov 332:417, 332: 463, 332:472, 332:423 Walid Al Jabowbi 332:437 Orestis Kotzias 332:417, 332: 463, 332:472

Vladimir Samokhin - 198:214, 198:352, 332:351, 332:343, 198:416, 332:452, 332:437 Bibliography SILENCE: Distributed Adaptive Sampling for Sensor-based Autonomic Systems, Eun Kyung Lee, Hariharasudhan Viswanathan, and Dario Pompili JenNet Stack User Guide, JN-UG-3041, Revision 2.0, 28 September 2010 Downscaling Radar-Rainfall Data via Ubiquitous Sensing and Data Fusion, D.J. Hill and F. Farzan

Appendix / Codes Developed

Add  /  Remove  Sensor  (  C  )     add_sensor.c    *  add_sensor.c    *    *  A  short  program  to  add  information  about  another  sensor  to    *  the  sql  database.    Requires  user  to  be  precise  with  requests    *  in  order  to  preserve  database  integrity.    */      #include  <mysql/mysql.h>  #include  <stdlib.h>  #include  <stdio.h>    #define  SQL_HOST  "mysql.sadionline.com"  #define  SQL_USR  "waleed25"  #define  SQL_PASSWORD  "Walid234"    #define  SQL_PORT  0    int  main(int  argc,  char  **argv)  {     int  addr;     MYSQL  *mysql;     MYSQL_RES  *result;     double  latt,  longe,  conv;     char  MODIFY=0;     char  query_str[512];       if(argc!=5  &&  argc!=6)     {       printf("invocation:  add_sensor  <address(hex)>  <latitude>  <longitude>  <conversion>  <-­‐m(modify,  optional)\n");       exit(0);     }         if(argc==6  &&  argv[5][0]=='-­‐'  &&  argv[5][1]=='m')     {       MODIFY=1;     }     else  if(argc==6)     {  

    printf("invocation:  add_sensor  <address(hex)>  <latitude>  <longitude>  <conversion>  <-­‐m(modify,  optional)\n");       exit(0);     }         //scan  arguments     if(sscanf(argv[1],  "%x",  &addr)!=1  ||  sscanf(argv[2],  "%lf",  &latt)!=1  ||  sscanf(argv[3],  "%lf",  &longe)!=1  ||         sscanf(argv[4],  "%lf",  &conv)!=1)     {       printf("invocation:  add_sensor  <address(hex)>  <latitude>  <longitude>  <conversion>  <-­‐m(modify,  optional)\n");       exit(0);     }         //initialize  connection     mysql=mysql_init(0);     if(mysql_real_connect(mysql,  SQL_HOST,  SQL_USR,  SQL_PASSWORD,  "rain_sensors",  SQL_PORT,  0,  0)==0)     {       printf("%s:  error  connecting  to  database\n",  argv[0]);       exit(1);     }         //if  modify  remove  the  row     if(MODIFY==1)     {       sprintf(query_str,  "SELECT  *  FROM  nodes  WHERE  addr=%d;",  addr);       mysql_query(mysql,  query_str);       result=mysql_store_result(mysql);       //See  if  result  is  already  stored       if(mysql_num_rows(result)==0)       {         printf("%s:  Sensor  %x  not  found.    Retry  without  -­‐m  flag\n",  argv[0],  addr);         exit(0);       }       //Idiot  check  to  see  if  more  than  one  entry  for  address  exists(should't  happen)       else  if(mysql_num_rows(result)>1)       {         sprintf(query_str,  "DELETE  FROM  nodes  WHERE  addr=%d;",  addr);         mysql_query(mysql,  query_str);  

      sprintf(query_str,  "INSERT  INTO  nodes  (addr,  lat,  longi,  tick_conversion)  VALUES  (%d,  %lf,  %lf,  %lf);",  addr,  latt,  longe,  conv);         mysql_query(mysql,  query_str);       }       //Otherwise  update  the  entry       else       {         sprintf(query_str,  "UPDATE  nodes  SET  lat=%lf,  longi=%lf,  tick_conversion=%lf  WHERE  addr=%d;",  latt,  longe,  conv,  addr);         mysql_query(mysql,  query_str);       }     }     else     {       sprintf(query_str,  "SELECT  *  FROM  nodes  WHERE  addr=%d;",  addr);       mysql_query(mysql,  query_str);       result=mysql_store_result(mysql);       //See  if  result  is  already  stored       if(mysql_num_rows(result)==0)       {         sprintf(query_str,  "INSERT  INTO  nodes  (addr,  lat,  longi,  tick_conversion)  VALUES  (%d,  %lf,  %lf,  %lf);",  addr,  latt,  longe,  conv);         mysql_query(mysql,  query_str);       }       else       {         printf("%s:  Sensor  %x  already  exists.    Retry  with  -­‐m  flag\n",  argv[0],  addr);         exit(0);       }     }     mysql_close(mysql);     printf("%s:  Operation  successful!    Restart  data_collector  to  enact  changes.\n",  argv[0]);  }       makefile  #  makefile  for  add/remove  sensor  tools    CC=gcc    all:add_sensor  remove_sensor    add_sensor:add_sensor.c  

  sh  -­‐c  "$(CC)  -­‐o  add_sensor  `mysql_config  -­‐-­‐cflags`  add_sensor.c  `mysql_config  -­‐-­‐libs`"  add_sensor.c      remove_sensor:remove_sensor.c     sh  -­‐c  "$(CC)  -­‐o  remove_sensor  `mysql_config  -­‐-­‐cflags`  remove_sensor.c  `mysql_config  -­‐-­‐libs`"  remove_sensor.c          

remove_sensor.c    *  remove_sensor.c    *    *  This  will  remove  the  record  of  a  rain  sensor  from  the      *  sql  database    */    #include  <mysql/mysql.h>  #include  <stdlib.h>  #include  <stdio.h>    #define  SQL_HOST  "mysql.sadionline.com"  #define  SQL_USR  "waleed25"  #define  SQL_PASSWORD  "Walid234"    #define  SQL_PORT  0    int  main(int  argc,  char  **argv)  {     char  PURGE=0;   //a  control  variable     int  addr;     MYSQL  *mysql;     MYSQL_RES  *result;     char  query_str[512];         //argument  check     if((argc!=2  &&  argc!=3)  ||  sscanf(argv[1],  "%x",  &addr)!=1)     {       printf("invocation:  remove_sensor  <address(hex)>  <-­‐purge(optional)>\n");       exit(1);     }         if(argc==3  &&  strcmp("-­‐purge",  argv[2])!=0)  

  {       printf("invocation:  remove_sensor  <address(hex)>  <-­‐purge(optional)>\n");       exit(1);     }         if(argc==3)     {       printf("%s:  All  data  associated  with  %x  will  be  removed(ctrl-­‐c  to  abort).\n",  argv[0],  addr);       int  i;       for(i=5;  i>0;  i-­‐-­‐)       {         printf("\r%d",  i);         sleep(1);       }       PURGE=1;     }           //initialize  connection     mysql=mysql_init(0);     if(mysql_real_connect(mysql,  SQL_HOST,  SQL_USR,  SQL_PASSWORD,  "rain_sensors",  SQL_PORT,  0,  0)==0)     {       printf("%s:  error  connecting  to  database\n",  argv[0]);       exit(1);     }     sprintf(query_str,  "SELECT  *  FROM  nodes  WHERE  addr=%d;",  addr);     mysql_query(mysql,  query_str);     result=mysql_store_result(mysql);     //See  if  result  is  already  stored     if(mysql_num_rows(result)==0)     {       printf("%s:  Sensor  %x  not  found\n",  argv[0],  addr);       exit(0);     }     else     {       sprintf(query_str,  "DELETE  FROM  nodes  WHERE  addr=%d;",  addr);       mysql_query(mysql,  query_str);       printf("%s:  Record  deleted  sucessfully!    Restart  data_collector  to  enable  changes.\n",  argv[0]);     }         if(PURGE==1)  

  {       sprintf(query_str,  "DELETE  FROM  data  WHERE  addr=%d;",  addr);       mysql_query(mysql,  query_str);       printf("%s:  Succesfully  purged  data!\n",  argv[0]);     }     mysql_close(mysql);  }            

Data  collector     data_collector.c  *  data_collector.c    *  This  is  the  main  file  in  the  data  collector  module.    It  reads  data  from  the  specified    *  serial  port,  analyzes  the  data,  and  forks  to  create  a  new  process  to  store  the  data  in    *  a  sql  database.    */        #include  <stdio.h>  #include  <stdlib.h>  #include  <sys/types.h>  #include  <sys/stat.h>  #include  <fcntl.h>  #include  <unistd.h>  #include  <termios.h>  #include  <string.h>  #include  <pthread.h>  #include  "sensor_data.h"  #include  "write_data.h"    #define  BAUDRATE  B115200    int  main(int  argc,  char  **argv)  {     int  serial;   //serial  port  file  descriptor     unsigned  int  data[5];   //scanned  data     unsigned  int  address;   //address  of  the  sensor     char  mode;     char  buff[50];       //buffer  for  data     int  numread;     sensor_data_t  *data_st;  

  write_data_t  *wr_data;     pthread_t  tid;         struct  termios  tio;   //serial  port  configuration       memset(&tio,  1,  sizeof(tio));         //get  serial  port  from  command  line  arguments     if(argc!=2)     {       printf("%s:  Invoke  as  ./data_collectormake  <serial  port>\n",  argv[0]);       exit(1);     }         //open  serial  port     if((serial  =  open(argv[1],  O_RDONLY  |  O_NOCTTY))<0)     {       printf("%s:  error  opening  serial  port\n",  argv[0]);       exit(1);     }         //configure  port     tio.c_cflag  =  BAUDRATE  |  CRTSCTS  |  CS8  |CLOCAL  |  CREAD;       tio.c_iflag  =  IGNPAR  |  ICRNL;       tio.c_oflag  =  0;       tio.c_lflag  =  ICANON;           tcflush(serial,  TCIFLUSH);     tcsetattr(serial,TCSANOW,&tio);         //Get  list  of  sensors     init_sensor_data(data_st);         for(;;)     {         //read  from  serial  port  and  use  first  char  to  classify  message       numread  =  read(serial,  &buff,  sizeof(buff));       switch(buff[0])       {         //data  message         case  'D':           //scan  in  the  message           if(sscanf(buff,  "D:%x:%d:%d:%d:%d:%d\n",  &address,  &data[0],  &data[1],  &data[2],  &data[3],  &data[4])<6)           {  

          printf("%s:  Bad  data\n",  argv[0]);             break;           }           //create  the  write  data  struct           wr_data=(write_data_t*)malloc(sizeof(write_data_t));           data[1]=(data[1]<<8)+data[0];           wr_data-­‐>addr=address;           wr_data-­‐>ticks=data[1];           wr_data-­‐>light=data[2];           wr_data-­‐>humidity=data[3];           wr_data-­‐>temp=data[4];           wr_data-­‐>data=data_st;           //process  the  data           write_data((void*)wr_data);           //pthread_create(&tid,  0,  write_data,  (void*)wr_data);           //pthread_detach(tid);                   break;         case  'R':           if(sscanf(buff,  "R:%d\n",  &data[0])<1)           {             perror("data_collector:  Bad  data\n");             break;           }           printf("SVC_RSP:%d\n",  data[0]);           break;         case  'Q':           if(sscanf(buff,  "Q:%d\n",  &data[0])<1)           {             perror("data_collector:  Bad  data\n");             break;           }           printf("REQ_RSP:%d\n",  data[0]);           break;         case  'U':           if(sscanf(buff,  "U:%d\n",  &data[0])<1)           {             perror("data_collector:  Bad  data\n");             break;           }           printf("NETWORK_UP:%d\n",  data[0]);           break;         case  'J':           if(sscanf(buff,  "J:%x:%d\n",  &data[0],  &data[1])<2)           {  

          perror("data_collector:  Bad  data\n");             break;           }           printf("Child  joined:%x,  %d\n",  data[0],  data[1]);           break;         case  'L':           if(sscanf(buff,  "L:%x:%d\n",  &data[0],  &data[1])<2)           {             perror("data_collector:  Bad  data\n");             break;           }           printf("Child  left:%x,  %d\n",  data[0],  data[1]);           break;         case  'T':           if(sscanf(buff,  "T:%d\n",  &data[0])<1)           {             perror("data_collector:  Bad  data\n");             break;           }           printf("Ticks:%d\n",  data[0]);           break;         default:           perror("data_collector:  invalid  message  type\n");       }     }     return  0;  }       makefile  CC=gcc  CFLAGS=-­‐c  EXEC=data_collector    $(EXEC):data_collector.o  sensor_data.o  write_data.o     sh  -­‐c  "$(CC)  -­‐o  $(EXEC)  -­‐pthread  `mysql_config  -­‐-­‐cflags`  data_collector.o  sensor_data.o  write_data.o  `mysql_config  -­‐-­‐libs`"    data_collector.o:data_collector.c  sensor_data.h     $(CC)  $(CFLAGS)  data_collector.c  -­‐pthread      sensor_data.o:sensor_data.c  sensor_data.h     $(CC)  $(CFLAGS)  sensor_data.c      write_data.o:write_data.c  write_data.h  

  $(CC)  $(CFLAGS)  write_data.c       sensor_data.c  /*  Vladimir  Samokhin    *  sensor_data.c    *      *  Gets  data  about  the  rain  sensors  from  a  database  and      *  stores  it  in  a  linked  list.    */      #include  "sensor_data.h"      void  init_sensor_data(sensor_data_t*  data)  {     MYSQL  *mysql;     MYSQL_RES  *result;     MYSQL_ROW  row;     sensor_data_t  *dataptr=data;         //initialize  connection     mysql=mysql_init(0);     if(mysql_real_connect(mysql,  SQL_HOST,  SQL_USR,  SQL_PASSWORD,  "rain_sensors",  SQL_PORT,  0,  0)==0)     {       printf("sensor_data:  error  connecting  to  database\n");       exit(1);     }         //Get  the  list  of  sensor  data     mysql_query(mysql,  "SELECT  *  FROM  nodes;");     result=mysql_store_result(mysql);         //verify  that  there  are  valid  results     if(mysql_num_rows(result)==0)     {       printf("sensor_data:  error:  no  sensors  in  database\n");       exit(1);     }     if(mysql_num_fields(result)!=5)     {       printf("sensor_data:  error:  invalid  database\n");       exit(1);     }      

  //read  fetched  data   and  store  it  in  a  linked  list     data=(sensor_data_t*)malloc(sizeof(sensor_data_t));     memset(dataptr,  0,  sizeof(sensor_data_t));     while((row=mysql_fetch_row(result)))     {       sscanf(row[1],  "%d",  &(dataptr-­‐>address));       sscanf(row[4],  "%lf",  &(dataptr-­‐>conversion));       pthread_mutex_init(&dataptr-­‐>lock,  0);       dataptr-­‐>next=(sensor_data_t*)malloc(sizeof(sensor_data_t));       dataptr=dataptr-­‐>next;       memset(dataptr,  0,  sizeof(sensor_data_t));     }     mysql_free_result(result);     mysql_close(mysql);  }    //Frees  all  alocated  memory  void  free_sensor_data(sensor_data_t*  data)  {     sensor_data_t*  temp;     while(data!=0)     {       temp=data;       data=data-­‐>next;       free(temp);     }  }           sensor_data.h  *  sensor_data.h    *      *  Gets  data  about  the  rain  sensors  from  a  database  and      *  stores  it  in  a  linked  list.    */    #ifndef  SENSOR_DATA_H  #define  SENSOR_DATA_H      #include  <time.h>  #include  <mysql/mysql.h>  #include  <stdio.h>  #include  <string.h>  #include  <pthread.h>  

#include  <stdlib.h>    #define  SQL_HOST  "mysql.sadionline.com"  #define  SQL_USR  "waleed25"  #define  SQL_PASSWORD  "Walid234"    #define  SQL_PORT  0  //a  data  structure  to  store  the  relevant  information  about  active  rain  sensors  typedef  struct  sensor_data  {     unsigned  int  address;     double  conversion;     time_t  last_time;     pthread_mutex_t  lock;     struct  sensor_data  *next;  }  sensor_data_t;    /*  Gets  the  sensor  data  from  the  database  and  puts  it  in  a      *  linked  list  of  sensor_data_t.    Allocates  data  into  sensor_data_t.    *  Returns  0  on  success.    */  void  init_sensor_data(sensor_data_t*);    //Free  sensor_data_t  structure  void  free_sensor_data(sensor_data_t*);    #endif       write_data.c  *  write_data.c    *    *  This  file  contains  all  of  the  functions  that  write    *  data  aquired  from  sensors  to  the  mysql  database    */    #include  "write_data.h"      void  *write_data(void  *wd)  {     write_data_t  *wr_data=(write_data_t*)wd;     MYSQL  *mysql;     sensor_data_t  *dataptr=wr_data-­‐>data;     time_t  ctime;     char  sql_query[512];  

  double  elapsed_time=0;     double  precip_rate=0;     double  precip=0;           //locate  record  of  reporting  sensor     while(dataptr-­‐>address!=0)     {       if(dataptr-­‐>address==wr_data-­‐>addr)       {         break;         printf("broken\n");       }       dataptr=dataptr-­‐>next;     }     if(dataptr-­‐>address==0)     {       printf("Write_data:  error:  no  record  of  sensor  %x.    Try  restarting  data_collector.\n",  wr_data-­‐>addr);       free(wd);       return;     }         pthread_mutex_lock(&(dataptr-­‐>lock));         //calculate  time  and  precipitation  rate     precip=(double)(wr_data-­‐>ticks)*dataptr-­‐>conversion;     time(&ctime);     if(dataptr-­‐>last_time!=0)     {       elapsed_time  =  difftime(ctime,  dataptr-­‐>last_time)/60/60;  //elapsed  time  in  hours  since  last  report       precip_rate=precip/elapsed_time;     }     else     {       elapsed_time=0;       precip_rate=0;     }     dataptr-­‐>last_time=ctime;     pthread_mutex_unlock(&(dataptr-­‐>lock));         //Connect  to  database     mysql=mysql_init(0);  

  if(mysql_real_connect(mysql,  SQL_HOST,  SQL_USR,  SQL_PASSWORD,  "rain_sensors",  SQL_PORT,  0,  0)==0)     {       printf("Write_data:  error  connecting  to  database\n");       mysql_close(mysql);           return  0;     }     sprintf(sql_query,  "INSERT  INTO  data  (time,  address,  precip_rate,  light,  humidity,  temp)  VALUES  (NOW(),  %i,  %lf,  %i,  %d,  %d);",  wr_data-­‐>addr,  precip_rate,  wr_data-­‐>light,  wr_data-­‐>humidity,  wr_data-­‐>temp);     printf("%s\n",  sql_query);     mysql_query(mysql,  sql_query);     mysql_close(mysql);       free(wd);     return  0;  }       write_data.h  *  write_data.h    *    *  This  file  contains  all  of  the  functions  that  write    *  data  aquired  from  sensors  to  the  mysql  database    */      #ifndef  WRITE_DATA_H  #define  WRITE_DATA_H    #include  <mysql/mysql.h>  #include  <stdio.h>  #include  <pthread.h>  #include  "sensor_data.h"    //A  struct  to  store  the  data  to  be  written  to  the  mysql  database  typedef  struct  {     sensor_data_t  *data;     int  addr;     int  ticks;     int  light;     int  humidity;     int  temp;  }write_data_t;    void  *write_data(void  *data);  

 #endif    

Data  import       dataimport.c  #include  <stdio.h>  #include  <stdlib.h>    #include  <mysql/mysql.h>  #define  SQL_HOST  "mysql.sadionline.com"  #define  SQL_USR  "waleed25"  #define  SQL_PASSWORD  "Walid234"  #define  SQL_PORT  0    typedef  struct  data_t  {     char  month[6];     int  day;     int  hour;     int  min;     float  sec;     int  year;     int  address;     int  tick0,  tick1;     int  light;     int  hum;     int  temp;     struct  data_t  *next;  }  data;    typedef  struct  packed_data_t  {     int  address;     int  year;     int  month;     int  day;     int  hour,  min,  sec;     double  precip_rate;     int  light;     int  hum;     int  temp;     struct  packed_data_t  *next;  }packed_data;  

 int  main(int  argc,  char  **argv)  {     data  *raw_data,  *rd_ptr;     FILE  *file;         if(0==(file=fopen(argv[1],  "r")))     {       perror("error  opening  file\n");       return  -­‐1;     }         raw_data=malloc(sizeof(data));     raw_data-­‐>next=0;     char  day[6];     rd_ptr=raw_data;         //read  data     while(1)     {       int  ret=fscanf(file,  "[%s  %s  %d  %d:%d:%f  %d]  D:%x:%d:%d:%d:%d:%d\n",  day,  rd_ptr-­‐>month,  &(rd_ptr-­‐>day),  &(rd_ptr-­‐>hour),  &(rd_ptr-­‐>min),  &(rd_ptr-­‐>sec),  &(rd_ptr-­‐>year),  &(rd_ptr-­‐>address),  &(rd_ptr-­‐>tick0),  &(rd_ptr-­‐>tick1),  &(rd_ptr-­‐>light),  &(rd_ptr-­‐>hum),  &(rd_ptr-­‐>temp));       if(ret==EOF)       {         rd_ptr-­‐>address=0;         break;       }       if(ret!=13)       {         while(fgetc(file)!='\n');         continue;       }       //hardcoded  to  only  look  for  one  sensor       if(rd_ptr-­‐>address!=0x1c7227)       {         continue;       }       rd_ptr-­‐>next=malloc(sizeof(data));       rd_ptr=rd_ptr-­‐>next;       rd_ptr-­‐>next;     }     rd_ptr=raw_data;  

  fclose(file);     printf("Data  imported\n");         //condense  data     packed_data  *p_data,  *pd_ptr;     p_data=malloc(sizeof(packed_data));     pd_ptr=p_data;     pd_ptr-­‐>next=0;     while(1)     {       int  ticks=0;       int  start_min;       int  start_sec;       int  stop_min;       start_min=rd_ptr-­‐>min;       start_sec=(int)(rd_ptr-­‐>sec);       stop_min=start_min+5;       if(stop_min>59)  stop_min-­‐=60;             while(rd_ptr-­‐>min!=stop_min)       {         ticks+=rd_ptr-­‐>tick0;         if(rd_ptr-­‐>next==0)         {           break;         }         rd_ptr=rd_ptr-­‐>next;       }       double  hours=0;       if(start_min<rd_ptr-­‐>min)       {         hours+=(double)(rd_ptr-­‐>min-­‐start_min)/60;       }       else       {         hours+=(double)((60-­‐start_min)+rd_ptr-­‐>min)/60;       }       if(start_sec<rd_ptr-­‐>sec)       {         hours+=(double)(rd_ptr-­‐>sec-­‐start_sec)/60/60;       }       else       {         hours+=(double)((60-­‐start_sec)+rd_ptr-­‐>sec)/60/60;  

    }       //printf("Start  %d,  end  %d,  hours  %lf,  ticks  %d\n",  start_min,  rd_ptr-­‐>min,  hours,  ticks);       pd_ptr-­‐>precip_rate=(double)ticks*0.01/hours;       pd_ptr-­‐>year=rd_ptr-­‐>year;       pd_ptr-­‐>address=rd_ptr-­‐>address;       pd_ptr-­‐>day=rd_ptr-­‐>day;       pd_ptr-­‐>hour=rd_ptr-­‐>hour;       pd_ptr-­‐>min=rd_ptr-­‐>min;       pd_ptr-­‐>month=4;       pd_ptr-­‐>sec=(int)rd_ptr-­‐>sec;       pd_ptr-­‐>light=rd_ptr-­‐>light;       pd_ptr-­‐>hum=rd_ptr-­‐>hum;       pd_ptr-­‐>temp=rd_ptr-­‐>temp;       if(rd_ptr-­‐>next==0)       {         break;       }       pd_ptr-­‐>next=malloc(sizeof(packed_data));       pd_ptr=pd_ptr-­‐>next;       pd_ptr-­‐>next=0;     }     pd_ptr=p_data;         //add  to  mysql  db.     MYSQL  *mysql;     mysql=mysql_init(0);     if(mysql_real_connect(mysql,  SQL_HOST,  SQL_USR,  SQL_PASSWORD,  "rain_sensors",  SQL_PORT,  0,  0)==0)     {       printf("%s:  error  connecting  to  database\n",  argv[0]);       exit(1);     }     while(pd_ptr-­‐>next!=0  &&  pd_ptr!=0)     {       char  query_str[256];       sprintf(query_str,  "INSERT  INTO  data  (time,  address,  precip_rate,  light,  humidity,  temp)  VALUES  (\"%d-­‐%d-­‐%d  %d:%d:%d\",  %i,  %lf,  %i,  %d,  %d);",  pd_ptr-­‐>year,  pd_ptr-­‐>month,  pd_ptr-­‐>day,  pd_ptr-­‐>hour,  pd_ptr-­‐>min,  pd_ptr-­‐>sec,  pd_ptr-­‐>address,  pd_ptr-­‐>precip_rate,  pd_ptr-­‐>light,  pd_ptr-­‐>hum,  pd_ptr-­‐>temp);       mysql_query(mysql,  query_str);       pd_ptr=pd_ptr-­‐>next;     }     return  0;  

}             makefile  dataimport:dataimport.c     sh  -­‐c  "gcc  -­‐o  dataimport  dataimport.c  `mysql_config  -­‐-­‐cflags`  `mysql_config  -­‐-­‐libs`"    

rain  sensor  simulate       RainSensorSim.pde  /*    *  RainSensorSim.pde  *    *  Arduino  sketch  to  simulate  the  rs232  output    *  of  the  rain  sensor  network    */  int  addr[3];    void  setup()  {      Serial.begin(19200);      addr[0]=0x123;      addr[1]=0x456;      addr[2]=0x789;  }    void  loop()  {      delay(4000);      int  node  =  random(3);      int  ticks=random(50);      int  light  =  random(50);      int  hum=random(10);      int  temp=random(40)-­‐10;      Serial.print("D:");      Serial.print(addr[node],  HEX);      Serial.print(":0:");      Serial.print(ticks);      Serial.print(":");      Serial.print(light);      Serial.print(":");      Serial.print(hum);      Serial.print(":");      Serial.print(temp);      Serial.print("\n");  

}      

Website       data.php  <?php  $sqlHost="localhost:7026";  //set  host  to  $sqlUsr="rain";  //set  username  $sqlPwd="rain";  //set  password    ini_set('display_errors',  '1');  //displays  errors,  false  if  failure  ini_set('display_startup_errors',  '1');  //displays  startup  errors,  false  if  failure  error_reporting(E_ALL);  //reports  all  errors    if(!isset($_GET['addr']))  //if  nothing  set,  true  &  print  below  {     echo("Error:  Address  not  specified");  //print  ""     die();  //print  to  user  &  exit  }  $addr=$_GET['addr'];  //set    variable  'addr'  to  'get  inputs  from  addr'  $numaddr  =  hexdec($addr);  //set  numaddr  to  'addr  converted  into  hexadecimal'    if(isset($_GET['ALL']))  //  check  if  'ALL'  is  set  {     $all=$_GET['ALL'];  //  true,  set  'all'  to  'get  inputs  from  ALL'  }  else  {     $all=false;  //false,  0  }    $con=mysql_connect($sqlHost,  $sqlUsr,  $sqlPwd);  //set  con  to  connect  to  sql  if(!$con)  //check  if  no  connection  {     die(mysql_error());  //  retrieve  error  text  and  exit  }  $dbSelect  =  mysql_selectdb("rain_sensors",  $con);  //  set  'dbSelect'  to  select  database  'rain_sensors'  with  connection  from  '$con'  if(!$dbSelect)  //if  not  'dbSelect'  {     die(mysql_error());  //retrieve  error  text  and  exit  }    

if($all==true)  //if  'all'  is  true  {     $result  =  mysql_query("SELECT  *  FROM  data  WHERE  address=$addr;");  //set  result  to  specific  database  }  else  {     $result  =  mysql_query("SELECT  *  FROM  data  WHERE  address=$addr  and  time>=DATE_SUB(NOW(),INTERVAL  3  week);");  //set  result  to  specific  database  with  time  greater  than  previous  3  weeks  to  date  }    if(!$result)  //check  if  results  do  not  exit  {     echo("Invalid  address");  //print     die();  //  if  no  'results',  then  exit  }      $filename=tempnam("../data",  "data");  //set  'filename'  to  create  temporary  filename  'data'  under  directory  'data'.  if  none  made,  return  false  $file=fopen($filename,  "w");  //set  'file'  to  open  a  file  'filename'.  'w'  is  write  only  for  open  and  clear/create  new  file  if  none  exist  if(  $file  ==  false  )  //check  if  'file'  does  not  exit  {        echo  (  "Error  in  opening  file"  );        exit();  //  or  die(),  exits  }    fwrite($file,  "timestamp;  precipitation  rate;  light;  humidity;  temperature;\r\n");  //write  in  measurement  titles  into  'file'    while($row  =  mysql_fetch_array($result))  //while  'row'  is  set  to  data  from  'result'  {     fwrite($file,  $row['time']  .  ";"  .  $row['precip_rate']  .  ";"  .  $row['light']  .  ";"  .  $row['humidity']  .  ";"  .  $row['temp']  .  ";\r\n");  }    fclose($file);  $fname="data"  .  $addr  .  ".dat";  header("Cache-­‐Control:  public");  header("Content-­‐Description:  File  Transfer");  header("Content-­‐Length:  ".  filesize("$filename").";");  header("Content-­‐Disposition:  attachment;  filename=$fname");  

header("Content-­‐Type:  application/octet-­‐stream;  ");    header("Content-­‐Transfer-­‐Encoding:  binary");    readfile($filename);  unlink($filename);  ?>       history.php  <?php  $sqlHost="localhost:7026";  $sqlUsr="rain";  $sqlPwd="rain";    ini_set('display_errors',  '1');  ini_set('display_startup_errors',  '1');  error_reporting(E_ALL);    require("include/HistoryHelper.php");    if(!isset($_GET['addr']))  {     echo("Error:  Address  not  specified");     die();  }  $addr=$_GET['addr'];  $numaddr  =  hexdec($addr);  $con=mysql_connect($sqlHost,  $sqlUsr,  $sqlPwd);  if(!$con)  {     die(mysql_error());  }  $dbSelect  =  mysql_selectdb("rain_sensors",  $con);    if(!$dbSelect)  {     die(mysql_error());  }    $HH=new  HistoryHelper($numaddr);    ?>      <html>      <head>  

      <title>Historical  data  for  <?php  echo($addr)?></title>          <?php  $HH-­‐>printJS();?>      </head>        <body>          <b>Last  three  weeks  of  historical  weather  data  for  sensor  <?php  echo($addr)?></b><br>          <div  id='chart_div'  style='width:  800px;  height:  500px;'></div>          Precipitation  rate  in  inches  per  hour,  temperature  in  celcius,  and  light  in  kilo  lumens.  <br><br>          Download  data  file:<a  href="data.php?addr=<?php  echo($addr)?>">last  three  weeks<a>  -­‐  <a  href="data.php?addr=<?php  echo($addr)?>&ALL=true">all  data(warning:file  may  be  large)<a><br>          <a  href="history.php?addr=<?php  echo($addr)?>">Refresh</a>  -­‐  <a  href="index.php">Return  to  map</a>  -­‐  <a  href="help.html">Help</a>  -­‐  <a  href="about.html">About</a>      </body>  </html>       index.php    <?php  $sqlHost="localhost:7026";  $sqlUsr="rain";  $sqlPwd="rain";    ini_set('display_errors',  '1');  ini_set('display_startup_errors',  '1');  error_reporting(E_ALL);    require_once('include/GoogleMap.php');    //this  was  found  on  the  internet.    It  interfaces  with  the  google  maps  api  which  is  in  java  script  require('include/OverviewLoader.php');      $MAP_OBJECT  =  new  GoogleMapAPI('map');    $MAP_OBJECT-­‐>_minify_js  =  isset($_REQUEST["min"])?FALSE:TRUE;  $MAP_OBJECT-­‐>setMapType('');  $MAP_OBJECT-­‐>setWidth(700);    $OLoader=new  OverviewLoader($MAP_OBJECT,  $sqlHost,  $sqlUsr,  $sqlPwd);  $OLoader-­‐>getData();  $OLoader-­‐>placeMarkers();    

?>    <html>  <head>  <title>Rainfall  Sensor  Data</title>  <?=$MAP_OBJECT-­‐>getHeaderJS();?>  <?=$MAP_OBJECT-­‐>getMapJS();?>  </head>    <body>    <b>Current  rainfall  data</b>  <?=$MAP_OBJECT-­‐>printOnLoad();?>  <?=$MAP_OBJECT-­‐>printMap();?>  <?=$MAP_OBJECT-­‐>printSidebar();?>    <pre>No  rain:<img  src="http://dl.dropbox.com/u/21246497/rainsensor/blue.gif"  alt="blue"  />    0-­‐2  inches/hour:<img  src="http://dl.dropbox.com/u/21246497/rainsensor/green.gif"  alt="green"  />    2-­‐4  inches/hour:<img  src="http://dl.dropbox.com/u/21246497/rainsensor/yellow.gif"  alt="yellow"  />    >4  inches/hour:<img  src="http://dl.dropbox.com/u/21246497/rainsensor/red.gif"  alt="red"  />    No  data:<img  src="http://dl.dropbox.com/u/21246497/rainsensor/no_data.gif"  alt="white"  />  </pre>  <a  href="index.php">Refresh</a>  -­‐  <a  href="help.html">Help</a>  -­‐  <a  href="about.html">About</a>    </body>  </html>    

Outside  Included  resources  GoogleMap.php  HistoryHelper/php  JSMin.php  OverviewLoader.php    

Sql  database       databasestructure.sql  -­‐-­‐  phpMyAdmin  SQL  Dump  -­‐-­‐  version  3.3.10.4  -­‐-­‐  http://www.phpmyadmin.net  -­‐-­‐  -­‐-­‐  Host:  mysql.sadionline.com  -­‐-­‐  Generation  Time:  May  02,  2012  at  07:37  PM  

-­‐-­‐  Server  version:  5.1.39  -­‐-­‐  PHP  Version:  5.2.17    SET  SQL_MODE="NO_AUTO_VALUE_ON_ZERO";    -­‐-­‐  -­‐-­‐  Database:  `rain_sensors`  -­‐-­‐    -­‐-­‐  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐    -­‐-­‐  -­‐-­‐  Table  structure  for  table  `data`  -­‐-­‐    CREATE  TABLE  IF  NOT  EXISTS  `data`  (      `id`  bigint(20)  unsigned  NOT  NULL  AUTO_INCREMENT,      `time`  datetime  NOT  NULL,      `address`  int(10)  unsigned  NOT  NULL,      `precip_rate`  double  unsigned  NOT  NULL,      `light`  float  NOT  NULL,      `humidity`  float  NOT  NULL,      `temp`  float  NOT  NULL,      PRIMARY  KEY  (`id`)  )  ENGINE=MyISAM    DEFAULT  CHARSET=latin1  AUTO_INCREMENT=12785  ;    -­‐-­‐  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐    -­‐-­‐  -­‐-­‐  Table  structure  for  table  `nodes`  -­‐-­‐    CREATE  TABLE  IF  NOT  EXISTS  `nodes`  (      `id`  bigint(20)  unsigned  NOT  NULL  AUTO_INCREMENT,      `addr`  int(10)  unsigned  DEFAULT  NULL,      `lat`  double  DEFAULT  NULL,      `longi`  double  DEFAULT  NULL,      `tick_conversion`  double  NOT  NULL,      PRIMARY  KEY  (`id`)  )  ENGINE=MyISAM    DEFAULT  CHARSET=latin1  AUTO_INCREMENT=10  ;       dump.sql  -­‐-­‐  MySQL  Administrator  dump  1.4  -­‐-­‐  

-­‐-­‐  -­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐-­‐  -­‐-­‐  Server  version   5.1.61-­‐0ubuntu0.11.10.1      /*!40101  SET  @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT  */;  /*!40101  SET  @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS  */;  /*!40101  SET  @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION  */;  /*!40101  SET  NAMES  utf8  */;    /*!40014  SET  @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS,  UNIQUE_CHECKS=0  */;  /*!40014  SET  @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS,  FOREIGN_KEY_CHECKS=0  */;  /*!40101  SET  @OLD_SQL_MODE=@@SQL_MODE,  SQL_MODE='NO_AUTO_VALUE_ON_ZERO'  */;      -­‐-­‐  -­‐-­‐  Create  schema  rain_sensors  -­‐-­‐    CREATE  DATABASE  IF  NOT  EXISTS  rain_sensors;  USE  rain_sensors;  CREATE  TABLE    `rain_sensors`.`data`  (      `id`  bigint(20)  unsigned  NOT  NULL  AUTO_INCREMENT,      `time`  datetime  NOT  NULL,      `address`  int(10)  unsigned  NOT  NULL,      `precip_rate`  double  unsigned  NOT  NULL,      `light`  float  NOT  NULL,      `humidity`  float  NOT  NULL,      `temp`  float  NOT  NULL,      PRIMARY  KEY  (`id`)  )  ENGINE=MyISAM  AUTO_INCREMENT=52  DEFAULT  CHARSET=latin1;  INSERT  INTO  `rain_sensors`.`data`  VALUES    (1,'2012-­‐03-­‐21  16:33:22',1342408,0,6,47,25),    (2,'2012-­‐03-­‐21  16:33:24',1342408,0,6,47,25),    (3,'2012-­‐03-­‐21  16:33:26',1342408,0,6,47,25),    (4,'2012-­‐03-­‐21  16:33:28',1342408,0,6,47,25),    (5,'2012-­‐03-­‐21  16:33:30',1342408,0,6,47,25),    (6,'2012-­‐03-­‐21  16:33:32',1342408,0,6,47,25),    (7,'2012-­‐03-­‐21  16:33:34',1342408,0,6,47,25),    (8,'2012-­‐03-­‐21  16:33:36',1342408,0,6,47,25),    (9,'2012-­‐03-­‐21  16:33:38',1342408,0,6,47,25),    (10,'2012-­‐03-­‐21  16:33:40',1342408,0,6,47,25),    (11,'2012-­‐03-­‐21  16:33:42',1342408,0,6,47,25),    (12,'2012-­‐03-­‐21  16:33:44',1342408,0,6,46,25),  

 (13,'2012-­‐03-­‐21  16:33:46',1342408,0,6,46,25),    (14,'2012-­‐03-­‐21  16:33:48',1342408,0,6,46,25),    (15,'2012-­‐03-­‐21  16:33:50',1342408,0,6,46,25),    (16,'2012-­‐03-­‐21  16:33:52',1342408,0,6,46,25),    (17,'2012-­‐03-­‐21  16:33:54',1342408,0,6,46,25),    (18,'2012-­‐03-­‐21  16:33:56',1342408,0,6,46,25),    (19,'2012-­‐03-­‐21  16:33:58',1342408,0,6,46,25),    (20,'2012-­‐03-­‐21  16:34:00',1342408,0,6,46,25),    (21,'2012-­‐03-­‐21  16:34:02',1342408,0,6,46,25),    (22,'2012-­‐03-­‐21  16:34:04',1342408,0,6,46,25),    (23,'2012-­‐03-­‐21  16:34:06',1342408,0,6,46,25),    (24,'2012-­‐03-­‐21  16:34:08',1342408,0,6,46,25),    (25,'2012-­‐03-­‐21  16:34:10',1342408,0,6,46,25),    (26,'2012-­‐03-­‐21  16:34:12',1342408,0,6,46,25),    (27,'2012-­‐03-­‐21  16:34:14',1342408,0,6,46,25),    (28,'2012-­‐03-­‐21  16:34:16',1342408,0,6,46,25),    (29,'2012-­‐03-­‐21  16:34:18',1342408,0,6,46,25),    (30,'2012-­‐03-­‐21  16:34:20',1342408,0,6,46,25),    (31,'2012-­‐03-­‐21  16:34:22',1342408,0,6,46,25),    (32,'2012-­‐03-­‐21  16:34:24',1342408,0,6,46,25),    (33,'2012-­‐03-­‐21  16:34:25',1342408,0,6,46,25),    (34,'2012-­‐03-­‐21  16:34:28',1342408,0,6,46,25),    (35,'2012-­‐03-­‐21  16:34:30',1342408,0,6,46,25),    (36,'2012-­‐03-­‐21  16:34:32',1342408,0,6,46,25),    (37,'2012-­‐03-­‐21  16:34:34',1342408,0,6,46,25),    (38,'2012-­‐03-­‐21  16:34:36',1342408,0,6,46,25),    (39,'2012-­‐03-­‐21  16:34:38',1342408,0,6,46,25),    (40,'2012-­‐03-­‐21  16:34:40',1342408,0,6,46,25),    (41,'2012-­‐03-­‐21  16:34:42',1342408,0,6,46,25),    (42,'2012-­‐03-­‐21  16:34:44',1342408,0,6,46,25),    (43,'2012-­‐03-­‐21  16:34:46',1342408,0,6,46,25),    (44,'2012-­‐03-­‐21  16:34:48',1342408,0,6,46,25),    (45,'2012-­‐03-­‐21  16:34:51',1342408,0,6,46,25),    (46,'2012-­‐03-­‐21  16:34:53',1342408,0,6,46,25),    (47,'2012-­‐03-­‐21  16:34:55',1342408,0,6,46,25),    (48,'2012-­‐03-­‐21  16:34:57',1342408,0,6,46,25),    (49,'2012-­‐03-­‐21  16:34:59',1342408,0,6,46,25),    (50,'2012-­‐03-­‐21  16:35:01',1342408,0,6,46,25),    (51,'2012-­‐03-­‐21  16:35:03',1342408,0,6,46,25);  CREATE  TABLE    `rain_sensors`.`nodes`  (      `id`  bigint(20)  unsigned  NOT  NULL  AUTO_INCREMENT,      `addr`  int(10)  unsigned  DEFAULT  NULL,      `lat`  double  DEFAULT  NULL,      `longi`  double  DEFAULT  NULL,  

   `tick_conversion`  double  NOT  NULL,      PRIMARY  KEY  (`id`)  )  ENGINE=MyISAM  AUTO_INCREMENT=3  DEFAULT  CHARSET=latin1;  INSERT  INTO  `rain_sensors`.`nodes`  VALUES    (2,1342408,1,1,1);        /*!40101  SET  SQL_MODE=@OLD_SQL_MODE  */;  /*!40014  SET  FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS  */;  /*!40014  SET  UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS  */;  /*!40101  SET  CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT  */;  /*!40101  SET  CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS  */;  /*!40101  SET  COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION  */;  /*!40101  SET  CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT  */;       makefile  #  a  makefile  for  the  entire  project    all:data_collector  add_remove_sensor    add_remove_sensor:     cd  add_remove_sensor/     make     cd  ../    data_collector:     cd  data_collector/     make     cd  ../