⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 node-comm.cc

📁 Develop Zigbee network real-time Os
💻 CC
字号:
#include <sys/stat.h>#include <termios.h>#include <time.h>#include <stdio.h>#include <getopt.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <sys/time.h>#include <sys/types.h>#include <fcntl.h>#include <inttypes.h>#include <string>#include <errno.h>#include "node-comm.hh"#include "crc.h"/* * Define "NO_NODE_POWER" to disable power measurement via DAQ * This requires a specific DAQ and a bunch very shaky drivers */#ifndef NO_NODE_POWER#define NO_NODE_POWER#endif/************************************************************************** * * struct timeval functions * *************************************************************************/const int usecs_pr_sec = 1000000;void normalize_timeval(struct timeval &res){  while (res.tv_usec > usecs_pr_sec) {    res.tv_usec -= usecs_pr_sec;    res.tv_sec += 1;  }  while (res.tv_usec < 0) {    res.tv_usec += usecs_pr_sec;    res.tv_sec -= 1;  }}struct timeval operator+(const struct timeval& a, const struct timeval &b){  struct timeval res;    res.tv_sec = a.tv_sec + b.tv_sec;  res.tv_usec = a.tv_usec + b.tv_usec;  normalize_timeval(res);    return res;}struct timeval operator-(const struct timeval& a, 			 const struct timeval& b){  struct timeval res;    res.tv_sec = a.tv_sec - b.tv_sec;  res.tv_usec = a.tv_usec - b.tv_usec;  normalize_timeval(res);    return res;}double tv2f(const struct timeval &t){  return (double)t.tv_sec + (double)t.tv_usec / (double)usecs_pr_sec;}/************************************************************************** * * Input file handling * *************************************************************************/bool parse_line(char *buffer, int *res){  char *colon = buffer;  for (int i = 0; i < 6; i++) {    colon = strchr(colon, ';');        if (!colon)      return false;    colon++;    res[i] = atoi(colon);  }  return true;}int count_lines = 0;bool fill_buffer(FILE *f, uint16_t *buf){  char buffer[1024];  uint16_t *buf_pos = buf;  for (int i = 0; i < 42; ) {    if (fgets(buffer, 1024, f)) {      int val[6];            if (parse_line(buffer, val)) {	*buf_pos++ = val[1];	*buf_pos++ = val[2];	*buf_pos++ = val[3];	i++;	count_lines++;      }    } else {      return false;    }  }  return true;}/************************************************************************** * * Serial communication * *************************************************************************/char line[1024];char *linepos = line;void flush_serial(int fd){  linepos = line;  read(fd, line, 1024);}char *read_line(int fd, struct timeval *tv){  static char res[1024];  fd_set rfds;  /* Do we already have a new line? */  char * pos;    pos = strchr(line, '\n');  if (pos) {    *pos = '\0';        strncpy(res, line, 1024);        memmove(line, pos + 1, 1024 - (pos - line) - 1);    linepos -= pos - line + 1;    return res;  }  while (1) {    FD_ZERO(&rfds);    FD_SET(fd, &rfds);    int retval = select(fd + 1, &rfds, NULL, NULL, tv);    if (retval != 0) {      retval = read(fd, linepos, 1024 - (linepos - line));      if (retval) {	linepos += retval;	*linepos = '\0';		pos = strchr(line, '\n');	if (pos) {	  *pos = '\0';	  	  strncpy(res, line, 1024);	  	  memmove(line, pos + 1, 1024 - (pos - line) - 1);	  linepos -= pos - line + 1;	  return res;	}      }    } else {      return 0;    }  } }uint8_t *read_256bytes(int fd){  static uint8_t buffer[256];  uint8_t *buffer_pos = buffer;  int retval;  fd_set rfds;  while (buffer_pos != buffer + 256) {    FD_ZERO(&rfds);    FD_SET(fd, &rfds);    retval = select(fd + 1, &rfds, NULL, NULL, 0);    if (retval != 0) {      retval = read(fd, buffer_pos, 256 - (buffer_pos - buffer));            if (retval) {	buffer_pos += retval;      }    }  }  return buffer;}uint8_t *read_block(int fd){  const int block_size = 259;  static uint8_t buffer[block_size];  uint8_t *buffer_pos = buffer;  int retval;  fd_set rfds;  struct timeval tv;  memset(buffer, 0xAA, block_size);  while (buffer_pos - buffer < block_size) {    FD_ZERO(&rfds);    FD_SET(fd, &rfds);    if (buffer_pos == buffer) {      tv.tv_sec = 1;      tv.tv_usec = 0;    } else {      tv.tv_sec = 5;      tv.tv_usec = 0;    }    retval = select(fd + 1, &rfds, NULL, NULL, &tv);    if (retval > 0) {      retval = read(fd, buffer_pos, block_size - (buffer_pos - buffer));            if (retval > 0) {				buffer_pos += retval;				if ((buffer_pos - buffer) == 2 && buffer[0] == 'f' 						&& buffer[1] == '\n') {					return 0;				}       } else if (retval < 0) {				throw std::string(std::string("Error reading: ") + strerror(errno));      } else if (retval == 0) {				fprintf(stderr, "Strange, read 0 bytes?\n");      }    } else if (retval == 0) {      if (buffer_pos == buffer) {				write(fd, "!", 1);      } else {				throw std::string("Timeout reading block");      }    } else {      throw std::string("Select error");    }  }  uint16_t crc = 0xFFFF;  	//	fprintf(stderr, "\n");  for (size_t j = 0; j < block_size - 2; j++) {		/*		fprintf(stderr, " %02X", ((uint8_t*)buffer)[j]);		if (j % 16 == 15) 		fprintf(stderr, "\n");*/		    crc = crcByte(crc, ((uint8_t*)buffer)[j]);	}  if (crc != *(uint16_t*)(buffer + block_size - 2)) {    char buf[1024];    snprintf(buf, 1024, "CRC in packet is 0x%04X. Should have been 0x%04X\n", 	     *(uint16_t*)(buffer + block_size - 2), crc);    throw std::string(buf);  }  return buffer + 1;}uint16_t real_buffer[4 * 239 * 256 / sizeof(uint16_t)];void sync_with_node(int fd){  printf("Syncing with node... ");  fflush(stdout);  while (1) {    flush_serial(fd);    write(fd, "p", 1);    struct timeval tv;    tv.tv_sec = 1;    tv.tv_usec = 0;    char *line = read_line(fd, &tv);    if (line == 0) {      uint8_t buf[256];      memset(buf, 0, 256);      write(fd, buf, 256);      continue;    }          if (strcmp(line, "pong") == 0) {      break;    }  }  printf("done\n");}void flush_node(int fd) {  printf("Flushing... ");  write(fd, "f", 2);  char *line = read_line(fd, 0);  if (strcmp(line, "done") != 0) {    printf("Got \"%s\" instead of done. Bailing out\n", line);    exit(1);  }  printf("done\n");  }const uint16_t total_pages = 4096 / 256;void really_write(int fd, const void *buf, size_t len){  size_t left = len;  do {    size_t res = write(fd, (const uint8_t*)buf + (len - left), left);    /*    for (uint8_t* i = (uint8_t*)buf + (len - left) ;	 i< (uint8_t*)buf+len ;	 i++) {      printf("%c", buf);      }*/    if (res > 0) {      left -= res;    } else if (res < 0) {      if (errno == EINTR) {	continue;      } else {	perror("Error writing to node");	    exit(1);      }    }  } while (left > 0);}int uploaded_pages;bool upload_pages(int fd, FILE *data_file){  struct timeval tv;  tv.tv_sec = 1;  tv.tv_usec = 0;  // Read potential left-over data from the node.  char *line = read_line(fd, &tv);  printf("Preparing for data upload... ");  write(fd, "a", 2);  line = read_line(fd, 0);  if (strcmp(line, "ok") != 0) {    printf("Got \"%s\" instead of ok. Bailing out\n", line);    exit(1);  }  printf("done\n");  printf("Uploading pages");  uint16_t *buffer = real_buffer;  bool more_data = true;  uploaded_pages = 0;  for (int i = 0; i < total_pages; i++) {    bool retry = false;    more_data = fill_buffer(data_file, buffer);    do {      if (retry) {				sleep(1);				flush_serial(fd);      }      really_write(fd, "b", 1);      really_write(fd, buffer, 256);	          uint16_t crc = 0xFFFF;      for (size_t j = 0; j < 256; j++)				crc = crcByte(crc, ((uint8_t*)buffer)[j]);      really_write(fd, &crc, 2);      struct timeval tv;      tv.tv_sec = 1;      tv.tv_usec = 0;            char * line = read_line(fd, &tv);      if (!line) {				printf("Node did not respond in a timely manner. Trying again.\n");				char buf[256];				memset(buf, 0, 256);				write(fd, buf, 256);				read_line(fd, &tv);				retry = true;      } else {				if (strcmp(line, "ok") != 0) {					retry = true;					printf("Node responded with \"%s\". Trying again (CRC 0x%X).\n", line, crc);				} else {					printf(".");					fflush(stdout);					retry = false;					uploaded_pages++;				}      }    } while (retry);    buffer += 256 / sizeof(*buffer);    if (!more_data)      break;  }	  write(fd, "x", 1);  printf(" done\n");  return more_data;}void read_uploaded_pages(int fd){  printf("Reading pages back");  uint16_t *buffer = real_buffer;    for (int i = 0; i < uploaded_pages; i++) {    write(fd, "r", 1);        uint8_t *buf = read_256bytes(fd);        if (memcmp(buffer, buf, 256) == 0) {      printf(".");      fflush(stdout);    } else {      printf("\nPosition %d did not match\n", i);      printf("Data sent to node:\n");      for (int j = 0; j < 256; j++) {	printf("%02x ", ((uint8_t*)buffer)[j]);	if ((j + 1) % 16 == 0)	  printf("\n");      }      printf("\n");      printf("Data received from node:\n");      for (int j = 0; j < 256; j++) {	printf("%02x ", ((uint8_t*)buf)[j]);	if ((j + 1) % 16 == 0)	  printf("\n");      }      printf("\n");			exit(1);    }    buffer += 256 / sizeof(*buffer);  }    write(fd, "x", 1);    printf("\n");}double total_time = 0;double total_watt = 0;int count_watt = 0;void do_compress(int fd, FILE *out_file, bool cont){  struct timeval start_time, end_time;  if (out_file) {    write(fd, "C", 1);  } else {    write(fd, "c", 1);  }#ifndef NO_NODE_POWER  start_power();#endif  gettimeofday(&start_time, 0);  printf("Compressing data");  fflush(stdout);    uint8_t *data = 0;  do {    try {      data = read_block(fd);    } catch (std::string &e) {      printf(("\nLost sync with node (error: " + e 	      + "). Flushing, and requesting resend.\n").c_str());      sleep(1);      uint8_t buf[1024];      printf("Read %d bytes while flushing.\n", read(fd, buf, 1024));      write(fd, "a", 1);      data = buf;      continue;    }    if (out_file && data) {      write(fd, "o", 1);      fwrite(data, 256, 1, out_file);      printf(".");      fflush(stdout);    }  } while (data != 0);  gettimeofday(&end_time, 0);#ifndef NO_NODE_POWER  double power = stop_power();#endif  printf("\nReceived end signal\n");  fflush(stdout);  printf("Compression took: %6.4f seconds.", 	 tv2f(end_time - start_time));#ifndef NO_NODE_POWER   printf(" Average power: %6.4f mW", power);#endif       printf("\n");  total_time += tv2f(end_time - start_time);#ifndef NO_NODE_POWER  total_watt += power;  count_watt++;#endif  if (!cont && out_file) {    write(fd, "F", 1);    try {      data = read_block(fd);      fflush(stdout);    } catch (std::string &e) {      printf(("Error: " + e + "\n").c_str());      exit(0);    }    if (data) {      fwrite(data, 256, 1, out_file);    }  }}// Borrowed from miniterm.cint cook_baud(int baud){    int cooked_baud = 0;    switch ( baud )    {    case     50: cooked_baud =     B50; break;    case     75: cooked_baud =     B75; break;    case    110: cooked_baud =    B110; break;    case    134: cooked_baud =    B134; break;    case    150: cooked_baud =    B150; break;    case    200: cooked_baud =    B200; break;    case    300: cooked_baud =    B300; break;    case    600: cooked_baud =    B600; break;    case   1200: cooked_baud =   B1200; break;    case   1800: cooked_baud =   B1800; break;    case   2400: cooked_baud =   B2400; break;    case   4800: cooked_baud =   B4800; break;    case   9600: cooked_baud =   B9600; break;    case  19200: cooked_baud =  B19200; break;    case  38400: cooked_baud =  B38400; break;    case  57600: cooked_baud =  B57600; break;    case 115200: cooked_baud = B115200; break;    case 230400: cooked_baud = B230400; break;    }    return cooked_baud;}int main(int argc, char * argv[]) {  struct termios oldtio, newtio;  int fd, ser_speed=cook_baud(230400);  char *input_file_name = NULL;  char *output_file_name = NULL;  char *serial_device = NULL;  int max_runs = -1;  FILE *data_file;  FILE *out_file = 0;  int c;  while ((c = getopt(argc, argv, "hr:d:o:s:")) != EOF ){    switch (c) {    case 'h':      printf("Usage: node-comm input-file [-d device] [-s speed] [-r runs] [-o ouput file]\n\n"	     " -h             This help message\n"	     " -d             The serial device to communicate with the mote\n"	     " -s             The transfer rate of the serial device (speed) \n"	     " -r             Maximum number of blocks to compress\n"	     " -o             Output file\n"	     );      return 0;      break;    case 'r':      max_runs = atoi(optarg);      break;    case 'd':      serial_device = optarg;      break;    case 's':      if ( (ser_speed = cook_baud(atoi(optarg))) == 0 ) {	printf("Bad serial speed\n");	return -1;      }      break;    case 'o':      output_file_name = optarg;      break;    }  }  if (optind >= argc) {    fprintf(stderr, "You must specify a file to upload (-h for help)\n");    return -1;  } else {    input_file_name = argv[optind];  }  if (output_file_name != NULL) {    out_file = fopen(output_file_name, "w");    if (!out_file) {      perror("Cannot open output file");    }  }  data_file = fopen(input_file_name, "r");  if (!data_file) {    perror("Cannot open data file");    exit(1);  }  if (serial_device == NULL){    serial_device = "/dev/ttyUSB0";  }  fd = open(serial_device, O_RDWR);  if (fd < 0) {    perror("Cannot open serial port");    exit(1);  }  tcgetattr(fd, &oldtio);	/* save current serial port settings */  memset(&newtio, 0, sizeof (newtio));  //newtio.c_cflag = B230400 | CS8 | CLOCAL | CREAD | HUPCL;  newtio.c_cflag = ser_speed | CS8 | CLOCAL | CREAD | HUPCL;  newtio.c_iflag = IGNBRK;  newtio.c_oflag = 0;  newtio.c_lflag = 0;//FLUSHO;  //  tcflush(fd, TCIOFLUSH);  tcsetattr(fd, TCSANOW, &newtio);  tcflush(fd, TCIOFLUSH);#ifndef NO_NODE_POWER  init_power();#endif     sync_with_node(fd);  flush_node(fd);  bool cont = true;  int cnt=0;  while (cont) {    cont = upload_pages(fd, data_file);    read_uploaded_pages(fd);    do_compress(fd, out_file, cont);    cnt++;    if (max_runs>0) {      if (cnt >= max_runs) {	cont = false;      }    }  }  printf("End results:\n");  printf("  Compressed lines: %d\n", count_lines);  printf("  Compression time: %6.4f s\n", total_time);#ifndef NO_NODE_POWER  printf("  Average Power   : %6.4f mW\n", total_watt / count_watt);  halt_power();#endif  return 0;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -