Monday 4 April 2011

eVC++ code to read GPS location

The following is code for a simple eVC++ application that reads your location from your GPS device and writes it to file on your WinCE device. It accompanies the following post for Simple GPS helper App...
http://forums.devbuzz.com/tm.asp?m=37186&p=1&tmode=1



// code should compile for any WinCE 3.x or higher based device
// some of the code was taken from Nick Gratton and Marshall Brian's book...
// Windows CE 3.0 Application Programming

// defines and includes
#define WIN32_LEAN_AND_MEAN  // Exclude rarely-used stuff from Windows headers
#include 
// function headers
void openComPort();
DWORD WINAPI GPSReadThread(LPVOID);
void ParseRMC(LPTSTR szSentence);
// class level variables
HANDLE hGPSPort = INVALID_HANDLE_VALUE;

int WINAPI WinMain( HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPTSTR    lpCmdLine,
    int       nCmdShow)
{
  // open the port
  openComPort();
  // read some data and write it to file
  GPSReadThread(NULL);
  // close the port
  if(hGPSPort != INVALID_HANDLE_VALUE)
  {
    CloseHandle(hGPSPort);
    hGPSPort = INVALID_HANDLE_VALUE;
  }
  return 0;
}

void openComPort()
{
  // hardcoded hear to COM port 1
  hGPSPort = CreateFile (_T("COM1:"), // Port Name (Unicode compatible)
          GENERIC_READ | GENERIC_WRITE, // Open for Read-Write
          0,             // COM port cannot be shared
          NULL,          // Always NULL for Windows CE
          OPEN_EXISTING, // For communication resource
          0,             // Non-overlapped operation only
          NULL);         // Always NULL for Windows CE
 
  if(hGPSPort == INVALID_HANDLE_VALUE)
  {
    MessageBox(0, _T("Error Opening Comms Port."), _T(""), 0);
    return;
  }

  // set the timeouts to specify the behavior of reads and writes.
  COMMTIMEOUTS ct;
  ct.ReadIntervalTimeout = 1000; 
  ct.ReadTotalTimeoutMultiplier = 0; 
  ct.ReadTotalTimeoutConstant = 0; 
  ct.WriteTotalTimeoutMultiplier = 10; 
  ct.WriteTotalTimeoutConstant = 1000;
  if(!SetCommTimeouts(hGPSPort, &ct))
  {
    MessageBox(0, _T("Error Setting Comm Timeouts."), _T(""), 0);
    CloseHandle(hGPSPort);
    hGPSPort = INVALID_HANDLE_VALUE;
    return;
  }

  // get the current communications parameters, and configure baud rate
  DCB dcb;
  dcb.DCBlength = sizeof(DCB);

  if(!GetCommState(hGPSPort, &dcb))
  {
    MessageBox(0, _T("Error Getting Comms State."), _T(""), 0);
    CloseHandle(hGPSPort);
    hGPSPort = INVALID_HANDLE_VALUE;
    return;
  }
  dcb.BaudRate = CBR_4800;
  dcb.fOutxCtsFlow = FALSE;
  dcb.fRtsControl     = RTS_CONTROL_DISABLE;
  dcb.fDtrControl     = DTR_CONTROL_DISABLE;
  dcb.fOutxDsrFlow    = FALSE;
  dcb.fOutX           = TRUE; // XON/XOFF control
  dcb.fInX            = TRUE;
  dcb.ByteSize        = 8;
  dcb.Parity          = NOPARITY;
  dcb.StopBits        = ONESTOPBIT;

  if(!SetCommState(hGPSPort, &dcb))
  {
    MessageBox(0, _T("Error Setting Comms State."), _T(""), 0);
    CloseHandle(hGPSPort);
    hGPSPort = INVALID_HANDLE_VALUE;
    return;
  }

  // give time for data to arrive into comm port
  Sleep(3000);

  // now need to create the thread that will be reading the comms port
  HANDLE hCommReadThread = CreateThread(NULL, 0, GPSReadThread, NULL, 0, NULL);
  if(hCommReadThread == NULL) 
  { 
    MessageBox(0, _T("Error Creating Thread."), _T(""), 0); 
    CloseHandle(hCommReadThread ); 
    hCommReadThread = INVALID_HANDLE_VALUE; 
    return;
  }
  else
  {
    CloseHandle(hCommReadThread ); 
  }
}

// Thread function reads NMEA output from GPS device
DWORD WINAPI GPSReadThread(LPVOID)
{
  DWORD dwBytesRead;
  char szSentence[1000], c;
  TCHAR szwcsSentence[1000];
  int nc = 0;
  int counter = 0;
  
  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
  while(hGPSPort != INVALID_HANDLE_VALUE)
  {
    if(!ReadFile(hGPSPort, &c, 1, &dwBytesRead, NULL))
    {
      MessageBox(0, _T("Error Reading comms port."), _T(""), 0);
      return 0;  // terminate thread on first error
    }
    if(dwBytesRead == 1)
    {
      if(c == '\n') // LF marks end of sentance
      {
        szSentence[nc - 1] = '\0';// remove trailing CR
        nc = 0;   // ready to read next sentence
        if(strlen(szSentence) < 6)
        ;
        else if(szSentence[0] != '$')
        ;
        else 
        {
          // have a sentence. convert to Unicode
          mbstowcs(szwcsSentence, szSentence, 1000);
          // find sentence ID
          if(wcsncmp(&szwcsSentence[3], _T("RMC"), 3) == 0)
          {
            ParseRMC(szwcsSentence);
            return 1;
          }
        }
      }
      else
        szSentence[nc++] = c;
    }
  }
  return 0;
}

// returns the next token from the sentence.
LPTSTR GetNextToken(LPTSTR lpSentence, LPTSTR lpToken)
{
  lpToken[0] = '\0';
  if(lpSentence == NULL) // empty sentence
    return NULL;
  if(lpSentence[0] == '\0') // end of sentence
    return NULL;
  if(lpSentence[0] == ',') // empty token
    return lpSentence + 1;
  while(*lpSentence != ',' && *lpSentence != '\0' && *lpSentence != '*')
  {
    *lpToken = *lpSentence;
    lpToken++;
    lpSentence++;
  }
  lpSentence++;  // skip over comma
  *lpToken = '\0';
  return lpSentence;
}

// Parses a RMC sentence which has the format:
// RMC,225446,A,4916.45,N,12311.12,W,000.5,054.7,191194,020.3,E*68
void ParseRMC(LPTSTR szSentence)
{
  TCHAR szToken[20];
  DWORD dwCheckSum = 0;
  FILE* stream;
  TCHAR* s = _T("|");
  LPCWSTR seps = (const unsigned short *) s;
  for(UINT i = 1; i < wcslen(szSentence) && szSentence[i] != '*'; i++)
    dwCheckSum ^= szSentence[i];
  // lpNextTok points at ID $GPRMS, ignore this
  szSentence = GetNextToken(szSentence, szToken);
  // Time of Fix, convert to Unicode
  szSentence = GetNextToken(szSentence, szToken);

  // Navigation receiver (GPS) warning
  szSentence = GetNextToken(szSentence, szToken);

  // Latitude
  szSentence = GetNextToken(szSentence, szToken);
 
  // write lat. to file
  stream = fopen( "\\location.txt", "w" );
  fputws( szToken, stream );
  fputws( seps, stream );
  fclose( stream );
  // Latitude N or S
  szSentence = GetNextToken(szSentence, szToken);
  // write N/S. to file
  stream = fopen( "\\location.txt", "a" );
  fputws( szToken, stream );
  fputws( seps, stream );
  // Longitude
  szSentence = GetNextToken(szSentence, szToken);
  // write lon. to file
  fputws( szToken, stream );
  fputws( seps, stream );
  // Longitude W or E
  szSentence = GetNextToken(szSentence, szToken);
  // write W/E. to file
  fputws( szToken, stream );
  fputws( seps, stream );
  fclose( stream );
}
Credit to pdcira2

No comments:

Post a Comment