1:/* getedmdata.c 2: routine to get edm data from NEC PC and make a one-day data file. 3: 4: THIS PROGRAM IS FOR ITO NETWORK. 5: 6: We get only one newline. 7: 8: Shigeru Nakao ... June 2002 */ 9: 10:/* robin.c -- implements simple serial port interaction program */ 11:#include 12:#include 13:#include 14:#include 15:#include 16:#include 17:#include 18:#include 19:#include /* for strerror() */ 20:#include 21:#include 22: 23:void usage(int exitcode, char *error, char *addl) { 24: fprintf(stderr, "Usage: robin [options] \n" 25: " [options] include:\n" 26: " -H for this help\n" 27: " -r for raw mode\n" 28: " -c to add CR with NL on output\n" 29: " -h for hardware flow control\n" 30: " -s for software flow control\n" 31: " -n for no flow control\n" 32: " -b for signalling rate\n"); 33: if (error) fprintf(stderr, "%s: %s\n", error, addl); 34: exit(exitcode); 35:} 36: 37:speed_t symbolic_speed(int speednum) { 38: if (speednum >= 460800) return B460800; 39: if (speednum >= 230400) return B230400; 40: if (speednum >= 115200) return B115200; 41: if (speednum >= 57600) return B57600; 42: if (speednum >= 38400) return B38400; 43: if (speednum >= 19200) return B19200; 44: if (speednum >= 9600) return B9600; 45: if (speednum >= 4800) return B4800; 46: if (speednum >= 2400) return B2400; 47: if (speednum >= 1800) return B1800; 48: if (speednum >= 1200) return B1200; 49: if (speednum >= 600) return B600; 50: if (speednum >= 300) return B300; 51: if (speednum >= 200) return B200; 52: if (speednum >= 150) return B150; 53: if (speednum >= 134) return B134; 54: if (speednum >= 110) return B110; 55: if (speednum >= 75) return B75; 56: return B50; 57:} 58: 59:/* These need to have file scope so that we can use them in 60: * signal handlers */ 61:/* old port termios settings to restore */ 62:static struct termios pots; 63:/* old stdout/in termios settings to restore */ 64:static struct termios sots; 65:/* port file descriptor */ 66:int pf; 67: 68:/* restore original terminal settings on exit */ 69:void cleanup_termios(int signal) { 70: tcsetattr(pf, TCSANOW, &pots); 71:/* tcsetattr(STDIN_FILENO, TCSANOW, &sots); */ 72: exit(0); 73:} 74: 75:/* handle a single escape character */ 76:void send_escape(int fd, char c) { 77: switch (c) { 78: case 'q': 79: /* restore termios settings and exit */ 80: cleanup_termios(0); 81: break; 82: case 'b': 83: /* send a break */ 84: tcsendbreak(fd, 0); 85: break; 86: default: 87: /* pass the character through */ 88: /* "C-\ C-\" sends "C-\" */ 89: write(fd, &c, 1); 90: break; 91: } 92: return; 93:} 94: 95:/* handle escape characters, writing to output */ 96:void cook_buf(int fd, char *buf, int num) { 97: int current = 0; 98: static int in_escape = 0; 99: 100: if (in_escape) { 101: /* cook_buf last called with an incomplete escape sequence */ 102: send_escape(fd, buf[0]); 103: num--; 104: buf++; 105: in_escape = 0; 106: } 107: while (current < num) { 108:# define CTRLCHAR(c) ((c)-0x40) 109: while ((current < num) && (buf[current] != CTRLCHAR('\\'))) current++; 110: if (current) write (fd, buf, current); 111: if (current < num) { 112: /* found an escape character */ 113: current++; 114: if (current >= num) { 115: /* interpret first character of next sequence */ 116: in_escape = 1; 117: return; 118: } 119: send_escape(fd, buf[current]); 120: } 121: num -= current; 122: buf += current; 123: current = 0; 124: } 125: return; 126:} 127: 128:int main(int argc, char *argv[]) { 129: char c; /* used for argument parsing */ 130: struct termios pts; /* termios settings on port */ 131: struct termios sts; /* termios settings on stdout/in */ 132: char *portname; 133: int speed = 0; /* used in argument parsing to set speed */ 134: struct sigaction sact;/* used to initialize the signal handler */ 135: fd_set ready; /* used for select */ 136: int raw = 0; /* raw mode? */ 137: int i = 0; /* used in the multiplex loop */ 138: int done = 0; 139:# define BUFSIZE 1024 140: char buf[BUFSIZE]; 141:# define CTRLCHAR(ch) ((ch)&0x1F) 142: 143: char chr[2], filename[18], ctemp[10], cbuf[BUFSIZE], cbuf2[BUFSIZE]; 144: int jhr, jday, jhour, jmin, input=0; 145: int iyr, imo, idy, ihr, imn, inumchar, iend, maxcharline=408; /*18;*/ 146: FILE *fp; 147: long location=1; 148: 149: struct timeval tv; 150: struct timezone tz; 151: time_t now; 152: 153: poptContext optCon; /* context for parsing command-line options */ 154: struct poptOption optionsTable[] = { 155: { "bps", 'b', POPT_ARG_INT, &speed, 0 }, 156: { "crnl", 'c', 0, 0, 'c' }, 157: { "help", 'H', 0, 0, 'H' }, 158: { "hwflow", 'h', 0, 0, 'h' }, 159: { "noflow", 'n', 0, 0, 'n' }, 160: { "raw", 'r', 0, &raw, 0 }, 161: { "swflow", 's', 0, 0, 's' }, 162: { NULL, 0, 0, NULL, 0 } 163: }; 164: 165:#ifdef DSLEEP 166: /* wait 10 minutes so we can attach a debugger */ 167: sleep(600); 168:#endif 169: 170: if (argc < 2) usage(1, "Not enough arguments", ""); 171: 172: /* Normally, we'd let popt figure out which argument is the 173: port name. Here we're forcing it to be the last one as it 174: eases the rest of the option parsing. */ 175: portname = argv[argc - 1]; 176: pf = open(portname, O_RDWR); 177: if (pf < 0) 178: usage(1, strerror(errno), portname); 179: 180: /* modify the port configuration */ 181: tcgetattr(pf, &pts); 182: pots = pts; 183: /* some things we want to set arbitrarily */ 184: pts.c_lflag &= ~ICANON; 185: pts.c_lflag &= ~(ECHO | ECHOCTL | ECHONL); 186: pts.c_cflag |= HUPCL; 187:/* pts.c_cc[VMIN] = 19;*/ 188: pts.c_cc[VMIN] = 1; 189: pts.c_cc[VTIME] = 0; 190: 191: pts.c_cc[VINTR] = CTRLCHAR('C'); 192: 193: /* Standard CR/LF handling: this is a dumb terminal. 194: * Do no translation: 195: * no NL -> CR/NL mapping on output, and 196: * no CR -> NL mapping on input. 197: */ 198: pts.c_oflag &= ~ONLCR; 199: pts.c_iflag &= ~ICRNL; 200: 201: /* Now deal with the local terminal side */ 202:/* tcgetattr(STDIN_FILENO, &sts); 203: sots = sts; */ 204: /* again, some arbitrary things */ 205:/* sts.c_iflag &= ~(BRKINT | ICRNL); 206: sts.c_iflag |= IGNBRK; 207: sts.c_lflag &= ~ISIG; 208: sts.c_cc[VMIN] = 1; 209: sts.c_cc[VTIME] = 0; 210: sts.c_lflag &= ~ICANON; */ 211: /* no local echo: allow the other end to do the echoing */ 212:/* sts.c_lflag &= ~(ECHO | ECHOCTL | ECHONL); */ 213: 214:/* optCon = poptGetContext("robin", argc, argv, optionsTable, 0); */ 215: optCon = poptGetContext("getedmdata", argc, argv, optionsTable, 0); 216: 217: /* option processing will now modify pts and sts */ 218: while ((c = poptGetNextOpt(optCon)) >= 0) { 219: switch (c) { 220: case 'H': 221: usage(0, NULL, NULL); 222: break; 223: case 'c': 224: /* send CR with NL */ 225: pts.c_oflag |= ONLCR; 226: break; 227: case 'h': 228: /* hardware flow control */ 229: pts.c_cflag |= CRTSCTS; 230: pts.c_iflag &= ~(IXON | IXOFF | IXANY); 231: break; 232: case 's': 233: /* software flow control */ 234: pts.c_cflag &= ~CRTSCTS; 235: pts.c_iflag |= IXON | IXOFF | IXANY; 236: break; 237: case 'n': 238: /* no flow control */ 239: pts.c_cflag &= ~CRTSCTS; 240: pts.c_iflag &= ~(IXON | IXOFF | IXANY); 241: break; 242: } 243: } 244: 245: if (c < -1) { 246: /* an error occurred during option processing */ 247: fprintf(stderr, "%s: %s\n", 248: poptBadOption(optCon, POPT_BADOPTION_NOALIAS), 249: poptStrerror(c)); 250: return 1; 251: } 252: poptFreeContext(optCon); 253: 254: /* speed is not modified unless -b is specified */ 255: if (speed) { 256: cfsetospeed(&pts, symbolic_speed(speed)); 257: cfsetispeed(&pts, symbolic_speed(speed)); 258: } 259: 260: /* set the signal handler to restore the old 261: * termios handler */ 262: sact.sa_handler = cleanup_termios; 263: sigaction(SIGHUP, &sact, NULL); 264: sigaction(SIGINT, &sact, NULL); 265: sigaction(SIGPIPE, &sact, NULL); 266: sigaction(SIGTERM, &sact, NULL); 267: 268: /* Now set the modified termios settings */ 269: tcsetattr(pf, TCSANOW, &pts); 270:/* tcsetattr(STDIN_FILENO, TCSANOW, &sts); */ 271: 272: inumchar=-1; 273: do { 274: FD_ZERO(&ready); 275:/* FD_SET(STDIN_FILENO, &ready); */ 276: FD_SET(pf, &ready); 277: select(pf+1, &ready, NULL, NULL, NULL); 278: if (FD_ISSET(pf, &ready)) { 279: /* pf has characters for us */ 280:/* i = read(pf, buf, BUFSIZE); */ 281: i = read(pf, buf, 1 ); 282: if (i >= 1) { 283: 284: inumchar = inumchar + 1; 285: cbuf[inumchar] = buf[0]; 286: 287:/* write(STDOUT_FILENO, cbuf, inumchar); */ 288: 289: if ( buf[0]=='\n' ) { 290: if ( inumchar == maxcharline ) { 291: 292:/* replace carriage control to new line */ 293: cbuf[maxcharline-1] = '\n'; 294: cbuf[maxcharline] = '\0'; 295: 296: chr[0] = cbuf[8]; 297: chr[1] = cbuf[9]; 298: chr[2] = '\0'; 299: jhr = atoi(chr); /* get hour of data sampling */ 300: 301: 302: if (jhr >= 9) { 303: filename[0] = '.'; 304: filename[1] = '/'; 305: filename[2] = 'd'; 306: filename[3] = 'a'; 307: filename[4] = 't'; 308: filename[5] = '/'; 309: filename[6] = 'i'; 310: filename[7] = 't'; 311: filename[8] = cbuf[0]; 312: filename[9] = cbuf[1]; 313: filename[10] = cbuf[3]; 314: filename[11] = cbuf[4]; 315: filename[12] = cbuf[6]; 316: filename[13] = cbuf[7]; 317: filename[14] = '.'; 318: filename[15] = 'd'; 319: filename[16] = 'a'; 320: filename[17] = 't'; 321: filename[18] = '\0'; 322: printf("filename- %s\n",filename); 323: 324: } else { 325: strncpy(ctemp,cbuf,8); 326: ctemp[0] = cbuf[0]; 327: ctemp[1] = cbuf[1]; 328: ctemp[2] = cbuf[3]; 329: ctemp[3] = cbuf[4]; 330: ctemp[4] = cbuf[6]; 331: ctemp[5] = cbuf[7]; 332: ctemp[6] = ' '; 333: ctemp[7] = ' '; 334: ctemp[8] = ' '; 335: ctemp[9] = ' '; 336: ctemp[10] = '\0'; 337: julian(ctemp, &jday, &jhour, &jmin); 338: jday = jday - 1; 339: invjulian(input,jday,jhour,jmin,&iyr,&imo,&idy,&ihr,&imn); 340: filename[0] = '.'; 341: filename[1] = '/'; 342: filename[2] = 'd'; 343: filename[3] = 'a'; 344: filename[4] = 't'; 345: filename[5] = '/'; 346: iyr = iyr - 1900; 347: if ( iyr > 99 ) iyr = iyr - 100; 348: sprintf(chr,"%02d",iyr); 349: filename[6] = 'i'; 350: filename[7] = 't'; 351: filename[8] = chr[0]; 352: filename[9] = chr[1]; 353: sprintf(chr,"%02d",imo); 354: filename[10] = chr[0]; 355: filename[11] = chr[1]; 356: sprintf(chr,"%02d",idy); 357: filename[12] = chr[0]; 358: filename[13] = chr[1]; 359: filename[14] = '.'; 360: filename[15] = 'd'; 361: filename[16] = 'a'; 362: filename[17] = 't'; 363: filename[18] = '\0'; 364: printf("filename2- %s\n",filename); 365: } 366: 367:/* open file and write data */ 368: 369: fp = fopen(filename,"a"); 370: fputs(cbuf,fp); 371: fclose(fp); 372: } else { 373:/* get date & time */ 374: gettimeofday(&tv,&tz); 375: now = tv.tv_sec; 376: fp = fopen("getedmdata.log","a"); 377: fprintf(fp,"%s -- %s",ctime(&now),cbuf); 378: fclose(fp); 379: } /* for if */ 380:/* reset parameters */ 381: inumchar = -1; 382: strncpy(cbuf," ",19); 383: 384: } 385: } else { 386: done = 1; 387: } 388: 389: } 390:/* if (FD_ISSET(STDIN_FILENO, &ready)) { */ 391: /* standard input has characters for us */ 392:/* i = read(STDIN_FILENO, buf, BUFSIZE); 393: if (i >= 1) { 394: if (raw) { 395: write(pf, buf, i); 396: } else { 397: cook_buf(pf, buf, i); 398: } 399: } else { 400: done = 1; 401: } 402: } */ 403: } while (!done); 404: 405: /* restore original terminal settings and exit */ 406: tcsetattr(pf, TCSANOW, &pots); 407:/* tcsetattr(STDIN_FILENO, TCSANOW, &sots); */ 408: exit(0); 409:} 410: int julian(char s[], int *jday,int *jhour,int *jmin) { 411: 412:/* subroutine JULIAN(iyr,imo,idy,ihr,imn,jday,jhour,jmin) 413: 414:c+ 415:c subroutine JULIAN(iyr,imo,idy,ihr,imn,jday,jhour,jmin) 416:c 417:c routine to convert date/time to 'julian' values (days, hours, mins) 418:c 419:c Input: 420:c iyr,imo,idy - date 421:c ihr,imn - time 422:c 423:c Output: 424:c jday - days after 0000 3 0 0 0 425:c jhour - hours after reference time 426:c jmin - mins after reference time 427:c 428:c NOTE: 429:c input year is AD (ie. usually 2 digit eg. 88) 430:c 431:c 432:c 433:c 434:c 435:c Alan Linde ... May 1987 436:c- 437: Shigeru Nakao ... April 2002 */ 438: 439: int jyr, iyr, jmo, imo, idy, ihr, imn; 440: int itmp1, itmp2; 441: char cyy[4], cjj[2]; 442: 443:/* character to integer */ 444: 445: cyy[0] = s[0]; 446: cyy[1] = s[1]; 447: cyy[2] = '\0'; 448: iyr = atoi(cyy); 449: iyr = iyr + 2000; 450: 451: cjj[0] = s[2]; 452: cjj[1] = s[3]; 453: cjj[2] = '\0'; 454: imo = atoi(cjj); 455: 456: cjj[0] = s[4]; 457: cjj[1] = s[5]; 458: cjj[2] = '\0'; 459: idy = atoi(cjj); 460: 461: cjj[0] = s[6]; 462: cjj[1] = s[7]; 463: cjj[2] = '\0'; 464: ihr = atoi(cjj); 465: 466: cjj[0] = s[8]; 467: cjj[1] = s[9]; 468: cjj[2] = '\0'; 469: imn = atoi(cjj); 470: 471: jyr = iyr; 472: if (imo < 3) { 473: jmo = imo + 9; 474: jyr = jyr - 1; 475: } 476: else 477: jmo = imo - 3; 478: 479: itmp1 = 365.25*jyr; 480: itmp2 = 30.6001*jmo + 0.5; 481: *jday = itmp1 + itmp2 + idy; 482: *jday = *jday - jyr/100 + jyr/400; 483: *jhour = *jday * 24 + ihr; 484: *jmin = *jhour* 60 + imn; 485: 486: return 0; 487:} 488: invjulian(int input, int jday, int jhour, int jmin, int *iyr, int *imo, 489: int *idy, int *ihr, int *imn) { 490:/* subroutine INVJULIAN(input,jday,jhour,jmin,iyr,imo,idy,ihr,imn) 491:c+ 492:c subroutine INVJULIAN(input,jday,jhour,jmin,iyr,imo,idy,ihr,imn) 493:c 494:c routine to convert 'julian' time (days/hours/mins) to date/time 495:c 496:c Input: 497:c input - 0 = input days, 1 = hours, 2 = minutes 498:c jday - # of days 499:c jhour - # of hours 500:c jmin - # of minutes 501:c 502:c Output: 503:c iyr,imo,idy - date 504:c ihr,imn - time 505:c 506:c NOTE: 507:c Origin time is 0000 3 0 0 0 (actually Feb 29) 508:c ie. 0000 3 1 is day 1 509:c 510:c Output year is AD ie. usually 4 digit (eg 1988) 511:c 512:c 513:c 514:c Alan Linde ... May 1987 515:c- 516: 517: Shigeru Nakao ... April 2002 */ 518: 519:/* logical repeat */ 520: 521: int ncheck, nyrdays, nleft, minr; 522: int itmp, kyr, repeat; 523: 524: 525: if (input == 0) { 526: jhour = jday * 24; 527: jmin = jday * 1440; 528: minr = 0; 529: } 530: else if (input == 1) { 531: jday = jhour / 24; 532: jmin = jhour * 60; 533: minr = jmin - jday * 1440; 534: } 535: else if (input == 2) { 536: jday = jmin / 1440; 537: jhour = jmin / 60; 538: minr = jmin - jday * 1440; 539: } 540: 541: *ihr = jhour - jday * 24; 542: 543: 544: *imn = minr - *ihr * 60; 545: 546: *iyr = jday / 365.25; 547: do { 548: itmp = 365.25*(*iyr); 549: nyrdays = itmp - (*iyr)/100 + (*iyr)/400; 550: ncheck = jday - nyrdays; 551: repeat = 0; 552: if (ncheck == 0) 553: *iyr = *iyr - 1; 554: else if (ncheck > 366) { 555: (*iyr) = (*iyr) + 1; 556: repeat = 1; 557: } 558: else if (ncheck == 366) { 559: kyr = (*iyr) + 1; 560: if ((kyr%4)!=0 || ((kyr%100)==0 && (kyr%400)!=0) ) { 561: *iyr = (*iyr) + 1; 562: repeat = 1; 563: } 564: } 565: 566: } while ( repeat == 1 ); 567: 568: itmp = 365.25*(*iyr); 569: nyrdays = itmp - (*iyr)/100 + (*iyr)/400; 570: nleft = jday - nyrdays; 571: *imo = (nleft-0.5)/30.6; 572: itmp = 30.6001*(*imo) + 0.5; 573: *idy = nleft - itmp; 574: 575: *imo = (*imo) + 3; 576: if ((*imo) > 12) { 577: *imo = (*imo) - 12; 578: *iyr = (*iyr) + 1; 579: } 580: 581: return 0; 582:}