Garmin Fleet Management Controller  2.19.0
AobrdEventLogConverter.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 *
3 * MODULE NAME:
4 * AobrdEventLogConverter.cpp
5 *
6 * Copyright 2012 by Garmin Ltd. or its subsidiaries.
7 *---------------------------------------------------------------------
8 * $NoKeywords$
9 *********************************************************************/
10 
11 #include "AobrdEventLogConverter.h"
12 #include "CsvWriter.h"
13 #include "util.h"
14 #include <stdlib.h>
15 #include <fstream>
16 #include <map>
17 
18 #include "pack_begin.h"
19 
20 #if( FMI_SUPPORT_A610 )
21 
22 using namespace std;
23 
24 __packed struct evt_log_header_fixed {
29 };
30 
31 //----------------------------------------------------------------------
32 // Static function prototypes
33 //----------------------------------------------------------------------
34 static void encodeStringFields( uint32 field_flags, int start, int end, ifstream & rawFile, CsvWriter & csvWriter );
35 static void convertTimeTypeToString( time_type aTimestamp, char * full, int fullSize );
36 static void encodeTimestampFields( uint32 field_flags, int start, int end, ifstream & rawFile, CsvWriter & csvWriter );
37 static time_type encodeTimestampField( uint32 field_flags, int start, ifstream & rawFile, CsvWriter & csvWriter );
38 static void encodeDegreeFields( uint32 field_flags, int start, int end, ifstream & rawFile, CsvWriter & csvWriter, char * format );
39 static void encodeUint32Fields( uint32 field_flags, int start, int end, ifstream & rawFile, CsvWriter & csvWriter, char * format );
40 static void encodeUint16Fields( uint32 field_flags, int start, int end, ifstream & rawFile, CsvWriter & csvWriter, char * format );
41 static uint16 readCSVRecord( ifstream & fstream, vector<string> & record, char delimiter );
42 static void modifyStatusChangeRecord( bool (*locator)(void * key, vector<string> & record), void * key, void (*updater)(void * val, vector<string> & record), void * val, const char * source );
43 static void decodeStringFields( uint32 & field_flags, int start, int end, ofstream & rawFile, vector<string> & record, uint16 & fieldIdx );
44 static void decodeDegreeFields( uint32 & field_flags, int start, int end, ofstream & rawFile, vector<string> & record, uint16 & fieldIdx, char * format );
45 static void decodeUint32Fields( uint32 & field_flags, int start, int end, ofstream & rawFile, vector<string> & record, uint16 & fieldIdx, char * format );
46 static void decodeUint16Fields( uint32 & field_flags, int start, int end, ofstream & rawFile, vector<string> & record, uint16 & fieldIdx, char * format );
47 static void decodeTimestampFields( uint32 & field_flags, int start, int end, ofstream & rawFile, vector<string> & record, uint16 & fieldIdx );
48 static void checkFieldHeaders( uint32 & field_flags, int start, int end, vector<string> & record, uint16 & fieldIdx );
49 static time_type parseDateTime( std::string cellValue );
50 
51 
52 //----------------------------------------------------------------------
54 //----------------------------------------------------------------------
56  {
57 
58  }
59 
60 //----------------------------------------------------------------------
62 //----------------------------------------------------------------------
63 static void encodeStringFields( uint32 field_flags, int start, int end, ifstream & rawFile, CsvWriter & csvWriter )
64  {
65  char buf[257];
66  uint8 len;
67  for( int i=start; i<=end; i++ )
68  {
69  if( field_flags & ( 0x01 << i) )
70  {
71  rawFile.read( (char*) &len, 1 );
72  if ( 0 < len )
73  {
74  rawFile.read( buf, len );
75  buf[len] = 0;
76  csvWriter.WriteValue( buf );
77  }
78  else
79  {
80  csvWriter.WriteValue( "" );
81  }
82  }
83  else
84  {
85  csvWriter.WriteValue( "" );
86  }
87  }
88  }
89 
90 static void convertTimeTypeToString( time_type aTimestamp, char * full, int fullSize )
91  {
92  date_time_data_type date_time;
93  UTIL_convert_UTC_to_local( &aTimestamp, &aTimestamp );
94  UTIL_convert_seconds_to_date_type( &aTimestamp, &date_time );
95  UTIL_convert_seconds_to_time_type( &aTimestamp, &date_time );
96 
97  sprintf_s(full, fullSize, "%04d-%02d-%02d %02d:%02d:%02d", date_time.date.year, date_time.date.month, date_time.date.day, date_time.time.hour, date_time.time.minute, date_time.time.second ) ;//, aTimestamp % 1000 );
98  }
99 //----------------------------------------------------------------------
101 //----------------------------------------------------------------------
102 static void encodeTimestampFields( uint32 field_flags, int start, int end, ifstream & rawFile, CsvWriter & csvWriter )
103  {
104  time_type aTimestamp;
105  char full[30];
106  for( int i=start; i<=end; i++ )
107  {
108  if( field_flags & ( 0x01 << i) )
109  {
110  rawFile.read( ( char*) &aTimestamp, sizeof( aTimestamp ) );
111  if( aTimestamp == 0 )
112  {
113  csvWriter.WriteValue( "" );
114  }
115  else
116  {
117  convertTimeTypeToString( aTimestamp, full, ( int ) sizeof( full ) );
118  csvWriter.WriteValue( full );
119  }
120  }
121  else
122  {
123  csvWriter.WriteValue( "" );
124  }
125  }
126  }
127 
128 static time_type encodeTimestampField( uint32 field_flags, int start, ifstream & rawFile, CsvWriter & csvWriter )
129  {
130  time_type aTimestamp = 0;
131  char full[30];
132  if( field_flags & ( 0x01 << start) )
133  {
134  rawFile.read( ( char*) &aTimestamp, sizeof( aTimestamp ) );
135  if( aTimestamp == 0 )
136  {
137  csvWriter.WriteValue( "" );
138  }
139  else
140  {
141  convertTimeTypeToString( aTimestamp, full, sizeof( full ) );
142  csvWriter.WriteValue( full );
143  }
144  }
145  else
146  {
147  csvWriter.WriteValue( "" );
148  }
149 
150  return aTimestamp;
151  }
152 
153 //----------------------------------------------------------------------
155 //----------------------------------------------------------------------
156 static void encodeDegreeFields( uint32 field_flags, int start, int end, ifstream & rawFile, CsvWriter & csvWriter, char * format = "%08.6f" )
157  {
158  char tmp[20];
159  sint32 rawValue;
160  double degrees;
161  for( int i=start; i<=end; i++ )
162  {
163  if( field_flags & ( 0x01 << i) )
164  {
165  rawFile.read( ( char*) &rawValue, sizeof( rawValue ) );
166  degrees = UTIL_convert_semicircles_to_degrees( rawValue );
167  sprintf( tmp, format, degrees );
168  csvWriter.WriteValue( tmp );
169  }
170  else
171  {
172  csvWriter.WriteValue( "" );
173  }
174  }
175  }
176 
177 //----------------------------------------------------------------------
179 //----------------------------------------------------------------------
180 static void encodeUint32Fields( uint32 field_flags, int start, int end, ifstream & rawFile, CsvWriter & csvWriter, char * format = "0x%.8x" )
181  {
182  char tmp[20];
183  uint32 value;
184  for( int i=start; i<=end; i++ )
185  {
186  if( field_flags & ( 0x01 << i) )
187  {
188  rawFile.read( ( char*) &value, sizeof( value ) );
189  sprintf( tmp, format, value );
190  csvWriter.WriteValue( tmp );
191  }
192  else
193  {
194  csvWriter.WriteValue( "" );
195  }
196  }
197  }
198 
199 //----------------------------------------------------------------------
201 //----------------------------------------------------------------------
202 static void encodeUint16Fields( uint32 field_flags, int start, int end, ifstream & rawFile, CsvWriter & csvWriter, char * format = "0x%.4x" )
203  {
204  char tmp[20];
205  uint16 value;
206  for( int i=start; i<=end; i++ )
207  {
208  if( field_flags & ( 0x01 << i) )
209  {
210  rawFile.read( ( char*) &value, sizeof( value ) );
211  sprintf( tmp, format, value );
212  csvWriter.WriteValue( tmp );
213  }
214  else
215  {
216  csvWriter.WriteValue( "" );
217  }
218  }
219  }
220 
221 //----------------------------------------------------------------------
224 //----------------------------------------------------------------------
225 static uint16 readCSVRecord( ifstream & fstream, vector<string> & record, char delimiter = ',' )
226  {
227  int inquotes=false;
228  char c;
229  string curstring;
230  record.clear();
231 
232  while( fstream.good() && !fstream.eof() )
233  {
234  fstream.read( &c, 1 );
235 
236  if (!inquotes && curstring.length()==0 && c=='"')
237  {
238  //beginquotechar
239  inquotes=true;
240  }
241  else if (inquotes && c=='"')
242  {
243  //quotechar
244  if ( fstream.peek()=='"' )
245  {
246  //encountered 2 double quotes in a row (resolves to 1 double quote)
247  curstring.push_back(c);
248  fstream.read( &c, 1 ); //skip the second double-quote
249  }
250  else
251  {
252  //endquotechar
253  inquotes=false;
254  }
255  }
256  else if (!inquotes && c==delimiter)
257  {
258  //end of field
259  record.push_back( curstring );
260  curstring="";
261  }
262  else if (!inquotes && (c=='\r' || c=='\n') )
263  {
264  if( c == '\r' && fstream.peek() == '\n' ) {
265  fstream.read( &c, 1 );
266  }
267  record.push_back( curstring );
268  return (uint16) record.size();
269  }
270  else
271  {
272  curstring.push_back(c);
273  }
274  fstream.peek();
275  }
276  record.push_back( curstring );
277  return (uint16) record.size();
278  }
279 
280 
281 //----------------------------------------------------------------------
283 //----------------------------------------------------------------------
284 bool locateEventBeingVerified(void * key, vector<string> & record)
285  {
286  return ( record[1].compare( "0x01" ) == 0 && record[2].compare( ( char* ) key ) == 0 );
287  }
288 
289 //----------------------------------------------------------------------
291 //----------------------------------------------------------------------
292 void updateEventBeingVerified(void * val, vector<string> & record)
293  {
294  record[22] = ( char* ) val;
295  }
296 
297 //----------------------------------------------------------------------
299 //----------------------------------------------------------------------
300 static void modifyStatusChangeRecord(bool (*locator)(void * key, vector<string> & record), void * key, void (*updater)(void * val, vector<string> & record), void * val, const char * source)
301  {
302  ifstream origFile( source, ios_base::in | ios_base::binary );
303  if( !origFile.good() )
304  {
305  return;
306  }
307 
308  char tmpFileName[_MAX_PATH];
309 
310  // Leave 5 characters remaining: 4 for .tmp (below), +1 for NUL terminator
311  strncpy( tmpFileName, source, _MAX_PATH - 5 );
312  tmpFileName[_MAX_PATH - 5] = '\0';
313  strcat( tmpFileName, ".tmp" );
314 
315  CFile modFile( CString( tmpFileName ), CFile::modeCreate | CFile::modeWrite );
316  CsvWriter csvWriter( &modFile );
317 
319  memset( &hdr, 0, sizeof( hdr ) );
320 
321  //read each record
322  vector<string> record;
323  uint16 cellCount = 0;
324  char cell[256];
325  while( 1 < ( cellCount = readCSVRecord( origFile, record ) ) )
326  {
327  if( '#' != record[0][0] )
328  {
329  if ( locator( key, record ) )
330  {
331  updater( val, record );
332  }
333  }
334 
335  //re-write record
336  for( uint32 i=0; i<record.size()-1; i++ )
337  {
338  strncpy( cell, record[i].c_str(), cnt_of_array( cell ) - 1 );
339  cell[cnt_of_array( cell ) - 1] = '\0';
340  csvWriter.WriteValue( cell );
341  }
342 
343  csvWriter.NewLine();
344 
345  modFile.Flush();
346  }
347  modFile.Close();
348  origFile.close();
349 
350  if( DeleteFile( CString( source ) ) )
351  {
352  MoveFile( CString( tmpFileName ), CString( source ) );
353  }
354 
355  }
356 
357 //----------------------------------------------------------------------
359 //----------------------------------------------------------------------
360 void AobrdEventLogConverter::convertToCsv( const char * source, const char * destFormat )
361  {
362  ifstream rawFile( source, ios_base::binary | ios_base::in );
363  if( !rawFile.good() )
364  {
365  return;
366  }
367 
369  memset( &hdr, 0, sizeof( hdr ) );
370 
371  time_type recordTimestamp = 0;
372 
373  map<time_type,time_type> verifiedStatusUpdates;
374 
375  char len[1];
376  char tmp[256];
377  tmp[0] = 0;
378  //seek past the fixed-width header and timestamp
379  rawFile.seekg( sizeof( hdr ) + sizeof( uint32 ), ios_base::beg );
380  //read the first 3 variable-width strings (the third is the driver ID)
381  for( int i=0; i<3; i++ )
382  {
383  rawFile.read( len, 1 );
384  rawFile.read( tmp, (int) len[0] );
385  tmp[(int)len[0]] = 0;
386  }
387  rawFile.seekg( 0, ios_base::beg );
388 
389  CFile csvFile;
390  char dest[MAX_PATH];
391  sprintf(dest, destFormat, tmp);
392  if( !csvFile.Open( CString( dest ), CFile::modeCreate | CFile::modeWrite | CFile::modeNoTruncate ) )
393  {
394  rawFile.close();
395  return;
396  }
397 
398  uint32 newPos = (uint32) csvFile.SeekToEnd();
399 
400  CsvWriter csvWriter( &csvFile );
401 
402  if( 0 == newPos )
403  {
404  csvWriter.WriteValue( "#version" );
405  csvWriter.WriteValue( "reason" );
406  csvWriter.WriteValue( "timestamp" );
407  csvWriter.WriteValue( "Driver first name" );
408  csvWriter.WriteValue( "Driver last name" );
409  csvWriter.WriteValue( "Driver ID" );
410  csvWriter.WriteValue( "Co-Driver first name" );
411  csvWriter.WriteValue( "Co-Driver last name" );
412  csvWriter.WriteValue( "Co-Driver ID" );
413  csvWriter.WriteValue( "Tractor number" );
414  csvWriter.WriteValue( "Trailer number" );
415  csvWriter.WriteValue( "Tractor VIN" );
416  csvWriter.WriteValue( "Current odom. reading" );
417  csvWriter.WriteValue( "Carrier ID" );
418  csvWriter.WriteValue( "Carrier name" );
419  csvWriter.WriteValue( "Nearest city name" );
420  csvWriter.WriteValue( "Nearest state name" );
421  csvWriter.NewLine();
422  }
423 
424  while ( rawFile.good() && !rawFile.eof() )
425  {
426  //read fixed header
427  rawFile.read( ( char* ) &hdr, sizeof( hdr ) );
428 
429  csvWriter.WriteValue( "#" );
430 
431  switch( hdr.reason )
432  {
433  case DRIVER_ANNOTATION:
434  {
435  csvWriter.WriteValue( "Driver annotation" );
436  for( int i = 0; i<15; i++)
437  {
438  csvWriter.WriteValue( "" );
439  }
440  csvWriter.WriteValue( "Start Time" );
441  csvWriter.WriteValue( "End Time" );
442  csvWriter.WriteValue( "Annotation Text" );
443  break;
444  }
445  case DRIVER_STATUS_CHANGE:
446  {
447  csvWriter.WriteValue( "Driver status change" );
448  for( int i = 0; i<15; i++)
449  {
450  csvWriter.WriteValue( "" );
451  }
452  csvWriter.WriteValue( "Old driver status" );
453  csvWriter.WriteValue( "New driver status" );
454  csvWriter.WriteValue( "Event number" );
455  csvWriter.WriteValue( "Latitude of change" );
456  csvWriter.WriteValue( "Longitude of change" );
457  csvWriter.WriteValue( "Verified time" );
458  csvWriter.WriteValue( "Additional status flag" );
459  break;
460  }
461  case DRIVER_VERIFIED_LOG:
462  {
463  csvWriter.WriteValue( "Driver verified log" );
464  for( int i = 0; i<15; i++)
465  {
466  csvWriter.WriteValue( "" );
467  }
468  csvWriter.WriteValue( "Original Timestamp" );
469  break;
470  }
471  case DRIVER_COULD_NOT_VERIFY_LOG:
472  {
473  csvWriter.WriteValue( "Driver could not verify log" );
474  for( int i = 0; i<15; i++)
475  {
476  csvWriter.WriteValue( "" );
477  }
478  csvWriter.WriteValue( "Original Timestamp" );
479  break;
480  }
481  case DRIVER_ADDED_NEW_SHIPMENT_ENTRY:
482  {
483  csvWriter.WriteValue( "Driver added new shipment entry" );
484  for( int i = 0; i<15; i++)
485  {
486  csvWriter.WriteValue( "" );
487  }
488  csvWriter.WriteValue( "Original Timestamp" );
489  csvWriter.WriteValue( "Start Time" );
490  csvWriter.WriteValue( "End Time" );
491  csvWriter.WriteValue( "Shipper name" );
492  csvWriter.WriteValue( "Shipment document number" );
493  csvWriter.WriteValue( "Shipment commodity" );
494  break;
495  }
496  case DRIVER_MODIFIED_EXISTING_SHIPMENT_ENTRY:
497  {
498  csvWriter.WriteValue( "Driver modified existing shipment entry" );
499  for( int i = 0; i<15; i++)
500  {
501  csvWriter.WriteValue( "" );
502  }
503  csvWriter.WriteValue( "Original Timestamp" );
504  csvWriter.WriteValue( "Start Time" );
505  csvWriter.WriteValue( "End Time" );
506  csvWriter.WriteValue( "Shipper name" );
507  csvWriter.WriteValue( "Shipment document number" );
508  csvWriter.WriteValue( "Shipment commodity" );
509  break;
510  }
511  case DRIVER_DELETED_SHIPMENT_ENTRY:
512  {
513  csvWriter.WriteValue( "Driver deleted shipment entry" );
514  for( int i = 0; i<15; i++)
515  {
516  csvWriter.WriteValue( "" );
517  }
518  csvWriter.WriteValue( "Original Timestamp" );
519  csvWriter.WriteValue( "Start Time" );
520  csvWriter.WriteValue( "End Time" );
521  csvWriter.WriteValue( "Shipper name" );
522  csvWriter.WriteValue( "Shipment document number" );
523  csvWriter.WriteValue( "Shipment commodity" );
524  break;
525  }
526  case PND_FAILURE_DETECTION:
527  {
528  csvWriter.WriteValue( "PND failure detection" );
529  for( int i = 0; i<15; i++)
530  {
531  csvWriter.WriteValue( "" );
532  }
533  csvWriter.WriteValue( "Event error code" );
534  csvWriter.WriteValue( "Event error timestamp" );
535  break;
536  }
537  }
538 
539  csvWriter.NewLine();
540 
541  //convert fixed header fields to hex strings
542  sprintf( tmp, "0x%.4x", hdr.version );
543  csvWriter.WriteValue( tmp );
544  //sprintf( tmp, "0x%.8x", hdr.field_flags );
545  //csvWriter.WriteValue( tmp );
546  //sprintf( tmp, "0x%.8x", hdr.reserved );
547  //csvWriter.WriteValue( tmp );
548  sprintf( tmp, "0x%.2x", hdr.reason );
549  csvWriter.WriteValue( tmp );
550 
551  //fields 0-15 are always present
552  recordTimestamp = encodeTimestampField( hdr.field_flags, 0, rawFile, csvWriter );
553  encodeStringFields( hdr.field_flags, 1, 9, rawFile, csvWriter );
554  encodeUint32Fields( hdr.field_flags, 10, 10, rawFile, csvWriter, "%d" );
555  encodeStringFields( hdr.field_flags, 11, 14, rawFile, csvWriter );
556 
557  for (int ii=0; ii < 32; ii++) {
558  if (hdr.field_flags & (0x01 << ii)) {
559  TRACE1("field flag %d present\n", ii);
560  }
561  }
562 
563  switch( hdr.reason )
564  {
565  case DRIVER_ANNOTATION:
566  {
567  encodeTimestampFields( hdr.field_flags, 27, 28, rawFile, csvWriter );
568  encodeStringFields( hdr.field_flags, 16, 16, rawFile, csvWriter );
569  break;
570  }
571  case DRIVER_STATUS_CHANGE:
572  {
573  encodeStringFields( hdr.field_flags, 17, 18, rawFile, csvWriter );
574  encodeUint32Fields( hdr.field_flags, 19, 19, rawFile, csvWriter );
575  encodeDegreeFields( hdr.field_flags, 20, 21, rawFile, csvWriter );//, "%h" );
576  encodeTimestampFields( hdr.field_flags, 22, 22, rawFile, csvWriter );
577  encodeUint16Fields( hdr.field_flags, 29, 29, rawFile, csvWriter ); //it is actually for 29 and 30, 1 byte each
578  break;
579  }
580  case DRIVER_VERIFIED_LOG:
581  {
582  time_type originalTimestamp = encodeTimestampField( hdr.field_flags, 23, rawFile, csvWriter );
583  verifiedStatusUpdates[originalTimestamp] = recordTimestamp;
584  break;
585  }
586  case DRIVER_COULD_NOT_VERIFY_LOG:
587  {
588  encodeTimestampFields( hdr.field_flags, 23, 23, rawFile, csvWriter );
589  break;
590  }
591  case DRIVER_ADDED_NEW_SHIPMENT_ENTRY:
592  {
593  encodeTimestampFields( hdr.field_flags, 23, 23, rawFile, csvWriter );
594  encodeTimestampFields( hdr.field_flags, 27, 28, rawFile, csvWriter );
595  encodeStringFields( hdr.field_flags, 24, 26, rawFile, csvWriter );
596  break;
597  }
598  case DRIVER_MODIFIED_EXISTING_SHIPMENT_ENTRY:
599  {
600  encodeTimestampFields( hdr.field_flags, 23, 23, rawFile, csvWriter );
601  encodeTimestampFields( hdr.field_flags, 27, 28, rawFile, csvWriter );
602  encodeStringFields( hdr.field_flags, 24, 26, rawFile, csvWriter );
603  break;
604  }
605  case DRIVER_DELETED_SHIPMENT_ENTRY:
606  {
607  encodeTimestampFields( hdr.field_flags, 23, 23, rawFile, csvWriter );
608  encodeTimestampFields( hdr.field_flags, 27, 28, rawFile, csvWriter );
609  encodeStringFields( hdr.field_flags, 24, 26, rawFile, csvWriter );
610  break;
611  }
612  case PND_FAILURE_DETECTION:
613  {
614  hdr.field_flags |= 0x01 << 27;
615  hdr.field_flags |= 0x01 << 28;
616  encodeUint16Fields( hdr.field_flags, 27, 27, rawFile, csvWriter );
617  encodeTimestampFields( hdr.field_flags, 28, 28, rawFile, csvWriter );
618  break;
619  }
620  }
621  csvWriter.NewLine();
622  rawFile.peek();
623  }
624 
625  rawFile.close();
626 
627  csvWriter.Finish();
628  csvFile.Close();
629 
630  char originalTimestampString[30], verifiedTimestampString[30];
631  for( map<time_type,time_type>::iterator it = verifiedStatusUpdates.begin(); it != verifiedStatusUpdates.end(); ++it )
632  {
633  convertTimeTypeToString( ( *it ).first, originalTimestampString, ( int ) sizeof( originalTimestampString ) );
634  convertTimeTypeToString( ( *it ).second, verifiedTimestampString, ( int ) sizeof( verifiedTimestampString ) );
635  modifyStatusChangeRecord(&locateEventBeingVerified, ( void * ) originalTimestampString, &updateEventBeingVerified, ( void * ) verifiedTimestampString, dest );
636  }
637  }
638 
639 //----------------------------------------------------------------------
641 //----------------------------------------------------------------------
642 static void decodeStringFields( uint32 & field_flags, int start, int end, ofstream & rawFile, vector<string> & record, uint16 & fieldIdx )
643  {
644  char len[1];
645 
646  ASSERT(record[fieldIdx].length() <= UCHAR_MAX);
647 
648  for( int i=start; i<=end; i++ )
649  {
650  if( field_flags & ( 0x01 << i) )
651  {
652  if( fieldIdx < record.size() )
653  {
654  len[0] = (char) record[fieldIdx].length();
655  rawFile.write( len, 1 );
656  rawFile.write( record[fieldIdx].c_str(), (std::streamsize) record[fieldIdx].length() );
657  }
658  else
659  {
660  len[0] = 0;
661  rawFile.write( len, 1 );
662  }
663  }
664  fieldIdx++;
665  }
666  }
667 
668 //----------------------------------------------------------------------
670 //----------------------------------------------------------------------
671 static void decodeDegreeFields( uint32 & /*field flags*/, int start, int end, ofstream & rawFile, vector<string> & record, uint16 & fieldIdx, char * format = "%f" )
672  {
673  float degrees = 0;
674  sint32 rawValue = 0;
675  for( int i=start; i<=end; i++ )
676  {
677  if( ( fieldIdx < record.size() ) && ( 0 < record[fieldIdx].length() ) )
678  {
679  sscanf_s( record[fieldIdx].c_str(), format, &degrees );
680  rawValue = UTIL_convert_degrees_to_semicircles( degrees );
681  rawFile.write( ( char* ) &rawValue, sizeof( rawValue ) );
682  //field_flags |= ( 0x01 << i );
683  }
684  fieldIdx++;
685  }
686  }
687 
688 //----------------------------------------------------------------------
690 //----------------------------------------------------------------------
691 static void decodeUint32Fields( uint32 & /*field flags*/, int start, int end, ofstream & rawFile, vector<string> & record, uint16 & fieldIdx, char * format = "%x" )
692  {
693  uint32 value = 0;
694  for( int i=start; i<=end; i++ )
695  {
696  if( ( fieldIdx < record.size() ) && ( 0 < record[fieldIdx].length() ) )
697  {
698  if( 0 == strcmp( "%x", format ) )
699  {
700  sscanf_s( record[fieldIdx].substr(2).c_str(), format, &value );
701  }
702  else
703  {
704  sscanf_s( record[fieldIdx].c_str(), format, &value );
705  }
706  rawFile.write( ( char* ) &value, sizeof( value ) );
707  //field_flags |= ( 0x01 << i );
708  }
709  fieldIdx++;
710  }
711  }
712 
713 //----------------------------------------------------------------------
715 //----------------------------------------------------------------------
716 static void decodeUint16Fields( uint32 & /*field flags*/, int start, int end, ofstream & rawFile, vector<string> & record, uint16 & fieldIdx, char * format = "%x" )
717  {
718  uint32 value = 0;
719  uint16 actualValue = 0;
720  for( int i=start; i<=end; i++ )
721  {
722  if( ( fieldIdx < record.size() ) && ( 0 < record[fieldIdx].length() ) )
723  {
724  sscanf_s( record[fieldIdx].substr(2).c_str(), format, &value );
725  actualValue = (uint16) value;
726  rawFile.write( ( char* ) &actualValue, sizeof( actualValue ) );
727  //field_flags |= ( 0x01 << i );
728  }
729  fieldIdx++;
730  }
731  }
732 
733 //----------------------------------------------------------------------
735 //----------------------------------------------------------------------
736 static void decodeTimestampFields( uint32 & /*field flags*/, int start, int end, ofstream & rawFile, vector<string> & record, uint16 & fieldIdx )
737  {
738  time_type timestamp;
739  for( int i=start; i<=end; i++ )
740  {
741  if( fieldIdx < record.size() )
742  {
743  timestamp = 0;
744  if( 0 < record[fieldIdx].length() )
745  {
746  timestamp = parseDateTime( record[fieldIdx] );
747  }
748  rawFile.write( ( char* ) &timestamp, sizeof( timestamp ) );
749  }
750  fieldIdx++;
751  }
752  }
753 
754 static void checkFieldHeaders( uint32 & field_flags, int start, int end, vector<string> & record, uint16 & fieldIdx )
755  {
756  for( int i=start; i<=end && (uint32)i<record.size(); i++ )
757  {
758  if( 0 < record[i].length() )
759  {
760  field_flags |= ( 0x01 << i );
761  }
762  }
763  fieldIdx = (uint16) end;
764  }
765 
766 //----------------------------------------------------------------------
768 //----------------------------------------------------------------------
769 uint32 AobrdEventLogConverter::convertToRaw( const char * source, const char * dest )
770  {
771  ifstream csvFile( source, ios_base::in | ios_base::binary );
772  if( !csvFile.good() )
773  {
774  return 0;
775  }
776 
777  ofstream rawFile( dest, ios_base::out | ios_base::binary );
778 
780  memset( &hdr, 0, sizeof( hdr ) );
781 
782  uint32 convertedRecords = 0;
783 
784  COleDateTime timestamp;
785  COleDateTime cutoff = COleDateTime::GetCurrentTime();
786  cutoff -= COleDateTimeSpan(14,0,0,0); //filter out data over 14 days old
787  vector<string> record;
788  uint16 cellCount = 0;
789  while( 1 < ( cellCount = readCSVRecord( csvFile, record ) ) )
790  {
791  if( '#' == record[0][0] )
792  {
793  continue;
794  }
795 
796  uint16 fieldIdx = 0;
797  sscanf_s( record[fieldIdx++].substr(2).c_str(), "%x", &hdr.version );
798  //sscanf_s( record[fieldIdx++].substr(2).c_str(), "%x", &hdr.field_flags );
799  //sscanf_s( record[fieldIdx++].substr(2).c_str(), "%x", &hdr.reserved );
800  uint32 reason = 0;
801  sscanf_s( record[fieldIdx++].substr(2).c_str(), "%x", &reason );
802  hdr.reason = (uint8) reason;
803 
804  switch( reason )
805  {
806  //filter out everything but Driver Status Changes
807  case DRIVER_STATUS_CHANGE:
808  break;
809  default:
810  continue;
811  }
812 
813  if( !timestamp.ParseDateTime( CString( record[fieldIdx].c_str() ) ) )
814  {
815  continue;
816  }
817 
818  if( timestamp < cutoff )
819  {
820  continue;
821  }
822 
823  convertedRecords++;
824 
825  //reconstruct field flags
826  uint16 hdrFieldIdx = fieldIdx;
827  //checkFieldHeaders( hdr.field_flags, 0, 14, record, hdrFieldIdx );
828  hdr.field_flags = 0x7FFF;
829 
830  switch( hdr.reason )
831  {
832  case DRIVER_ANNOTATION:
833  {
834  //can't use checkFieldFlags because the fields do not line up with the positions of the field flag bits
835  hdr.field_flags |= 0x01 << 27; //start time
836  hdr.field_flags |= 0x01 << 28; //end time
837  hdr.field_flags |= 0x01 << 16; //text
838  break;
839  }
840  case DRIVER_STATUS_CHANGE:
841  {
842  checkFieldHeaders( hdr.field_flags, 17, 22, record, hdrFieldIdx );
843  hdr.field_flags |= 0x01 << 22; //verified time is always included
844  hdr.field_flags |= 0x01 << 29; //new status byte A
845  hdr.field_flags |= 0x01 << 30; //new status byte B
846  break;
847  }
848  case DRIVER_VERIFIED_LOG:
849  {
850  checkFieldHeaders( hdr.field_flags, 23, 23, record, hdrFieldIdx );
851  break;
852  }
853  case DRIVER_COULD_NOT_VERIFY_LOG:
854  {
855  checkFieldHeaders( hdr.field_flags, 23, 23, record, hdrFieldIdx );
856  break;
857  }
858  case DRIVER_ADDED_NEW_SHIPMENT_ENTRY:
859  {
860  checkFieldHeaders( hdr.field_flags, 23, 28, record, hdrFieldIdx );
861  break;
862  }
863  case DRIVER_MODIFIED_EXISTING_SHIPMENT_ENTRY:
864  {
865  checkFieldHeaders( hdr.field_flags, 23, 28, record, hdrFieldIdx );
866  break;
867  }
868  case DRIVER_DELETED_SHIPMENT_ENTRY:
869  {
870  checkFieldHeaders( hdr.field_flags, 23, 28, record, hdrFieldIdx );
871  break;
872  }
873  case PND_FAILURE_DETECTION:
874  {
875  checkFieldHeaders( hdr.field_flags, 27, 28, record, hdrFieldIdx );
876  break;
877  }
878  }
879 
880  rawFile.write( ( char* ) &hdr, sizeof( hdr ) );
881 
882  decodeTimestampFields( hdr.field_flags, 0, 0, rawFile, record, fieldIdx );
883  decodeStringFields( hdr.field_flags, 1, 9, rawFile, record, fieldIdx );
884  decodeUint32Fields( hdr.field_flags, 10, 10, rawFile, record, fieldIdx, "%d" );
885  decodeStringFields( hdr.field_flags, 11, 14, rawFile, record, fieldIdx );
886 
887  switch( hdr.reason )
888  {
889  case DRIVER_ANNOTATION:
890  {
891  //corresponds to field flag positions 29,30
892  decodeTimestampFields( hdr.field_flags, 15, 16, rawFile, record, fieldIdx );
893  //corresponds to field flag position 16
894  decodeStringFields( hdr.field_flags, 17, 17, rawFile, record, fieldIdx );
895  break;
896  }
897  case DRIVER_STATUS_CHANGE:
898  {
899  decodeStringFields( hdr.field_flags, 17, 18, rawFile, record, fieldIdx );
900  decodeUint32Fields( hdr.field_flags, 19, 19, rawFile, record, fieldIdx );
901  decodeDegreeFields( hdr.field_flags, 20, 21, rawFile, record, fieldIdx );
902  decodeTimestampFields( hdr.field_flags, 22, 22, rawFile, record, fieldIdx );
903  decodeUint16Fields( hdr.field_flags, 29, 29, rawFile, record, fieldIdx );
904  break;
905  }
906  case DRIVER_VERIFIED_LOG:
907  {
908  decodeTimestampFields( hdr.field_flags, 23, 23, rawFile, record, fieldIdx );
909  break;
910  }
911  case DRIVER_COULD_NOT_VERIFY_LOG:
912  {
913  decodeTimestampFields( hdr.field_flags, 23, 23, rawFile, record, fieldIdx );
914  break;
915  }
916  case DRIVER_ADDED_NEW_SHIPMENT_ENTRY:
917  {
918  decodeTimestampFields( hdr.field_flags, 23, 23, rawFile, record, fieldIdx );
919  decodeTimestampFields( hdr.field_flags, 27, 28, rawFile, record, fieldIdx );
920  decodeStringFields( hdr.field_flags, 24, 26, rawFile, record, fieldIdx );
921  break;
922  }
923  case DRIVER_MODIFIED_EXISTING_SHIPMENT_ENTRY:
924  {
925  decodeTimestampFields( hdr.field_flags, 23, 23, rawFile, record, fieldIdx );
926  decodeTimestampFields( hdr.field_flags, 27, 28, rawFile, record, fieldIdx );
927  decodeStringFields( hdr.field_flags, 24, 26, rawFile, record, fieldIdx );
928  break;
929  }
930  case DRIVER_DELETED_SHIPMENT_ENTRY:
931  {
932  decodeTimestampFields( hdr.field_flags, 23, 23, rawFile, record, fieldIdx );
933  decodeTimestampFields( hdr.field_flags, 27, 28, rawFile, record, fieldIdx );
934  decodeStringFields( hdr.field_flags, 24, 26, rawFile, record, fieldIdx );
935  break;
936  }
937  case PND_FAILURE_DETECTION:
938  {
939  decodeUint16Fields( hdr.field_flags, 27, 27, rawFile, record, fieldIdx );
940  decodeTimestampFields( hdr.field_flags, 28, 28, rawFile, record, fieldIdx );
941  break;
942  }
943  }
944 
945  rawFile.flush();
946  }
947  rawFile.close();
948  csvFile.close();
949 
950  return convertedRecords;
951  }
952 
953 //----------------------------------------------------------------------
955 //----------------------------------------------------------------------
957  {
958  ifstream csvFile( source, ios_base::in | ios_base::binary );
959  if( !csvFile.good() )
960  {
961  return 0;
962  }
963 
964  uint16 count = 0;
965 
967  memset( &hdr, 0, sizeof( hdr ) );
968 
969  //read each record
970  vector<string> record;
971  uint16 cellCount = 0;
972  uint32 reason = 0;
973  while( 1 < ( cellCount = readCSVRecord( csvFile, record ) ) )
974  {
975  if( '#' != record[0][0] )
976  {
977  sscanf_s( record[1].substr(2).c_str(), "%x", &reason );
978  if ( reason == (uint32) type ) {
979  count++;
980  }
981  }
982  }
983  csvFile.close();
984 
985  return count;
986  }
987 
988 //----------------------------------------------------------------------
990 //----------------------------------------------------------------------
991 bool AobrdEventLogConverter::findRecordAt( const char* source, evt_log_reason type, uint16 index, bool ( *visitor ) ( AobrdEventLogConverter * converter, vector<string> & record, void * data ), void * data )
992  {
993  ifstream csvFile( source, ios_base::in | ios_base::binary );
994  if( !csvFile.good() )
995  {
996  return 0;
997  }
998 
999  uint16 count = 0;
1000 
1002  memset( &hdr, 0, sizeof( hdr ) );
1003 
1004  //read each record
1005  vector<string> record;
1006  uint16 cellCount = 0;
1007  uint32 reason = 0;
1008  while( 1 < ( cellCount = readCSVRecord( csvFile, record ) ) )
1009  {
1010  if( '#' != record[0][0] )
1011  {
1012  sscanf_s( record[1].substr(2).c_str(), "%x", &reason );
1013  if ( reason == (uint32) type ) {
1014  if( index == count++ )
1015  {
1016  visitor( this, record, data );
1017  break;
1018  }
1019  }
1020  }
1021  }
1022  csvFile.close();
1023  return( index == count-1 );
1024  }
1025 
1026 //----------------------------------------------------------------------
1028 //----------------------------------------------------------------------
1029 static time_type parseDateTime( std::string cellValue )
1030  {
1031  time_type timestamp;
1032  time_type time, date;
1033  COleDateTime dt;
1034  date_time_data_type date_time;
1035  dt.ParseDateTime( CString( cellValue.c_str() ) );
1036  date_time.date.year = (uint16) dt.GetYear();
1037  date_time.date.month = (uint8) dt.GetMonth();
1038  date_time.date.day = (uint8) dt.GetDay();
1039  date_time.time.hour = (sint16) dt.GetHour();
1040  date_time.time.minute = (uint8) dt.GetMinute();
1041  date_time.time.second = (uint8) dt.GetSecond();
1042  UTIL_convert_time_type_to_seconds( &date_time, &time );
1043  UTIL_convert_date_time_to_seconds( &date_time, &date );
1044  timestamp = date + time;// + dt.GetMilliseconds();
1045  UTIL_convert_local_to_UTC( &timestamp, &timestamp );
1046  return timestamp;
1047  }
1048 
1049 //----------------------------------------------------------------------
1051 //----------------------------------------------------------------------
1052 bool AobrdEventLogConverter::convertAnnotation( std::vector<std::string> & record, fmi_driver_annotation_data_type * annotation )
1053  {
1054  annotation->server_timestamp = parseDateTime( record[2] );
1055  annotation->server_start_time = parseDateTime( record[17] );
1056  annotation->server_end_time = parseDateTime( record[18] );
1057  strncpy( annotation->server_annotation, record[19].c_str(), cnt_of_array( annotation->server_annotation ) - 1 );
1058  annotation->server_annotation[cnt_of_array( annotation->server_annotation ) - 1] = '\0';
1059  return true;
1060  }
1061 #endif
sint32 UTIL_convert_degrees_to_semicircles(double aDegrees)
Converts a latitude/longitude from degrees to semicircles.
Definition: util.cpp:204
struct date_time_data_type::_date date
uint8 second
second (0-59)
Definition: garmin_types.h:162
static void encodeUint16Fields(uint32 field_flags, int start, int end, ifstream &rawFile, CsvWriter &csvWriter, char *format)
Convert 2 byte unsigned int into 6 byte hex string.
uint8 minute
minute (0-59)
Definition: garmin_types.h:161
static void encodeDegreeFields(uint32 field_flags, int start, int end, ifstream &rawFile, CsvWriter &csvWriter, char *format)
Convert 4 byte signed int into degrees.
static void modifyStatusChangeRecord(bool(*locator)(void *key, vector< string > &record), void *key, void(*updater)(void *val, vector< string > &record), void *val, const char *source)
Function for finding and updating a record.
static time_type parseDateTime(std::string cellValue)
Convert date-time string to UTC timestamp.
static void encodeStringFields(uint32 field_flags, int start, int end, ifstream &rawFile, CsvWriter &csvWriter)
Convert 1 byte length and character stream into CSV cell.
void WriteValue(char *value)
Definition: CsvWriter.cpp:25
STL namespace.
bool convertAnnotation(std::vector< std::string > &record, fmi_driver_annotation_data_type *annotation)
Convert an Annotation record to structure sent to FMI device.
#define cnt_of_array(_a)
The number of elements in _a.
Definition: util_macros.h:90
uint16 countRecords(const char *source, evt_log_reason type)
Count records by type.
Utility for converting between raw AOBRD data to human- readable CSV file. Used to attempt to auto-co...
static uint16 readCSVRecord(ifstream &fstream, vector< string > &record, char delimiter)
Convert CSV record into vector of strings.
struct date_time_data_type::_time time
void UTIL_convert_time_type_to_seconds(const date_time_data_type *aDateTime, time_type *aSeconds)
Converts a time_type to seconds since midnight.
Definition: util.cpp:295
static void encodeTimestampFields(uint32 field_flags, int start, int end, ifstream &rawFile, CsvWriter &csvWriter)
Convert time_type into human-readable formatted timestamp.
void UTIL_convert_seconds_to_time_type(const time_type *aSeconds, date_time_data_type *aDateTime)
Converts from a Garmin time to a structure containing separate members for hour, minute, and second (time_type).
Definition: util.cpp:274
signed short int sint16
16-bit signed integer
Definition: garmin_types.h:57
Date & time data type with separate fields for month, day, year, hour, minute, and second...
Definition: garmin_types.h:150
static void decodeTimestampFields(uint32 &field_flags, int start, int end, ofstream &rawFile, vector< string > &record, uint16 &fieldIdx)
Convert human-readable formatted timestamp into seconds.
double UTIL_convert_semicircles_to_degrees(sint32 aSemicircles)
Converts a latitude/longitude from semicircles to degrees.
Definition: util.cpp:260
static void checkFieldHeaders(uint32 &field_flags, int start, int end, vector< string > &record, uint16 &fieldIdx)
void UTIL_convert_seconds_to_date_type(const time_type *aSeconds, date_time_data_type *aDateTime)
Converts a Garmin date to a structure containing year, month, and day.
Definition: util.cpp:39
signed long int sint32
32-bit signed integer
Definition: garmin_types.h:59
boolean UTIL_convert_date_time_to_seconds(const date_time_data_type *aDateTime, time_type *aSeconds)
Converts a date from from a structure to a Garmin date.
Definition: util.cpp:114
Data type for the Annotation Download Response Packet ID (0X110D) from server to client.
Definition: fmi.h:1850
void convertToCsv(const char *source, const char *destFormat)
Convert raw file to CSV.
unsigned short int uint16
16-bit unsigned integer
Definition: garmin_types.h:64
static void decodeUint16Fields(uint32 &field_flags, int start, int end, ofstream &rawFile, vector< string > &record, uint16 &fieldIdx, char *format)
Convert 6 byte hex string into 2 byte unsigned int.
uint16 year
Real year (1990 means 1990!)
Definition: garmin_types.h:156
static void decodeStringFields(uint32 &field_flags, int start, int end, ofstream &rawFile, vector< string > &record, uint16 &fieldIdx)
Convert CSV fields into 1 byte length and character stream.
uint8 month
month (1-12)
Definition: garmin_types.h:154
unsigned char uint8
8-bit unsigned integer
Definition: garmin_types.h:62
void updateEventBeingVerified(void *val, vector< string > &record)
callback for updating a verified Driver Status Change event
static void convertTimeTypeToString(time_type aTimestamp, char *full, int fullSize)
static void decodeUint32Fields(uint32 &field_flags, int start, int end, ofstream &rawFile, vector< string > &record, uint16 &fieldIdx, char *format)
Convert 10 byte hex string into 4 byte unsigned int.
bool locateEventBeingVerified(void *key, vector< string > &record)
callback for finding a Driver Status Change event in CSV file
static time_type encodeTimestampField(uint32 field_flags, int start, ifstream &rawFile, CsvWriter &csvWriter)
bool findRecordAt(const char *source, evt_log_reason type, uint16 index, bool(*visitor)(AobrdEventLogConverter *converter, std::vector< std::string > &record, void *data), void *data)
Visit records by type and index.
void Finish()
Definition: CsvWriter.cpp:63
void UTIL_convert_UTC_to_local(const time_type *aUtcTime, time_type *aLocalTime)
Converts a time_type from UTC to local time.
Definition: util.cpp:526
static void encodeUint32Fields(uint32 field_flags, int start, int end, ifstream &rawFile, CsvWriter &csvWriter, char *format)
Convert 4 byte unsigned int into 10 byte hex string.
unsigned long int uint32
32-bit unsigned integer
Definition: garmin_types.h:66
uint32 convertToRaw(const char *source, const char *dest)
Convert CSV file to raw.
uint32 time_type
Absolute time (number of seconds since 12/31/1989 12:00 am UTC)
Definition: garmin_types.h:97
void NewLine()
Definition: CsvWriter.cpp:57
sint16 hour
hour (0-65535), range required for correct ETE conversion
Definition: garmin_types.h:160
static void decodeDegreeFields(uint32 &field_flags, int start, int end, ofstream &rawFile, vector< string > &record, uint16 &fieldIdx, char *format)
Convert degrees into 4 byte signed int.
void UTIL_convert_local_to_UTC(const time_type *aLocalTime, time_type *aUtcTime)
Converts a time_type from local to UTC time.
Definition: util.cpp:549