Code Search for Developers
 
 
  

emview_device.c from EmStar at Krugle


Show emview_device.c syntax highlighted

/*
 *
 * Copyright (c) 2003 The Regents of the University of California.  All 
 * rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Neither the name of the University nor the names of its
 *   contributors may be used to endorse or promote products derived
 *   from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS''
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
 * PARTICULAR  PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "emview_i.h"
#include <time.h>

QUEUE_INST(emview_dnode, ptrs, nodes, emview_dev_node_ext_t, emview_device_t);
QUEUE_INST(emview_device, ptrs, devices, emview_device_t, emview_device_list_t);

/*
 *  data ID assignment
 */

static
int emview_next_id()
{
  static int id = EMVIEW_SIMCONFIG_DATA_ID+1;
  return id++;
}


/*
 * registering a device (how you get data from the proxy) 
 */

emview_device_t *
emview_register_device(emview_device_opts_t *opts)
{
  emview_device_t *dev = g_new0(emview_device_t, 1);
  
  /* initialize the device struct */
  dev->opts = *opts;

  /* copy the strings */
  dev->opts.name = strdup(dev->opts.name);
  if (dev->opts.proxy_string) 
    dev->opts.proxy_string = strdup(dev->opts.proxy_string);

  /* define an ID */
  dev->data_id = emview_next_id();

  /* create the per-node hash table */
  dev->node_data = g_hash_table_new(g_direct_hash, g_direct_equal); 

  /* add to the core */
  emview_device_push(&(_core.device_list), dev);  
  
  return dev;
}


emview_device_opts_t *emview_get_device_opts(emview_device_t *dev)
{
  return &(dev->opts);
}


/*
 *  API call to modify the command string
 */

int emview_update_proxy_string(emview_device_t *dev, char *new_string)
{
  if (dev->opts.proxy_string) 
    free(dev->opts.proxy_string);
  dev->opts.proxy_string = NULL;
  if (new_string)
    dev->opts.proxy_string = strdup(new_string);
  
  /* force resend of new stuff */
  emview_device_update_command();
  return 0;
}


/*
 *  device node data accessors
 */

node_id_t emview_dn_get_node_id(emview_dev_node_t *node_data)
{ return ((emview_dev_node_ext_t *)node_data)->node_id; }

emview_dev_node_t *emview_dn_top(emview_device_t *dev)
{ return (emview_dev_node_t *)emview_dnode_top(dev); }

emview_dev_node_t *emview_dn_next(emview_dev_node_t *node_data)
{ return (emview_dev_node_t *)emview_dnode_next((emview_dev_node_ext_t *)node_data); }


/*
 *  device node lookup/creation
 */

emview_dev_node_t *emview_dev_node_lookup(emview_device_t *dev, node_id_t id)
{
  /* look up the per-node data */
  emview_dev_node_t *dn = 
    (emview_dev_node_t *)g_hash_table_lookup(dev->node_data, (void*)id);

  /* create if not found */
  if (dn == NULL) {
    emview_dev_node_ext_t *dne = g_new0(emview_dev_node_ext_t, 1);
    dne->node_id = id;
    emview_dnode_push(dev, dne);
    g_hash_table_insert(dev->node_data, (void *)id, dne);
    dn = (emview_dev_node_t *)dne;
  }

  return dn;
}


/*
 *  callback functions
 */

static
int emview_device_handle_data(emproxy_reply_hdr_t *reply, void *data)
{
  emview_device_t *ptr;

  elog(LOG_DEBUG(5), "Got data reply.. id=%d, node=%d", reply->data_id, reply->node_id);

  /* if we're logging to the trace.. */
  if (_core.trace_path) {
    emview_trace_log(reply);
  }

  /* check for simconfig data */
  if (reply->data_id == EMVIEW_SIMCONFIG_DATA_ID) {
    emview_node_handle_simconfig(reply);
    goto out;
  }
  
  /* is this a new node? */
  emview_node_heard(reply->node_id, 1);

  /* determine module to pass this to */
  for (ptr = emview_device_top(&(_core.device_list)); ptr;
       ptr = emview_device_next(ptr)) 
    if (ptr->data_id == reply->data_id) 
      if (ptr->opts.data_handler) {

	/* check the data length */
	if (ptr->opts.nominal_data_length &&
	    (ptr->opts.nominal_data_length != reply->data_length)) {
	  elog(LOG_WARNING, "Got data from %s, wrong length (%d bytes, expected %d bytes)",
	       ptr->opts.name,
	       reply->data_length, ptr->opts.nominal_data_length);
	}

	else {
	  /* look up the per-node data */
	  emview_dev_node_t *dn = emview_dev_node_lookup(ptr, reply->node_id);
	  
	  /* call the callback */
	  ptr->opts.data_handler(ptr, reply, dn);
	}

	goto out;
      }
  elog(LOG_WARNING, "Received data for id %d, no such device registered", reply->data_id);

 out:
  return EVENT_RENEW;
}


/*
 *  internal API call to clear and update the emproxy state
 */

void emview_device_update_command()
{
  emview_device_t *ptr;
  buf_t *buf = buf_new();

  /* clear update timer */
  g_event_destroy(_core.device_list.device_recompute_timer);
  
  /* construct a new command */
  bufprintf(buf, "session=%d:type=request\n", _core.device_list.session_nonce);
  bufprintf(buf, "dev=%s:node=-1:id=%d\n", EMSIM_CONFIG_DEVNAME, EMVIEW_SIMCONFIG_DATA_ID);
  
  /* now output each in turn */
  for (ptr = emview_device_top(&(_core.device_list)); ptr;
       ptr = emview_device_next(ptr)) 
    if (ptr->active) {
      elog(LOG_DEBUG(0), "Adding device %s to the command", ptr->opts.proxy_string);
      bufprintf(buf, "%s:id=%d\n", ptr->opts.proxy_string, ptr->data_id);
    }

  /* push it to emproxy */
  emproxy_multi_set_command(_core.device_list.emproxy_event, buf->buf);

  /* log new request to the trace file */
  if (_core.trace_path) {
    buf_t *emproxy_cmd = buf_new();
    emproxy_reply_hdr_t hdr = {
      data_length: buf->len
    };
    bufcpy(emproxy_cmd, &hdr, sizeof(hdr));
    bufcpy(emproxy_cmd, buf->buf, buf->len);
    emview_trace_log((emproxy_reply_hdr_t *)emproxy_cmd->buf);
    buf_free(emproxy_cmd);
  }
  
  /* free the buffer */
  buf_free(buf);
}


void emview_device_clear_active_flags()
{
  emview_device_t *ptr;

  /* clear the active marks on all devices */
  for (ptr = emview_device_top(&(_core.device_list)); ptr;
       ptr = emview_device_next(ptr))
    ptr->active = ptr->opts.always_active;
}


/*
 *  activates a device and will trigger a recomputation of the request string
 */

static
int emview_device_recompute(void *data, int interval, g_event_t *event) 
{
  emview_device_update_command();
  return TIMER_DONE;
}


/* forces timer set if dev is NULL */
void emview_device_activate(emview_device_t *dev)
{
  if (dev)
    elog(LOG_DEBUG(0), "Activating device %s (%d)", dev->opts.name, dev->active);

  /* skip if already active */
  if (dev && dev->active) return;

  if (dev) dev->active = 1;

  /* set the timer */
  if (!g_timer_isset(_core.device_list.device_recompute_timer))
    g_timer_add(EMVIEW_DEVICE_RECOMPUTE_DELAY, emview_device_recompute, NULL, NULL,
		&(_core.device_list.device_recompute_timer));
}


/*
 *  calls timeout handlers
 */

void emview_device_note_timeout(node_id_t id)
{
  emview_device_t *ptr;

  /* call each device's timeout handler */
  for (ptr = emview_device_top(&(_core.device_list)); ptr;
       ptr = emview_device_next(ptr)) 
    if (ptr->opts.node_timeout) {

      /* look up the per-node data */
      emview_dev_node_t *dn = emview_dev_node_lookup(ptr, id);
      
      /* call the callback */
      ptr->opts.node_timeout(ptr, dn);
    }
}

/*
 *  emview device status
 */


static
int emview_device_status_printable(status_context_t *info, buf_t *buf)
{
  //int now = time(0);
  emview_device_t *ptr;
  
  bufprintf(buf, "Active Devices:\n");
  
  for (ptr = emview_device_top(&_core.device_list); ptr;
       ptr = emview_device_next(ptr)) {
    bufprintf(buf, "  dev=%s, id=%d, active=%d\n",
	      ptr->opts.name, ptr->data_id, boolify(ptr->active));    
  }

  bufprintf(buf, "\nCurrent String:\n'%s'\n", 
	    emproxy_multi_get_command(_core.device_list.emproxy_event));
  
  return STATUS_MSG_COMPLETE;
}


/*
 *  Trace Replay
 */


void emview_trace_log(emproxy_reply_hdr_t *reply)
{
  int status;
  status = write(_core.trace_fd, "HELO", 4);
  status = write(_core.trace_fd, reply, sizeof(*reply)+reply->data_length);
  if (status < 0) {
    elog(LOG_CRIT, "Unable to write to trace file %s: %m", _core.trace_path);
    close(_core.trace_fd);
    _core.trace_path = NULL;
  }
}


void emview_trace_close()
{
  /* close and clean up old */
  close(_core.trace_fd);
  frame_processor_destroy(_core.de_frame);
  if (_core.on_deck) {
    free(_core.on_deck);
    _core.on_deck = NULL;
  }
  if (_core.input_trace_path) {
    free(_core.input_trace_path);
    _core.input_trace_path = NULL;
  }
}


static
int emview_trace_packet_handler(frame_context_t *ctx, char *buffer, size_t len)
{
  emproxy_reply_hdr_t *hdr = (emproxy_reply_hdr_t *)buffer;

  /* time yet? */
  /* $$$$$ */
  
  /* is this a emproxy request? */
  if (hdr->data_id == 0) {
  }

  else {
    emview_device_handle_data(hdr, NULL);
  }

  return EVENT_RENEW;
}


int emview_trace_open(char *path)
{
  int fd = open(path, O_RDONLY);
  if (fd < 0) {
    elog(LOG_WARNING, "Unable to open trace file %s: %m", path);
    return -1;
  }

  emview_trace_close();

  /* switch to new file */
  _core.input_trace_path = strdup(path);
  _core.trace_fd = fd;
  set_nonblock(_core.trace_fd, 1);
  {
    frame_opts_t opts = {
      frame_type: FRAME_TYPE_LENGTH,
      frame_start: "HELO",
      length_format: FRAME_LENGTH_INT,
      length_offset: offsetof(emproxy_reply_hdr_t, data_length),
      length_correction: sizeof(emproxy_reply_hdr_t),
      length_valid_max: 65536,
      handle_frame: emview_trace_packet_handler,
      report_eof: 1,
      report_errors: 1
    };

    if (frame_processor_new(&opts, _core.trace_fd, &(_core.de_frame)) < 0){
      elog(LOG_CRIT, "Can't create trace file event: %m");
      exit(1);
    }    
  }

  return 0;
}


/* we get passed an opts struct with the addresses filled */
void emview_devices_init(emproxy_client_opts_t *opts)
{
  char buf[1024];
  
  /* select random nonce */
  _core.device_list.session_nonce = random();

  /* generate an initial null request */
  sprintf(buf, "session=%d:type=request\n", _core.device_list.session_nonce);

  /* fill the opts */
  opts->handler = emview_device_handle_data;
  opts->command = buf;

  /* start loading the trace file */
  if (_core.input_trace_path) {
    char *path = _core.input_trace_path;
    _core.input_trace_path = NULL;
    _core.trace_fd = -1;
    emview_trace_open(path);
  }

  else {
    /* start up request */
    if (emproxy_multi_open(opts, &(_core.device_list.emproxy_event)) < 0) {
      elog(LOG_CRIT, "Unable to connect to emproxy: %m");
      exit(1);
    }
  }

  /* configure (optional) status device */
  {
    status_dev_opts_t opts = {
      device: {
	devname: "/dev/emview/devices"
      },
      printable: emview_device_status_printable
    };  
    g_status_dev(&opts, &(_core.device_list.stat));
  }

}






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

  emview_analysis.c
  emview_analysis.h
  emview_box_component.c
  emview_component.c
  emview_component.h
  emview_config.c
  emview_config.h
  emview_device.c
  emview_device.h
  emview_gui.c
  emview_gui.h
  emview_gui_menu.c
  emview_i.h
  emview_main.c
  emview_node.c
  emview_node.h
  emview_node_component.c
  emview_slots.c
  emview_source.c
  emview_source.h