Code Search for Developers
 
 
  

vp2.c from EmStar at Krugle


Show vp2.c syntax highlighted

/*
 *  vp2.c
 *
 *   Connects to davis weatherenvoy or vantage pro 2
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <libevent/event.h>
#include <link/link.h>
#include <emrun/emrun.h>
#include <sys/socket.h>
#include <termios.h>
#include <sys/uio.h>

#include "libmisc/misc.h"
#include "libdev/status_dev.h"
#include "timesync/sync.h"

#define READ_LEN 4096
#define SUMMARY_STATUS_DEV sim_path("/dev/davis-vp2/summary")
#define BUFLEN 99

g_event_t *request_timer = NULL;

typedef struct W {
  float wind_spd;
  int wind_direction;
  float temperature;
  int rh;
  float soil_t;
  float leaf_t;
  struct timeval report_time;
} weather_t;

int baud;
g_event_t *serial = NULL;
char *device;
int serial_fd;
weather_t weather;
status_context_t *summary_ref = NULL;
char *clock_opt = NULL;
int clock_number = -1;
int test_mode = 0;

/*
 *  periodic request
 */

int timer_fired (void *data, int interval, g_event_t *event)
{
  char buf[BUFLEN];
  if (test_mode)
    sprintf(buf, "TEST\n");
  else
    sprintf(buf, "LOOP 100\n");
  write_to_fd(serial_fd, buf, strlen(buf));
  elog(LOG_DEBUG(0), "write request string!");
  return TIMER_RENEW;
}

/*
 *  Handle incoming data from serial port.
 */

static
int serial_data_ready(void *data, int fd, int cond, g_event_t *event)
{ 
  static char buf[2*BUFLEN];
  static int buf_len = 0;
  /* the file descriptor is ready for reading... */
  if (cond & FUSD_NOTIFY_INPUT) {

    /* read into the buffer.. */
    int status = read(fd, buf+buf_len, sizeof(buf) - buf_len);

    /* error condition.. */
    if (status < 0) {
      if (errno == EINTR || errno == EAGAIN) 
	goto done;
      elog(LOG_CRIT, "Read error from serial %s: %m", device);
      exit(1);
    }

    /* got data.. */
    if (status > 0) {
      buf_len += status;
      elog(LOG_DEBUG(5), "got %d bytes from serial.. pushing", status);
      elog_raw(LOG_DEBUG(5), buf, buf_len);

    retry:
      while (buf_len > 0) {
	if (buf[0] == 0x6) 
	  goto trash_it_silently;

	int check_max = buf_len;
	if (check_max > 3) check_max = 3;
	
	if (strncmp(buf, "LOO", check_max)) {
	  goto trash_it;
	}
	else break;
      }	

      if (buf_len >= BUFLEN) {	    
	if (buf[95]=='\n' && buf[96]=='\r') {
	  
	  /* got a frame? */
	  
	  gettimeofday(&weather.report_time, NULL);
	  
	  if (clock_number >= 0) {
	    sync_id_t src = {
	      node: my_node_id,
	      comp: CPU
	    };
	    sync_id_t dest = {
	      node: my_node_id,
	      comp: clock_number
	    };
	    
	    struct timeval src_tv = weather.report_time;
	    if (sync_convert_tv(&src, &src_tv, &dest, &weather.report_time) < 0) {
	      elog(LOG_WARNING, "couldn't convert from %s to %s: %m\n",
		   print_sync_id(&src), print_sync_id(&dest));
	    }
	  }
	  
	  weather.wind_spd = (float)buf[14];
	  
	  /* convert mph -> m/s */
	  weather.wind_spd *= 0.44704;
	  
	  weather.wind_direction = buf[17];
	  weather.wind_direction *= 256;
	  weather.wind_direction += buf[16];
	  
	  weather.temperature = buf[13];
	  weather.temperature *= 256;
	  weather.temperature += buf[12];
	  weather.temperature /= 10;
	  
	  /* convert F -> C */
	  weather.temperature = ((weather.temperature - 32) * 5)/9;
	  
	  weather.rh = buf[33];
	  
	  weather.soil_t = buf[25] - 90;
	  weather.soil_t = ((weather.soil_t - 32) * 5)/9;
	  
	  weather.leaf_t = buf[29] - 90;
	  weather.leaf_t = ((weather.leaf_t - 32) * 5)/9;
	  
	  g_status_dev_notify(summary_ref);
	  
	  buf_len -= BUFLEN;
	  memmove(buf, buf+BUFLEN, buf_len);
	  
	  /* reset request timer */
	  g_event_destroy(request_timer);
	  g_timer_add(2000, timer_fired, NULL, NULL, &request_timer);
	}
	else {
	  goto trash_it;
	}
      }
    }
    
  done:
    ;
  }

  /* exceptions occur when the device disappears out from under or other
   * unusual events.. */
  if (cond & FUSD_NOTIFY_EXCEPT) {
    elog(LOG_CRIT, "exception on serial port device: %m");
    exit(1);
  }

  return EVENT_RENEW;

 trash_it:
  elog(LOG_WARNING, "dropping byte: %x", buf[0]);
 trash_it_silently:
  buf_len--;
  memmove(buf, buf+1, buf_len);
  goto retry;
}

/*
 *  Usage and initialization
 */

void usage(char *name)
{
  misc_print_usage
    (name, 
     "-d <device> [-b <baud>] [--clock <clock-name>]",
     "  --device <device>: specify device to expose\n"
     "  --baud <baud>: specify baud rate\n"
     "  --clock <clock-name>: clock in which to record data\n"
     "\n"
     "device, baud args are required\n"
     );
  exit(1);
}


static void vp2_shutdown(void *data)
{
  elog(LOG_NOTICE, "vp2 device (connected to '%s'), shutting down...",
       device);
  exit(0);
}

int summary_status_print(status_context_t *info, buf_t *buf)
{
  
  bufprintf(buf, "%ld.%06ld %.2f %d %.2f %d %.2f %.2f\n", 
	    weather.report_time.tv_sec, weather.report_time.tv_usec, 
	    weather.wind_spd, weather.wind_direction,
	    weather.temperature, weather.rh, weather.soil_t, 
	    weather.leaf_t);
  return STATUS_MSG_COMPLETE; 
}


int main(int argc, char **argv)
{
  misc_init(&argc, argv, CVSTAG);

  /* parse args */
  baud = 19200;
  misc_parse_option_as_uint(&argc, argv, "baud", 'b', (uint*)&baud);
  if ((device = misc_parse_out_option(&argc, argv, "device", 'd')) == NULL)
    usage(argv[0]);
  clock_opt = misc_parse_out_option(&argc, argv, "clock", 0);
  if (misc_parse_out_switch(&argc, argv, "help", 'h'))
    usage(argv[0]);
  test_mode = misc_parse_out_switch(&argc, argv, "test", 0);
  if (misc_args_remain(&argc, argv))
    usage(argv[0]);

  if (clock_opt) {
    clock_number = sync_clock_no_create(clock_opt);  
    if (clock_number < 0) {
      elog(LOG_WARNING, "No clock by the name of %s exists!\n", clock_opt);
    }      
  }

  /* Try to open the port */
  if ((serial_fd = open(device, O_RDWR | O_NOCTTY)) < 0) {
    elog(LOG_CRIT, "can't open %s: %m", device);
    exit(1);
  }
    
  /* configure the serial port: raw, set baud, no rtscts */
  misc_config_serial(serial_fd, baud, 0);

  /* flush output */
  if (tcflush(serial_fd, TCIFLUSH) < 0)
    elog(LOG_WARNING, "can't tcflush serial port %s: %m", device);
  
  /* Set this FD to be nonblocking */
  set_nonblock(serial_fd, 1);

  /* try to reset the device */
  write(serial_fd, "\n", 1);
  sleep(1);
  write(serial_fd, "\n", 1);
  sleep(1);
  write(serial_fd, "\n", 1);
  sleep(1);
  write(serial_fd, "TEST\n", 5);
     
  /* Add an event that fires when the serial port is readable */
  if (g_event_add(serial_fd, FUSD_NOTIFY_INPUT | FUSD_NOTIFY_EXCEPT, 
		  serial_data_ready, NULL, NULL, &serial) < 0) {
    elog(LOG_CRIT, "can't create event for %s: %m", device);
    exit(1);
  }

  elog(LOG_NOTICE, "Davis VantagePro2 (connected to '%s') starting...",
       device);
 
  status_dev_opts_t s_opts_summary = {
    device: {
      devname: SUMMARY_STATUS_DEV, 
      device_info: NULL
    }, 
    printable: summary_status_print
  };
  if (g_status_dev(&s_opts_summary, &summary_ref) < 0) {
    elog(LOG_CRIT, "Unable to create status device: %m");
    exit(1);
  }

  /* $$$ also create sensor devs!! */
  /* $$$ sensorcat ... echos relative, streams back text formatted data! */

  /* connect to emrun */
  emrun_opts_t emrun_opts = {
    shutdown: vp2_shutdown,
    data: NULL
  };

  g_timer_add(2000, timer_fired, NULL, NULL, &request_timer);

  emrun_init(&emrun_opts);

  /* start event loop */
  g_main();
  return 1;
} 




See more files for this project here

EmStar

EmStar is a software system for developing and deploying wireless sensor networks involving Linux-based platforms. As the wireless sensor network community has attempted to deploy more complex designs---large-scale, long-lived systems that need self-organization and adaptivity---a number of difficult software design issues have arisen. Advances in software design have not kept pace with the capabilities of hardware. This is because designing for an adaptive, efficient, and useful sensor network has turned out to be surprisingly complex and difficult. EmStar is a Linux-based software framework, whose goal is to dramatically reduce this complexity, enabling work to be shared and reused, and simplifying and speeding the design of new sensor network applications.

Project homepage: http://cvs.cens.ucla.edu/emstar/
Programming language(s): C,Shell Script
License: other

  vp2.c