00001
00002 #include <stdio.h>
00003 #include <stdlib.h>
00004 #include <errno.h>
00005 #include <stdarg.h>
00006 #include <unistd.h>
00007 #include <ctype.h>
00008 #include <fcntl.h>
00009 #include <math.h>
00010 #include <poll.h>
00011
00012 #include "ocean.h"
00013 #include "ros/time.h"
00014
00015 #define FILE_LOGGING 0
00016
00017 using namespace willowgarage::ocean;
00018
00019
00020 const int ocean::NMEA_MAX;
00021 const int ocean::MAXTAGLEN;
00022 const int ocean::MAXCHANNELS;
00023
00024 const int ocean::INPUT_BUF_SIZE;
00025 const int ocean::OUTPUT_BUF_SIZE;
00026 const unsigned int ocean::MAX_PACKET_LENGTH;
00027 const int ocean::BAD_PACKET;
00028 const int ocean::NO_PACKET;
00029 const int ocean::NMEA_PACKET;
00030
00031
00032
00033
00034 const struct ocean::regPair ocean::regList[] = {
00035 {"Manufacturer Access" ,"" , 0x00},
00036 {"Remaining Capacity Alarm" ,"" , 0x01},
00037 {"Remaining Time Alarm" ,"min" , 0x02},
00038 {"Battery Mode" ,"" , 0x03},
00039 {"At Rate" ,"mA" , 0x04},
00040 {"At Rate Time To Full" ,"min" , 0x05},
00041 {"At Rate Time To Empty" ,"min" , 0x06},
00042 {"At Rate OK" ,"bool" , 0x07},
00043 {"Temperature" ,"0.1 K" , 0x08},
00044 {"Voltage" ,"mV" , 0x09},
00045 {"Current" ,"mA" , 0x0a},
00046 {"Average Current" ,"mA" , 0x0b},
00047 {"Max Error" ,"%" , 0x0c},
00048 {"Relative State Of Charge" ,"%" , 0x0d},
00049 {"Absolute State Of Charge" ,"%" , 0x0e},
00050 {"Remaining Capacity" ,"mAh" , 0x0f},
00051 {"Full Charge Capacity" ,"mAh" , 0x10},
00052 {"Run Time To Empty" ,"min" , 0x11},
00053 {"Average Time To Empty" ,"min" , 0x12},
00054 {"Average Time To Full" ,"min" , 0x13},
00055 {"Battery Status" ,"" , 0x16},
00056 {"Cycle Count" ,"cycle" , 0x17},
00057 {"Design Capacity" ,"mAh" , 0x18},
00058 {"Design Voltage" ,"mV" , 0x19},
00059 {"Specification Info" ,"" , 0x1a},
00060 {"Manufacture Date" ,"DMY" , 0x1b},
00061 {"Serial Number" ,"uint" , 0x1c},
00062 {"Manufacture Name" ,"string", 0x20},
00063 {"Device Name" ,"string", 0x21},
00064 {"Device Chemistry" ,"string", 0x22},
00065 {"Manufacture Data" ,"" , 0x23}
00066 };
00067 const unsigned ocean::regListLength(sizeof(regList)/ sizeof(struct regPair));
00073 ocean::ocean ( int id, int debug)
00074 {
00075 debuglevel = debug;
00076 server.id = id;
00077 server.battery.resize(4);
00078
00079
00080 for (uint i = 0; i < server.battery.size(); ++i)
00081 server.battery[i].last_battery_update = ros::Time(-1);
00082 }
00083
00084 ocean::~ocean ()
00085 {
00086 if (close (inputDevice) != 0)
00087 {
00088 fprintf (stderr, "failed closing serial device: %s\n", strerror (errno));
00089 }
00090 }
00091
00092 void
00093 ocean::setDebugLevel (int level)
00094 {
00095 debuglevel = level;
00096 }
00097
00098 void
00099 ocean::initialize (const std::string &input_dev)
00100 {
00101 inputDevice = open (input_dev.c_str(), O_RDWR | O_NOCTTY);
00102
00103 if (inputDevice < 0)
00104 {
00105 fprintf (stderr, "failed to open tty device [%s]: %s\n", input_dev.c_str(), strerror (errno));
00106 }
00107 if (isatty (inputDevice) != 1)
00108 {
00109 fprintf (stderr, "Device [%s] not a tty device.\n", input_dev.c_str());
00110 }
00111 report (2, "Device opened dev=%d\n", inputDevice);
00112
00113 tcgetattr (inputDevice, &ttyset);
00114
00115 ttyset.c_cflag &= ~(PARENB | PARODD | CRTSCTS);
00116 ttyset.c_cflag |= CREAD | CLOCAL;
00117 ttyset.c_iflag = ttyset.c_oflag = ttyset.c_lflag = (tcflag_t) 0;
00118
00119 set_speed (19200);
00120
00121 #if (FILE_LOGGING > 0)
00122 char logname[128];
00123 sprintf ( logname, "/tmp/oceanServer%c.log", input[strlen(input) -1]);
00124 report (2, "Logging to file: %s\n", logname);
00125
00126 outputFile = open( logname, (O_WRONLY | O_APPEND ) );
00127
00128 if(outputFile < 0)
00129 {
00130 if(errno == ENOENT )
00131 {
00132 outputFile = open( logname, (O_WRONLY | O_CREAT), (S_IRWXU | S_IRWXG) );
00133 }
00134
00135 if((outputFile < 0))
00136 {
00137 report (2, "Failed to open log file: %d\n", errno);
00138 close(inputDevice);
00139 exit(outputFile);
00140 }
00141 }
00142 #endif
00143
00144 if(commTest())
00145 resetOcean();
00146
00147 }
00148
00149 void
00150 ocean::read_file (const std::string &input)
00151 {
00152 inputDevice = open (input.c_str(), O_RDONLY);
00153 if (inputDevice < 0)
00154 {
00155 fprintf (stderr, "failed to open tty file [%s]: %s\n", input.c_str(), strerror (errno));
00156 }
00157
00158 packet_reset();
00159 }
00160
00161 int ocean::commTest()
00162 {
00163 int maxTries = 10;
00164 fd_set rfds;
00165 struct timeval tv;
00166 int retval;
00167
00168 packet_reset();
00169
00170 int listenCount = 50;
00171 do
00172 {
00173 maxTries = 10;
00174
00175 while((packetType != NMEA_PACKET) && (maxTries--))
00176 {
00177 report(5,"commTest: call packet_get\n");
00178 int result = NO_PACKET;
00179
00180 FD_ZERO(&rfds);
00181 FD_SET(inputDevice, &rfds);
00182 tv.tv_sec = 2;
00183 tv.tv_usec = 0;
00184
00185 retval = select( inputDevice + 1, &rfds, NULL, NULL, &tv);
00186 if(retval < 0)
00187 report(0, "select error\n");
00188 else if(retval > 0)
00189 {
00190 {
00191 report(5, "calling packet_get\n");
00192 result = packet_get();
00193 }
00194 }
00195 else
00196 {
00197 report(2, "select timeout\n");
00198 listenCount -= 10;
00199 maxTries = 0;
00200 }
00201 usleep(1000);
00202 }
00203
00204 if(packetType == NMEA_PACKET)
00205 {
00206 report(5,"NMEA packet\n");
00207 if(nmea_parse() > 0)
00208 {
00209 return(0);
00210 }
00211 } else
00212 report(5,"non NMEA packet\n");
00213
00214 report(6, "listenCount=%d\n", listenCount);
00215 } while( listenCount-- > 0);
00216
00217 return(-1);
00218 }
00219
00220 void
00221 ocean::resetOcean()
00222 {
00223 report(5, "Sending ocean reset string\n");
00224 string_send(" ");
00225 usleep(1000);
00226 string_send("x");
00227 usleep(1000);
00228 }
00229
00230 int
00231 ocean::run (void)
00232 {
00233 int status (0);
00234
00235 packet_get ();
00236 if (packetType == NMEA_PACKET)
00237 {
00238 status = nmea_parse ();
00239 }
00240 return status;
00241 }
00242
00246 void
00247 ocean::flush (void)
00248 {
00249 tcflush (inputDevice, TCIOFLUSH);
00250 }
00251
00252
00253 int
00254 ocean::get_speed (void)
00255 {
00256 speed_t code = cfgetospeed (&ttyset);
00257 switch (code)
00258 {
00259 case B0:
00260 return (0);
00261 case B300:
00262 return (300);
00263 case B1200:
00264 return (1200);
00265 case B2400:
00266 return (2400);
00267 case B4800:
00268 return (4800);
00269 case B9600:
00270 return (9600);
00271 case B19200:
00272 return (19200);
00273 case B38400:
00274 return (38400);
00275 case B57600:
00276 return (57600);
00277 default:
00278 return (115200);
00279 }
00280 }
00281
00282 void
00283 ocean::set_speed (int newspeed)
00284 {
00285 unsigned int rate;
00286 if (newspeed < 300)
00287 rate = B0;
00288 else if (newspeed < 1200)
00289 rate = B300;
00290 else if (newspeed < 2400)
00291 rate = B1200;
00292 else if (newspeed < 4800)
00293 rate = B2400;
00294 else if (newspeed < 9600)
00295 rate = B4800;
00296 else if (newspeed < 19200)
00297 rate = B9600;
00298 else if (newspeed < 38400)
00299 rate = B19200;
00300 else if (newspeed < 57600)
00301 rate = B38400;
00302 else if (newspeed < 115200)
00303 rate = B57600;
00304 else
00305 rate = B115200;
00306
00307 if (cfsetispeed (&ttyset, B0) != 0)
00308 report (0, "Failed setting input speed\n");
00309 if (cfsetospeed (&ttyset, rate) != 0)
00310 report (0, "Failed setting output speed\n");
00311
00312 ttyset.c_iflag &= ~(PARMRK | INPCK);
00313 ttyset.c_cflag &= ~(CSIZE | CSTOPB | PARENB | PARODD);
00314
00315 ttyset.c_cflag |= CS8;
00316
00317 if (tcsetattr (inputDevice, TCSANOW, &ttyset) != 0)
00318 report (0, "Failed to configure serial device\n");
00319
00320 flush ();
00321 report (1, "set_speed speed=%d rate=%x\n", newspeed, rate);
00322
00323 currentBaudRate = (unsigned int) newspeed;
00324 packet_reset ();
00325 }
00326
00327 void
00328 ocean::report (int errlevel, const char *fmt, ...)
00329 {
00330 if (errlevel <= debuglevel)
00331 {
00332 char buf[BUFSIZ], buf2[BUFSIZ], *sp;
00333 va_list ap;
00334
00335 (void) strcpy (buf, "ocean: ");
00336 va_start (ap, fmt);
00337 (void) vsnprintf (buf + strlen (buf), sizeof (buf) - strlen (buf), fmt,
00338 ap);
00339 va_end (ap);
00340
00341 buf2[0] = '\0';
00342 for (sp = buf; *sp != '\0'; sp++)
00343 if (isprint (*sp)
00344 || (isspace (*sp) && (sp[1] == '\0' || sp[2] == '\0')))
00345 (void) snprintf (buf2 + strlen (buf2), 2, "%c", *sp);
00346 else
00347 (void) snprintf (buf2 + strlen (buf2), 6, "\\x%02x", (unsigned) *sp);
00348
00349 (void) fputs (buf2, stderr);
00350 }
00351 }
00352
00353
00354 enum
00355 {
00356 GROUND_STATE,
00357 NMEA_DOLLAR,
00358 NMEA_PUB_LEAD,
00359 NMEA_LEADER_END,
00360 NMEA_CR,
00361 NMEA_RECOGNIZED
00362 };
00363
00364 char *
00365 ocean::gpsd_hexdump (void *binbuf, size_t binbuflen)
00366 {
00367 static char hexbuf[MAX_PACKET_LENGTH * 2 + 1];
00368 size_t i;
00369 size_t len =
00370 (size_t) ((binbuflen >
00371 MAX_PACKET_LENGTH) ? MAX_PACKET_LENGTH : binbuflen);
00372 char *ibuf = (char *) binbuf;
00373 memset (hexbuf, 0, sizeof (hexbuf));
00374
00375 for (i = 0; i < len; i++)
00376 {
00377 (void) snprintf (hexbuf + (2 * i), 3, "%02x",
00378 (unsigned int) (ibuf[i] & 0xff));
00379 }
00380 return hexbuf;
00381 }
00382
00388 void
00389 ocean::nextstate (unsigned char c)
00390 {
00391 switch (packetState)
00392 {
00393 case GROUND_STATE:
00394 if (c == '$')
00395 {
00396 packetState = NMEA_DOLLAR;
00397 }
00398 break;
00399
00400 case NMEA_DOLLAR:
00401 if (c == 'S')
00402 packetState = NMEA_LEADER_END;
00403 else if (c == 'C')
00404 packetState = NMEA_LEADER_END;
00405 else if (c == 'B')
00406
00407 packetState = NMEA_LEADER_END;
00408 else
00409 packetState = GROUND_STATE;
00410 break;
00411
00412
00413
00414
00415
00416
00417
00418
00419 case NMEA_LEADER_END:
00420 if (c == '\r')
00421 packetState = NMEA_CR;
00422 else if (c == '\n')
00423
00424 packetState = NMEA_RECOGNIZED;
00425 else if (c == '$')
00426
00427 packetState = NMEA_DOLLAR;
00428 else if (!isprint (c))
00429 packetState = GROUND_STATE;
00430 break;
00431
00432 case NMEA_CR:
00433 if (c == '\n')
00434 packetState = NMEA_RECOGNIZED;
00435 else
00436 packetState = GROUND_STATE;
00437 break;
00438 case NMEA_RECOGNIZED:
00439 if (c == '$')
00440 packetState = NMEA_DOLLAR;
00441 else
00442 packetState = GROUND_STATE;
00443 break;
00444
00445 }
00446 }
00447
00448 #define STATE_DEBUG
00449
00450
00451 void
00452 ocean::packet_accept (int packet_type)
00453 {
00454 size_t packetlen = inbufptr - inbuffer;
00455 if (packetlen < sizeof (outbuffer))
00456 {
00457 memcpy ((void *) outbuffer, (void *) inbuffer, packetlen);
00458 outbuflen = packetlen;
00459 outbuffer[packetlen] = '\0';
00460 packetType = packet_type;
00461 #ifdef STATE_DEBUG
00462 report (6, "Packet type %d accepted %d = %s\n",
00463 packet_type, packetlen, gpsd_hexdump (outbuffer, outbuflen));
00464 #endif
00465 }
00466 else
00467 {
00468 report (1, "Rejected too long packet type %d len %d\n",
00469 packet_type, packetlen);
00470 }
00471 }
00472
00473
00474 void
00475 ocean::packet_discard ()
00476 {
00477 size_t discard = inbufptr - inbuffer;
00478 size_t remaining = inbuflen - discard;
00479 inbufptr = (unsigned char *) memmove (inbuffer, inbufptr, remaining);
00480 inbuflen = remaining;
00481 #ifdef STATE_DEBUG
00482 report (6, "Packet discard of %d, chars remaining is %d = %s\n",
00483 discard, remaining, gpsd_hexdump (inbuffer, inbuflen));
00484 #endif
00485 }
00486
00487
00488 void
00489 ocean::character_discard ()
00490 {
00491 memmove (inbuffer, inbuffer + 1, (size_t)-- inbuflen);
00492 inbufptr = inbuffer;
00493 #ifdef STATE_DEBUG
00494 report (6, "Character discarded, buffer %d chars = %s\n",
00495 inbuflen, gpsd_hexdump (inbuffer, inbuflen));
00496 #endif
00497 }
00498
00499
00500
00501
00502
00503 #define getword(i) (short)(session->inbuffer[2*(i)] | (session->inbuffer[2*(i)+1] << 8))
00504
00505
00506
00507 ssize_t
00508 ocean::packet_parse (size_t newdata)
00509 {
00510 #ifdef STATE_DEBUG
00511 report (6, "Read %d chars to buffer offset %d (total %d): %s\n",
00512 newdata,
00513 inbuflen, inbuflen + newdata, gpsd_hexdump (inbufptr, newdata));
00514 #endif
00515
00516 outbuflen = 0;
00517 inbuflen += newdata;
00518 #if 0
00519 inbuffer[inbuflen] = '\0';
00520
00521 report (5, "Input buffer: %s\n", inbuffer);
00522 #endif
00523 while (inbufptr < (inbuffer + inbuflen))
00524 {
00525 unsigned char c = *inbufptr++;
00526 static const char *state_table[] = {
00527 "GROUND_STATE",
00528 "NMEA_DOLLAR",
00529 "NMEA_PUB_LEAD",
00530 "NMEA_LEADER_END",
00531 "NMEA_CR",
00532 "NMEA_RECOGNIZED"
00533 };
00534 nextstate (c);
00535 report (7, "%08ld: character '%c' [%02x], new state: %s\n",
00536 char_counter,
00537 (isprint (c) ? c : '.'), c, state_table[packetState]);
00538 char_counter++;
00539
00540 if (packetState == GROUND_STATE)
00541 {
00542 character_discard ();
00543 }
00544 else if (packetState == NMEA_RECOGNIZED)
00545 {
00546 bool checksum_ok = true;
00547 char csum[3];
00548 char *trailer = (char *) inbufptr - 5;
00549
00550 if (*trailer == '%')
00551 {
00552 unsigned int n, crc = 0;
00553 for (n = 1; (char *) inbuffer + n < trailer; n++)
00554 crc ^= inbuffer[n];
00555 (void) snprintf (csum, sizeof (csum), "%02X", crc);
00556 checksum_ok = (toupper (csum[0]) == toupper (trailer[1])
00557 && toupper (csum[1]) == toupper (trailer[2]));
00558
00559 }
00560 if (checksum_ok)
00561 packet_accept (NMEA_PACKET);
00562
00563 packetState = GROUND_STATE;
00564 packet_discard ();
00565 break;
00566 }
00567 }
00568
00569 return (ssize_t) newdata;
00570 }
00571
00572 #undef getword
00573
00574
00575 ssize_t
00576 ocean::packet_get ()
00577 {
00578 ssize_t newdata;
00579 newdata =
00580 read (inputDevice, inbuffer + inbuflen, sizeof (inbuffer) - (inbuflen));
00581 if ((newdata < 0) && (errno != EAGAIN))
00582 return BAD_PACKET;
00583 else if ((newdata == 0) || ((newdata < 0) && (errno == EAGAIN)))
00584 return NO_PACKET;
00585
00586 #if (FILE_LOGGING > 0)
00587 write( outputFile, inbuffer, newdata );
00588 #endif
00589
00590 return packet_parse ((size_t) newdata);
00591 }
00592
00593
00594 void
00595 ocean::packet_reset ()
00596 {
00597 packetState = GROUND_STATE;
00598 inbuflen = 0;
00599 inbufptr = inbuffer;
00600 packetType = NO_PACKET;
00601 }
00602
00607
00608
00609
00610
00611
00612 unsigned int ocean::processSystem (int count, char *field[])
00613 {
00614 report (2, "processSystem message\n");
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 server.last_system_update = ros::Time::now();
00626
00627 for( int index = 1; index < count; )
00628 {
00629
00630 int tmp = atoi(field[index]);
00631 ++index;
00632 switch(tmp)
00633 {
00634 case 1:
00635 server.time_left.fromSec((double)strtol( field[index], 0, 16 ) * 60);
00636 report (5, "timeLeft=%d\n", server.time_left.sec);
00637 break;
00638 case 3:
00639 server.message.assign(field[index]);
00640
00641 report (5, "processSystem message=%s\n", server.message.c_str());
00642 break;
00643 case 4:
00644 server.average_charge = (int32_t)strtol( field[index], 0, 16 );
00645 report (5, "averageCharge=%x\n", server.average_charge);
00646 break;
00647 default:
00648 ;
00649 }
00650 ++index;
00651 }
00652
00653 return 0;
00654 }
00655
00656 unsigned int ocean::processController (int count, char *field[])
00657 {
00658 report (2, "processController message\n");
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673
00674
00675
00676
00677
00678 server.last_controller_update = ros::Time::now();
00679
00680 for( int index = 1; index < count; )
00681 {
00682 int tmp = atoi (field[index]);
00683
00684 int value = strtol(field[index+1], 0, 16);
00685 report (5, "switch=%d value=0x%x\n", tmp, value);
00686
00687
00688
00689
00690
00691
00692
00693
00694 {
00695 switch(tmp)
00696 {
00697 case 1:
00698 {
00699 for(int xx = 0; xx < server.MAX_BAT_COUNT; ++xx)
00700 {
00701 server.battery[xx].present = value & 1;
00702 value = value >> 1;
00703 }
00704 }
00705 break;
00706 case 2:
00707 {
00708 for(int xx = 0; xx < server.MAX_BAT_COUNT; ++xx)
00709 {
00710 server.battery[xx].charging = value & 1;
00711 value = value >> 1;
00712 }
00713 }
00714 break;
00715 case 3:
00716 {
00717 for(int xx = 0; xx < server.MAX_BAT_COUNT; ++xx)
00718 {
00719 server.battery[xx].discharging = value & 1;
00720 value = value >> 1;
00721 }
00722 }
00723 break;
00724 case 4:
00725 #if 0 //we don't care about reserved. --Curt
00726 {
00727 for(int xx = 0; xx < server.MAX_BAT_COUNT; ++xx)
00728 {
00729 server.battery[xx].reserved = value & 1;
00730 value = value >> 1;
00731 }
00732 }
00733 #endif
00734 break;
00735 case 5:
00736 {
00737 for(int xx = 0; xx < server.MAX_BAT_COUNT; ++xx)
00738 {
00739 server.battery[xx].power_present = value & 1;
00740 value = value >> 1;
00741 }
00742 }
00743 break;
00744 case 6:
00745 {
00746 for(int xx = 0; xx < server.MAX_BAT_COUNT; ++xx)
00747 {
00748 server.battery[xx].power_no_good = value & 1;
00749 value = value >> 1;
00750 }
00751 }
00752 break;
00753 case 7:
00754 {
00755 for(int xx = 0; xx < server.MAX_BAT_COUNT; ++xx)
00756 {
00757 server.battery[xx].inhibited = value & 1;
00758 value = value >> 1;
00759 }
00760 }
00761 break;
00762 }
00763 }
00764 index += 2;
00765 }
00766
00767 return 0;
00768 }
00769
00770 unsigned int ocean::processBattery (int count, char *field[])
00771 {
00772
00773 report (2, "processBattery %s\n", field[0]);
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785 unsigned int battery = (unsigned int)(field[0][2] - '0');
00786 --battery;
00787 report (5, "processBattery count=%d \n", count);
00788 report (5, "currentBattery=%d \n", battery);
00789
00790 server.battery[battery].last_battery_update = ros::Time::now();
00791 --count;
00792
00793 int32_t regNumber;
00794 int16_t value;
00795 unsigned int xx = 1;
00796 while(count > 0)
00797 {
00798 regNumber = (int32_t)strtoul( field[xx], 0, 16);
00799 ++xx;
00800 value = (int16_t)strtoul( field[xx], 0, 16);
00801 ++xx;
00802 report (5, "reg[%u]=%x \n", regNumber, value);
00803 if(regNumber >= server.MAX_BAT_REG)
00804 {
00805 report (2, "Register greater than expected: %x MAX_BAT_REG=%x\n", regNumber, server.MAX_BAT_REG);
00806 }
00807 else
00808 {
00809 server.battery[battery].battery_register[regNumber] = value;
00810 server.battery[battery].battery_update_flag[regNumber] = 1;
00811 server.battery[battery].battery_register_update[regNumber] = ros::Time::now();
00812 }
00813
00814 count -= 2;
00815 }
00816
00817 return 0;
00818 }
00819
00820
00821
00822
00823
00824
00825
00826
00827 unsigned int
00828 ocean::nmea_parse ()
00829 {
00830 static struct
00831 {
00832 const char *name;
00833 int funcNum;
00834 } nmea_phrase[] =
00835 {
00836 {
00837 "S", 1},
00838 {
00839 "C1", 2},
00840 {
00841 "B1", 3},
00842 };
00843 char buf[NMEA_MAX + 1];
00844 static char zeroStr[] = "0";
00845
00846 int count;
00847 unsigned int retval = 0;
00848 unsigned int i;
00849 char *p, *field[NMEA_MAX], *s;
00850
00851
00852 strncpy (buf, (const char *) outbuffer, NMEA_MAX);
00853
00854
00855 for (p = buf; (*p != '*') && (*p >= ' ');)
00856 ++p;
00857
00858 *p = 0;
00859
00860
00861 for (count = 0, p = (char *) buf; (p != 0) && (*p != 0);
00862 p = strchr (p, ','))
00863 {
00864 *p = 0;
00865 ++p;
00866 if ((*p) != ',')
00867 {
00868 field[count] = p;
00869 }
00870 else
00871 field[count] = zeroStr;
00872
00873 ++count;
00874 }
00875
00876
00877 for (i = 0; i < (unsigned) (sizeof (nmea_phrase) / sizeof (nmea_phrase[0]));
00878 ++i)
00879 {
00880 s = field[0];
00881
00882
00883 if (strncmp (nmea_phrase[i].name, s, 2) == 0)
00884 {
00885 switch (nmea_phrase[i].funcNum)
00886 {
00887 case 1:
00888 processSystem (count, field);
00889 retval = 1;
00890 break;
00891 case 2:
00892 processController (count, field);
00893 retval = 2;
00894 break;
00895 case 3:
00896 processBattery (count, field);
00897 retval = 3;
00898 break;
00899 default:
00900 retval = 0;
00901 break;
00902 }
00903
00904 strncpy (tag, nmea_phrase[i].name, MAXTAGLEN);
00905 sentenceLength = strlen ((const char *) outbuffer);
00906 report (5, "Got Packet: type=%s\n", tag);
00907 break;
00908 }
00909 }
00910 packetType = NO_PACKET;
00911 return retval;
00912 }
00913
00914
00915 void
00916 ocean::nmea_add_checksum (char *sentence)
00917 {
00918 unsigned char sum = '\0';
00919 char c, *p = sentence;
00920
00921 if (*p == '$')
00922 {
00923 p++;
00924 }
00925 else
00926 {
00927 report (1, "Bad NMEA sentence: '%s'\n", sentence);
00928 }
00929 while (((c = *p) != '*') && (c != '\0'))
00930 {
00931 sum ^= c;
00932 p++;
00933 }
00934 *p++ = '*';
00935 (void) snprintf (p, 5, "%02X\r\n", (unsigned) sum);
00936 }
00937
00938
00939 int
00940 ocean::nmea_send (const char *fmt, ...)
00941 {
00942 int status;
00943 char buf[BUFSIZ];
00944 va_list ap;
00945
00946 va_start (ap, fmt);
00947 (void) vsnprintf (buf, sizeof (buf) - 5, fmt, ap);
00948 va_end (ap);
00949 if (fmt[0] == '$')
00950 {
00951 strcat (buf, "*");
00952 nmea_add_checksum (buf);
00953 }
00954 else
00955 strcat (buf, "\r\n");
00956 status = (int) write (inputDevice, buf, strlen (buf));
00957 if (status == (int) strlen (buf))
00958 {
00959 report (3, "=> OCEAN: %s\n", buf);
00960 return status;
00961 }
00962 else
00963 {
00964 report (3, "=> OCEAN: %s FAILED\n", buf);
00965 return -1;
00966 }
00967 }
00968
00969 int
00970 ocean::string_send (const char *fmt, ...)
00971 {
00972 int status;
00973 char buf[BUFSIZ];
00974 va_list ap;
00975
00976 va_start (ap, fmt);
00977 (void) vsnprintf (buf, sizeof (buf) - 5, fmt, ap);
00978 va_end (ap);
00979 status = (int) write (inputDevice, buf, strlen (buf));
00980 if (status == (int) strlen (buf))
00981 {
00982 report (3, "=> Ocean: %s\n", buf);
00983 return status;
00984 }
00985 else
00986 {
00987 report (3, "=> Ocean: %s FAILED\n", buf);
00988 return -1;
00989 }
00990 }
00991