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

📄 bluegps.c

📁 GPS接收软件
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * BlueGPS -- a tool to control the RBT 3000 GPS Datalogger * Copyright (C) 2006 Till Harbaum and Simon Budig * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */#include <stdio.h>#include <stdlib.h>#include <errno.h>#include <unistd.h>#include <time.h>#include <math.h>#include <signal.h>#include <stdarg.h>#include <ctype.h>#include <netinet/ip.h>#include <bluetooth/bluetooth.h>#include <bluetooth/rfcomm.h>#include "rbt3000.h"#define RFCOMM_CHANNEL 1#define NAUTIC_MILE  (1.85185)#define KPH2KNOTS(a) ((a)/NAUTIC_MILE)typedef enum{  STATE_AA,  STATE_55,  STATE_LEN_LO,  STATE_LEN_HI,  STATE_PAYLOAD,  STATE_SUM,  STATE_33,  STATE_CC} RbtParserState;typedef enum{  SET_LOG_ENABLE    = 1 << 0,  SET_LOG_OVERWRITE = 1 << 1,  SET_LOG_HEIGHT    = 1 << 2,  SET_CONST_TIME    = 1 << 3,  SET_CONST_DIST    = 1 << 4,  SET_MAX_SPEED     = 1 << 5,  SET_NAME          = 1 << 6,  SET_PASSWORD      = 1 << 7,  ERASE_DATALOG     = 1 << 8,} BlueGPSCommand;typedef enum{  MSG_QUIET,  MSG_NORMAL,  MSG_VERBOSE,} BlueMsgLevel;typedef struct{  bdaddr_t         device;  int              device_fd;  int              req_quit;  int              need_password;  int              expected_entries;  BlueMsgLevel     messages;  char             password[4];  char            *filename;  FILE            *outfile;  int              have_old_config;  datalog_config_t old_config;  int              commands;  char             new_name[15];  datalog_config_t new_config;  char             new_password[4];} BlueGPSContext;BlueGPSContext *context = NULL;void rbt3000_handle_reply (int device_fd, unsigned char *buffer, int len);void print_message        (BlueMsgLevel level, char *format, ...)                            __attribute__((__format__ (__printf__, 2, 3)));intfull_write (int fd, void *buf, int count){  int pos = 0, ret = 0;  while (ret >= 0 && pos < count)    {      ret = write (fd, buf + pos, count - pos);      if (ret >= 0)        pos += ret;    }  if (ret < 0)    return ret;  else    return count;}voidsigproc (int sig){  signal (SIGINT, sigproc);  if (context->req_quit)    exit (1);  context->req_quit = 1;}voidprint_message (BlueMsgLevel level, char *format, ...){  va_list ap;  if (level <= context->messages)    {      va_start (ap, format);      vfprintf (stderr, format, ap);      va_end (ap);    }}voidprint_datalog_config (BlueMsgLevel level, datalog_config_t *datalog){  print_message (level,                 "Datalog:            %s\n"                 "  - when full:      %s\n"                 "  - height info:    %s\n",                 datalog->enabled ? "on" : "off",                 datalog->overwrite ? "overwrite" : "stop",                 datalog->include_altitude ? "on" : "off");  print_message (level, "  - constant time:  ");  if (datalog->interval)    print_message (level, "%lds\n", datalog->interval);  else    print_message (level, "off\n");  print_message (level, "  - constant dist:  ");  if (datalog->constant_distance)    print_message (level, "%ldm\n", datalog->constant_distance);  else    print_message (level, "off\n");  print_message (level, "  - maximum speed:  ");  if (datalog->speeding_limit > 0.0001)    print_message (level, "%.2f km/h\n", datalog->speeding_limit);  else    print_message (level, "off\n");}unsigned charnmea_checksum (unsigned char *str){  unsigned char check = 0;  while (*str)    {      if (*str != '$')        check ^= *str;      str ++;    }  return check;}voidfprint_datalog_entry_nmea (FILE *stream, datalog_entry_t *entry){  unsigned char nmea[128];  int latdegrees, londegrees;  float latminutes, lonminutes;  char  latdir, londir;  nmea[127] = 0;  latdegrees = floor (fabs (entry->latitude));  latminutes = 60 * fmod (fabs (entry->latitude), 1.0);  latdir = entry->latitude < 0 ? 'S' : 'N';  londegrees = floor (fabs (entry->longitude));  lonminutes = 60 * fmod (fabs (entry->longitude), 1.0);  londir = entry->longitude < 0 ? 'W' : 'E';  /* GPRMC message */  snprintf ((char *) nmea, 127,            "$GPRMC,%02u%02u%06.3f,A,%02d%07.4f,%c,%03d%07.4f,%c,"            "%.3f,%.3f,%02u%02u%02u,,",            entry->hour, entry->minute, entry->second,            latdegrees, latminutes, latdir,            londegrees, lonminutes, londir,            KPH2KNOTS (entry->speed), entry->direction,            entry->day, entry->month, entry->year);  fprintf (stream, "%s*%02X\r\n", nmea, nmea_checksum (nmea));  /* GPGGA message */  snprintf ((char *) nmea, 127,            "$GPGGA,%02u%02u%06.3f,%02d%07.4f,%c,%03d%07.4f,%c,"            "1,%02d,%.1f,%.2f,M,,M,,",            entry->hour, entry->minute, entry->second,            latdegrees, latminutes, latdir,            londegrees, lonminutes, londir,            entry->satellites, entry->HDOP, entry->altitude);  fprintf (stream, "%s*%02X\r\n", nmea, nmea_checksum (nmea));  /* GPGLL message */  snprintf ((char *) nmea, 127,            "$GPGLL,%02d%07.4f,%c,%03d%07.4f,%c,"            "%02u%02u%06.3f,A",            latdegrees, latminutes, latdir,            londegrees, lonminutes, londir,            entry->hour, entry->minute, entry->second);  fprintf (stream, "%s*%02X\r\n", nmea, nmea_checksum (nmea));  /* GPVTG message */  snprintf ((char *) nmea, 127,            "$GPVTG,%.3f,T,,M,%.3f,N,%.3f,K",            entry->direction, KPH2KNOTS(entry->speed), entry->speed);  fprintf (stream, "%s*%02X\r\n", nmea, nmea_checksum (nmea));  /* GPGSA message */  snprintf ((char *) nmea, 127,            "$GPGSA,A,,,,,,,,,,,,,,%.2f,%.2f,,",            entry->PDOP, entry->HDOP);  fprintf (stream, "%s*%02X\r\n", nmea, nmea_checksum (nmea));}voidprint_progress_bar (BlueMsgLevel level, int sent, int total){#define BAR_WIDTH 50  int i;  print_message (level, "\rDownloading: [");  for (i = 0; i < BAR_WIDTH; i++)    print_message (level, "%c", i < (BAR_WIDTH * sent / total) ? '#' : '-');  print_message (level, "]  %d/%d     \r", sent, total);  fflush (stderr);#undef BAR_WIDTH}intrbt3000_connect (char *device_addr){  struct sockaddr_rc rem_addr;  baswap (&context->device, strtoba (device_addr));  rem_addr.rc_family  = AF_BLUETOOTH;  rem_addr.rc_bdaddr  = context->device;  rem_addr.rc_channel = RFCOMM_CHANNEL;  /* bluez connects to BlueClient */  if ((context->device_fd = socket (PF_BLUETOOTH,                                    SOCK_STREAM,                                    BTPROTO_RFCOMM)) < 0 )    {      perror ("Can't create socket");      return 0;    }  /* connect on rfcomm */  if (connect (context->device_fd,               (struct sockaddr *) &rem_addr,               sizeof (rem_addr)) < 0 )    {      perror ("Can't connect");      close (context->device_fd);      return 0;    }  return 1;}voidrbt3000_init (int fd){  /* sending $RCMD402*2E  */  uint8_t cmd1[] = { 0xa0, 0xa2, 0x00, 0x31, 0xa5, 0x00, 0x04, 0x04,                     0x00, 0x00, 0xe1, 0x00, 0x08, 0x01, 0x00, 0x00,                     0x00, 0xff, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00,                     0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x05, 0x05,                     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,                     0x00, 0xff, 0x05, 0x05, 0x00, 0x00, 0x00, 0x00,                     0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0xb2, 0xb0,                     0xb3 };  print_message (MSG_NORMAL, "Initializing RBT-3000...\n");  full_write (fd, "\r\n", 2);  full_write (fd, "$RCMD402*2E\r\n", 13);  full_write (fd, cmd1, sizeof (cmd1));}voidrbt3000_parse_byte (int device_fd, unsigned char byte){  static RbtParserState state = STATE_AA;  static int len = 0;  static int count = 0;  static int xsum = 0;  static unsigned char *buffer = NULL;  switch (state)  {    case STATE_AA:      if (byte == 0xAA)        state = STATE_55;      break;    case STATE_55:      if (byte == 0x55)        state = STATE_LEN_LO;      else        state = (byte != 0xAA) ? STATE_AA : STATE_55;      break;    case STATE_LEN_LO:      len = byte;      state = STATE_LEN_HI;      break;    case STATE_LEN_HI:      len += 256 * byte;      if (buffer)        free (buffer);      buffer = malloc (len);      xsum = count = 0;      state = STATE_PAYLOAD;      break;    case STATE_PAYLOAD:      if (count < len)        {          buffer[count] = byte;          xsum ^= byte;          count ++;        }      if (count == len)        {          state = STATE_SUM;        }      break;    case STATE_SUM:      if (xsum == byte)        {          state = STATE_33;        }      else        {          print_message (MSG_QUIET, "Checksum error\n");          state = (byte != 0xAA) ? STATE_AA : STATE_55;        }      break;    case STATE_33:      if (byte == 0x33)        {          state = STATE_CC;        }      else        {          print_message (MSG_QUIET, "Postamble 0x33 error\n");          state = (byte != 0xAA) ? STATE_AA : STATE_55;        }      break;    case STATE_CC:      if (byte == 0xCC)        {          rbt3000_handle_reply (device_fd, buffer, len);          state = STATE_AA;        }      else        {          print_message (MSG_QUIET, "Postamble 0xCC error\n");          state = (byte != 0xAA) ? STATE_AA : STATE_55;        }      break;  }}intrbt3000_send_cmd_seq (int   fd,                      char  command,                      char *data,                      int   len){  unsigned char buffer[5] = { 0xAA, 0x55, 0x00, 0x00, 0x00 };  int ret;  /* Preamble */  buffer[2] = (len + 1) & 0xff;  buffer[3] = (len + 1) >> 8;  buffer[4] = command;  ret = full_write (fd, buffer, 5);  if (ret < 0)    return ret;  if (len > 0)    {      ret = full_write (fd, data, len);      if (ret < 0)        return ret;    }  /* Postamble */  buffer[0] = command;  while (len)    {      buffer[0] ^= *data;      data++;      len--;    }  buffer[1] = 0x33;  buffer[2] = 0xCC;  ret = full_write (fd, buffer, 3);  if (ret < 0)    return ret;  return 0;}intrbt3000_send_cmd (int  fd,                  char cmd){  return rbt3000_send_cmd_seq (fd, cmd, NULL, 0);}voidrbt3000_abort (char *message){  print_message (MSG_QUIET, "%s Aborting.\n", message);  context->req_quit = 1;}voidrbt3000_handle_reply_action (int device_fd, unsigned char *buffer, int len){  static int entrycount;  switch (buffer[0])  {    case CMD_ECHO:      break;    case CMD_STATUS:      if (len - 1 == sizeof (status_t))        {          status_t *status = (status_t *) (buffer + 1);          print_message (MSG_NORMAL,                         "Device name:        %s\n",                         status->name);          print_message (MSG_VERBOSE,                         "Firmware version:   %s\n"                         "Battery:            %s\n"                         "Password:           %s\n",                         status->version,                         status->batt ? (status->batt == 2 ? "low" : "mid")                                      : "high",                         status->password ? "enabled" : "disabled");          print_datalog_config (MSG_VERBOSE, &status->datalog);          context->old_config  = status->datalog;          context->have_old_config = 1;          context->need_password = status->password;        }      else        {          rbt3000_abort ("Wrong status reply size.");        }      break;    case CMD_PASSWORD:      if (buffer[1])        context->need_password = 0;      break;    case CMD_LOGSTATE:      if (len - 1 == sizeof (datalog_state_t))        {          datalog_state_t *state = (datalog_state_t *) (buffer + 1);

⌨️ 快捷键说明

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