Garmin Fleet Management Controller  2.19.0
FmiApplicationLayer.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 *
3 * MODULE NAME:
4 * FmiApplicationLayer.cpp
5 *
6 * Copyright 2008-2018 by Garmin Ltd. or its subsidiaries.
7 *---------------------------------------------------------------------
8 * $NoKeywords$
9 *********************************************************************/
10 
11 #include "stdafx.h"
12 #include <stdlib.h>
13 #include <fstream>
14 
15 #include "fmi.h"
16 #include "FmiApplicationLayer.h"
17 #include "GarminTransportLayer.h"
18 #include "GarminPacket.h"
19 #include "Event.h"
20 #include "util.h"
21 #include "utl_crc.h"
22 #include "SerialPort.h"
23 #include <zlib.h>
24 
25 #if( FMI_SUPPORT_A610 )
26 #include "AobrdEventLogConverter.h"
27 #endif
28 
29 /*--------------------------------------------------------------------
30 LITERAL CONSTANTS
31 --------------------------------------------------------------------*/
32 #if( FMI_SUPPORT_A603 )
33 #define SAVE_STOPS "a603_stops.dat"
36 #endif
37 
38 #if( FMI_SUPPORT_A604 )
39 #define SAVE_CAN_RESP "canned_responses.dat"
42 
45 #define SAVE_CAN_MSG "canned_messages.dat"
46 
49 #define SAVE_STATUS "driver_status.dat"
50 
53 #define SAVE_SENT_CAN "sent_canned_response_messages.dat"
54 
56 #define GZIPPED_TRANSFER_FILENAME "transfer_file.gz"
57 #endif
58 
59 #if( FMI_SUPPORT_A607 )
60 #define SAVE_CATEGORIES "categories.dat"
63 
66 #define SAVE_WAYPOINTS "waypoints.dat"
67 
70 #define SAVE_DRIVER_LOGINS "drivers.dat"
71 #endif
72 
73 #if( FMI_SUPPORT_A610 )
74 #define SAVE_AOBRD_DRIVERS "aobrd_drivers.dat"
77 #endif
78 
79 using namespace std;
80 
81 //----------------------------------------------------------------------
83 //----------------------------------------------------------------------
85 #if( FMI_SUPPORT_A602 )
86  id_type freeformFmiPacketId
87 #endif
88  )
89  : ApplicationLayer( GarminTransportLayer::getInstance() )
90 #if( FMI_SUPPORT_A603 )
91  , mA603Stops( SAVE_STOPS )
92 #endif
93 #if( FMI_SUPPORT_A604 )
94  , mCannedMessages( SAVE_CAN_MSG )
95  , mCannedResponses( SAVE_CAN_RESP )
96  , mDriverStatuses( SAVE_STATUS )
97  , mSentCannedResponseMessages( SAVE_SENT_CAN )
98 #endif
99 #if( FMI_SUPPORT_A607 )
100  , mWaypoints( SAVE_WAYPOINTS )
101  , mCategories( SAVE_CATEGORIES )
102  , mDriverLogins( SAVE_DRIVER_LOGINS )
103 #endif
104 #if( FMI_SUPPORT_A610 )
105  , mCurrentSendFileType( FMI_FILE_TYPE_GPI )
106  , mAOBRDDrivers( SAVE_AOBRD_DRIVERS )
107 #endif
108 #if( FMI_SUPPORT_A611 )
109  , mLongTextMessageInProgress( false )
110 #endif
111 #if( FMI_SUPPORT_A616 )
112  , mBaudRateSyncRateType( 0 )
113 #endif
114 #if( FMI_SUPPORT_A623 )
115  , mEtaMode( ETA_SETTING_DISPATCH )
116 #endif
117 {
118 #if( FMI_SUPPORT_A604 )
119  memset( mFilePath, 0, sizeof( mFilePath ) );
121  memset( mSentDriverId, 0, sizeof( mSentDriverId ) );
122  memset( &mLastFilePacketSent, 0, sizeof( mLastFilePacketSent ) );
129 #endif
130 
131  //public
134  memset( mClientUnitId, 0, sizeof( mClientUnitId ) );
135  memset( mPVTFixType, 0, sizeof( mPVTFixType ) );
136  memset( mPvtDate, 0, sizeof( mPvtDate ) );
137  memset( mPvtTime, 0, sizeof( mPvtTime ) );
138  memset( mPvtLatitude, 0, sizeof( mPvtLatitude ) );
139  memset( mPvtLongitude, 0, sizeof( mPvtLongitude ) );
140  memset( mPvtAltitude, 0, sizeof( mPvtAltitude ) );
141  memset( mPvtEastWestVelocity, 0, sizeof( mPvtEastWestVelocity ) );
142  memset( mPvtNorthSouthVelocity, 0, sizeof( mPvtNorthSouthVelocity ) );
143  memset( mPvtUpDownVelocity, 0, sizeof( mPvtUpDownVelocity ) );
144  memset( mHorizontalVelocity, 0, sizeof( mHorizontalVelocity ) );
145  memset( mProtocols, 0, sizeof( mProtocols ) );
146  mClientProductId = 0;
148 #if( FMI_SUPPORT_A602 )
149  mEnablePending = false;
150  mFreeformFmiPacketId = freeformFmiPacketId;
151 #endif
152 #if( FMI_SUPPORT_A603 )
153  memset( mEtaTime, 0, sizeof( mEtaTime ) );
154  memset( mEtaLatitude, 0, sizeof( mEtaLatitude ) );
155  memset( mEtaLongitude, 0, sizeof( mEtaLongitude ) );
156  memset( mEtaDistance, 0, sizeof( mEtaDistance ) );
159 #endif
160 #if( FMI_SUPPORT_A604 )
161  memset( mDriverId, 0, sizeof( mDriverId ) );
162  memset( mDriverStatus, 0, sizeof( mDriverStatus ) );
163  memset( mFileVersion, 0, sizeof( mFileVersion ) );
165  mFileSize = 0;
166  mFileVersionLength = 0;
167  mClientPingCount = 0;
168  mServerPingCount = 0;
171 #endif
172 
173 #if( FMI_SUPPORT_A607 )
174  mUseMultipleDrivers = false;
175  mUsePasswords = false;
176 #endif
177 
178 #if( FMI_SUPPORT_A610 )
181  memset( &mCurrentReceiptFile, 0, sizeof( mCurrentReceiptFile ) );
182 #endif
183 } /* FmiApplicationLayer() */
184 
185 //----------------------------------------------------------------------
187 //----------------------------------------------------------------------
189 {
190 }
191 
192 //----------------------------------------------------------------------
204 //----------------------------------------------------------------------
206  (
207  const Packet * aPacket
208  )
209 {
210  const GarminPacket * garminPacket = dynamic_cast<const GarminPacket *>( aPacket );
211 
212  ASSERT( garminPacket != NULL );
213 
214  switch( garminPacket->mPacketId )
215  {
216  case ID_PVT_DATA:
217  {
218  pvt_data_type pvt;
219  time_type pvtTimeUtc;
220  time_type pvtTimeLocal;
221  gps_time_type gpsTime;
222  date_time_data_type pvtDateTime;
223  double latitudeDegrees;
224  double longitudeDegrees;
225 
226  memset( &pvt, 0, sizeof( pvt ) );
227  memcpy( &pvt, garminPacket->mPayload, minval( sizeof( pvt ), garminPacket->mPayloadSize ) );
228 
229  switch( pvt.type_of_gps_fix )
230  {
231  case GPS_FIX_UNUSABLE:
232  sprintf( mPVTFixType, "%s", "unusable" );
233  break;
234  case GPS_FIX_INVALID:
235  sprintf( mPVTFixType, "%s", "invalid" );
236  break;
237  case GPS_FIX_2D:
238  sprintf( mPVTFixType, "%s", "2D-fix" );
239  break;
240  case GPS_FIX_3D:
241  sprintf( mPVTFixType, "%s", "3D-fix" );
242  break;
243  case GPS_FIX_2D_DIFF:
244  sprintf( mPVTFixType, "%s", "2D-diff" );
245  break;
246  case GPS_FIX_3D_DIFF:
247  sprintf( mPVTFixType, "%s", "3D-diff" );
248  break;
249  }
250 
251  gpsTime.time_of_week = maxval( 0, (sint32) pvt.time_of_week - (sint32) pvt.leap_seconds );
252  gpsTime.week_number_days = pvt.week_number_days;
253  UTIL_convert_gps_time_to_seconds( &gpsTime, &pvtTimeUtc );
254  UTIL_convert_UTC_to_local( &pvtTimeUtc, &pvtTimeLocal );
255 
256  UTIL_convert_seconds_to_date_type( &pvtTimeLocal, &pvtDateTime );
257  UTIL_format_date_string( &pvtDateTime, mPvtDate, sizeof( mPvtDate ) );
258  UTIL_convert_seconds_to_time_type( &pvtTimeLocal, &pvtDateTime );
259  UTIL_format_time_string( &pvtDateTime, mPvtTime, sizeof ( mPvtTime ) );
260 
261  latitudeDegrees = UTIL_convert_radians_to_degrees( pvt.position.lat );
262  if( latitudeDegrees < 0 )
263  sprintf( mPvtLatitude, "%08.6f °S", latitudeDegrees * -1 );
264  else
265  sprintf( mPvtLatitude, "%08.6f °N", latitudeDegrees );
266 
267  longitudeDegrees = UTIL_convert_radians_to_degrees( pvt.position.lon );
268  if( longitudeDegrees < 0 )
269  sprintf( mPvtLongitude, "%08.6f °W", longitudeDegrees * -1 );
270  else
271  sprintf( mPvtLongitude, "%08.6f °E", longitudeDegrees );
272 
273  sprintf( mPvtAltitude, "%05.3f m", pvt.altitude );
274 
275  if( pvt.east_velocity < 0 )
276  sprintf( mPvtEastWestVelocity, "%05.3f m/s W", pvt.east_velocity * -1 );
277  else
278  sprintf( mPvtEastWestVelocity, "%05.3f m/s E", pvt.east_velocity );
279 
280  if( pvt.north_velocity < 0 )
281  sprintf( mPvtNorthSouthVelocity, "%05.3f m/s S", pvt.north_velocity * -1 );
282  else
283  sprintf( mPvtNorthSouthVelocity, "%05.3f m/s N", pvt.north_velocity );
284 
285  if( pvt.up_velocity < 0 )
286  sprintf( mPvtUpDownVelocity, "%05.3f m/s D", pvt.up_velocity * -1 );
287  else
288  sprintf( mPvtUpDownVelocity, "%05.3f m/s U", pvt.up_velocity );
289 
291 
292  //tell app to update PVT
294  break;
295  } // end of case ID_PVT_DATA
296  case ID_UNIT_ID:
297  {
298  unit_id_data_type unitIdData;
299  memset( &unitIdData, 0, sizeof( unitIdData ) );
300  memcpy( &unitIdData, garminPacket->mPayload, minval( sizeof( unitIdData ), garminPacket->mPayloadSize ) );
301 
302  sprintf( mClientUnitId, "%u", unitIdData.unit_id );
304  break;
305  } // end of case ID_UNIT_ID
306  case ID_PRODUCT_DATA:
307  {
308  /* Legacy product data protocol. See 001-00063-00 Rev C */
309  product_id_data_type productIdPacket;
310  memset( &productIdPacket, 0, sizeof( productIdPacket ) );
311  memcpy( &productIdPacket, garminPacket->mPayload, minval( sizeof( productIdPacket ), garminPacket->mPayloadSize ) );
312 
313  mClientProductId = productIdPacket.product_id;
314  mClientSoftwareVersion = productIdPacket.software_version;
316  break;
317  }
318 #if( CDT_SUPPORT )
319  case ID_CDT_PACKET:
320  {
321  cdt_id_type cdtPacketId = *(cdt_id_type *) garminPacket->mPayload;
322  uint8 const * cdtPayload = &garminPacket->mPayload[ sizeof( cdtPacketId ) ];
323  sint16 cdtPayloadSize = garminPacket->mPayloadSize - sizeof( cdtPacketId );
324 
325  switch( cdtPacketId )
326  {
327  case CDT_DATA_TRANSFER: // 0x0000
328  {
329  Event::post( EVENT_CDT_PACKET_RECEIVED, cdtPayloadSize, ( void* ) cdtPayload, TRUE );
330  break;
331  }
332  case CDT_PING_RECEIPT: // 0x0081
333  {
334  Event::post( EVENT_CDT_PING_RECEIVED, cdtPayloadSize, ( void* ) cdtPayload, TRUE );
335  break;
336  }
337  }
338  break;
339  }
340 #endif
341 #if( FMI_SUPPORT_A602 )
342  case ID_FMI_PACKET:
343 #if( FMI_SUPPORT_A615 )
344  case ID_HOSART_PACKET:
345 #endif
346  {
347  fmi_id_type fmiPacketId = *(fmi_id_type *) garminPacket->mPayload;
348  uint8 const * fmiPayload = &garminPacket->mPayload[ sizeof( fmiPacketId ) ];
349  sint16 fmiPayloadSize = garminPacket->mPayloadSize - sizeof( fmiPacketId );
350 
351  //This is an FMI Packet, so we need to switch the FMI ID to see what we really have
352  switch( fmiPacketId )
353  {
354  case FMI_ID_PRODUCT_ID_DATA: // 0x0002
355  {
356  product_id_data_type productIdPacket;
357  memset( &productIdPacket, 0, sizeof( productIdPacket ) );
358  memcpy( &productIdPacket, fmiPayload, minval( sizeof( productIdPacket ), fmiPayloadSize ) );
359  mClientProductId = productIdPacket.product_id;
360  mClientSoftwareVersion = productIdPacket.software_version;
361  //flag to tell app new mClientProductId was received and to update the info
363  break;
364  } // end of FMI_ID_PRODUCT_ID_DATA
365  case FMI_ID_PROTOCOL_DATA: // 0x0003
366  {
368  for( unsigned int i = 0; i < fmiPayloadSize - sizeof( protocol ); i += sizeof( protocol ) )
369  {
370  //copy one protocol from fmiPayload
371  memset( &protocol, 0, sizeof( protocol ) );
372  memcpy( &protocol, &fmiPayload[i], sizeof( protocol ) );
373  int offset = ( 5 * ( i / sizeof( protocol ) ) );
374  //print one char tag and 3 digit data (i.e.,. A604) and a space to protocol string
375  sprintf_s( mProtocols + offset, sizeof( mProtocols ) - offset, "%c%03d ", (char)protocol.tag, protocol.data );
376  }
377  //flag to tell app we have received a protocol listing
379  break;
380  } // end of FMI_ID_PROTOCOL_DATA
381 #if( FMI_SUPPORT_A604 && UNICODE_ENABLED )
382  case FMI_ID_UNICODE_REQUEST: // 0x0004
383  {
385  txFmi( FMI_ID_UNICODE_RESPONSE, NULL, 0 );
386  break;
387  } // FMI_ID_UNICODE_REQUEST
388 #endif
389  case FMI_ID_TEXT_MSG_ACK: // 0x0020
390  {
393 #if( FMI_SUPPORT_A604 )
394  BOOL cannedResponse = FALSE;
395 #endif
396 
397  memset( &data, 0, sizeof( data ) );
398  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
399 
400  memset( ackEvent->ack_text, 0, sizeof( ackEvent->ack_text ) );
401  ackEvent->message_id = MessageId( data.id_size, data.id );
402 
403 #if( FMI_SUPPORT_A604 )
404  //prepare and send receipt
405  text_msg_id_data_type receipt;
406  memset( &receipt, 0, sizeof( receipt ) );
407  receipt.id_size = minval( data.id_size, sizeof( data.id ) );
408  memcpy( receipt.id, data.id, receipt.id_size );
409  txFmi( FMI_ID_TEXT_MSG_ACK_RCPT, (uint8*)&receipt, sizeof( receipt ) );
410 
411  //this packet ID is sent back for all A602 ACKs and canned messages
412  //must check to see if the id corresponds to a canned response
414  {
415  cannedResponse = TRUE;
417  }
418 
419  if( cannedResponse )
420  {
421  //Get the response text
422  ClientListItem& canResp = mCannedResponses.get( data.msg_ack_type );
423  if( canResp.isValid() )
424  {
425  char str[50];
426  WideCharToMultiByte( mClientCodepage, 0, canResp.getCurrentName(), -1, str, 50, NULL, NULL );
427  str[49] = '\0';
428  sprintf( ackEvent->ack_text, "%s", str );
429  }
430  else
431  sprintf( ackEvent->ack_text, "%s", "invalid" );
432  }
433  //if not a canned message...it is an old A602 ACK
434  else
435 #endif //FMI_SUPPORT_A604
436  {
437  switch( data.msg_ack_type )
438  {
439  case OK_ACK:
440  strcpy( ackEvent->ack_text, "Okay" );
441  break;
442  case YES_ACK:
443  strcpy( ackEvent->ack_text, "Yes" );
444  break;
445  case NO_ACK:
446  strcpy( ackEvent->ack_text, "No" );
447  break;
448  default:
449  strcpy( ackEvent->ack_text, "invalid" );
450  break;
451  }
452  }
453  //Tell app to display the text message ack dialog
454  Event::post( EVENT_FMI_TXT_MSG_ACK, 0, ackEvent );
455  break;
456  } // end of FMI_ID_TXT_MSG_ACK
457 #if( FMI_SUPPORT_A603 )
458  case FMI_ID_CLIENT_OPEN_TXT_MSG: // 0x0024
459  {
463 
464  memset( &textMessage, 0, sizeof( textMessage ) );
465  memcpy( &textMessage, fmiPayload, minval( sizeof( textMessage ), fmiPayloadSize ) );
466 
467  receipt.unique_id = textMessage.unique_id;
468  txFmi( FMI_ID_CLIENT_TXT_MSG_RCPT, (uint8*)&receipt, sizeof( receipt ) );
469 
470  memset( textMessageEvent, 0, sizeof( textMessageEvent ) );
471  strncpy( textMessageEvent->message_text, textMessage.text_message, cnt_of_array( textMessageEvent->message_text ) - 1 );
472  textMessageEvent->origination_time = textMessage.origination_time;
473 
474  textMessageEvent->message_id = textMessage.unique_id;
475  Event::post( EVENT_FMI_TXT_MSG_FROM_CLIENT, 0, textMessageEvent );
476  break;
477  } // end of FMI_ID_CLIENT_OPEN_TXT_MSG
478 #endif
479 #if( FMI_SUPPORT_A607 )
480  case FMI_ID_A607_CLIENT_OPEN_TXT_MSG: // 0x0026
481  {
485  textMessageEvent->latitude = INVALID_LAT;
486 
487  memset( &textMessage, 0, sizeof( textMessage ) );
488  memcpy( &textMessage, fmiPayload, minval( sizeof( textMessage ), fmiPayloadSize ) );
489 
490  receipt.unique_id = textMessage.unique_id;
491  txFmi( FMI_ID_CLIENT_TXT_MSG_RCPT, (uint8*)&receipt, sizeof( receipt ) );
492 
493  memset( textMessageEvent->message_text, 0, sizeof( textMessageEvent->message_text ) );
494  strncpy( textMessageEvent->message_text, textMessage.text_message, cnt_of_array( textMessageEvent->message_text ) - 1 );
495  textMessageEvent->origination_time = textMessage.origination_time;
496 
497  textMessageEvent->message_id = textMessage.unique_id;
498  textMessageEvent->link_id = MessageId( textMessage.id_size, textMessage.id );
499  textMessageEvent->latitude = textMessage.scposn.lat;
500  textMessageEvent->longitude = textMessage.scposn.lon;
501 
502  Event::post( EVENT_FMI_TXT_MSG_FROM_CLIENT, 0, textMessageEvent );
503  break;
504  }
505 #endif
506 #if( FMI_SUPPORT_A604 )
507  case FMI_ID_CANNED_RESP_LIST_RCPT: // 0x0029
508  {
510  memset( &receipt, 0, sizeof( receipt ) );
511  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
512 
513  if( receipt.result_code == CANNED_RESP_LIST_SUCCESS ) //success
514  {
515  //we have to keep track of canned response text messages
516  //because the packet that is sent back for the response
517  //is the same as Okay/Yes/No messages so they need
518  //to be distinguished
519  MessageId messageId( receipt.id_size, receipt.id );
520  InboxListItem & item = mSentCannedResponseMessages.get( messageId );
521  item.setValid();
523 
524 #if( FMI_SUPPORT_A611 )
525  // If necessary, send a Long Text Message instead.
527  {
529  }
530  else
531 #endif
532  {
534  }
535  }
536  else
537  {
539  }
540  break;
541  }
542 
543  case FMI_ID_A604_OPEN_TEXT_MSG_RCPT: // 0x002B
544  {
546  memset( &receipt, 0, sizeof( server_to_client_text_msg_receipt_data_type ) );
547  memcpy( &receipt, fmiPayload, minval( sizeof( server_to_client_text_msg_receipt_data_type ), fmiPayloadSize ) );
548  if( receipt.result_code == FALSE )
549  {
550  Event::post( EVENT_FMI_A604_TXT_MSG_ERROR, 0, new MessageId( receipt.id_size, receipt.id ) );
551  }
552  break;
553  }
554 #endif
555 
556 #if( FMI_SUPPORT_A607 )
558  {
560  memset( &response, 0, sizeof( response ) );
561  memcpy( &response, fmiPayload, minval( fmiPayloadSize, sizeof( response ) ) );
562 
564  break;
565  }
566 #endif
567 
568 #if( FMI_SUPPORT_A604 )
569  case FMI_ID_SET_CANNED_RESPONSE_RCPT: // 0x0032
570  {
572  map<uint32, ClientListItem>::iterator iter;
573  memset( &receipt, 0, sizeof( receipt ) );
574  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
577  else if( receipt.result_code )
578  {
579  if( mCannedResponses.contains( receipt.response_id ) ) //is in map...otherwise there was an error
580  {
581  ClientListItem& item = mCannedResponses.get( receipt.response_id );
582  item.commitName();
584  }
585  }
586  break;
587  }
588  case FMI_ID_DELETE_CANNED_RESPONSE_RCPT: // 0x0033
589  {
591  memset( &receipt, 0, sizeof( receipt ) );
592  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
593  if( receipt.result_code )
594  {
597  }
598  break;
599  }
600  case FMI_ID_REFRESH_CANNED_RESP_LIST: // 0x0034
601  {
604  memset( &request, 0, sizeof( request ) );
605  memcpy( &request, fmiPayload, minval( fmiPayloadSize, sizeof( request ) ) );
606 
607  //send all valid ids
608  if( request.response_count == 0 )
609  {
610  for( iter = mCannedResponses.begin(); iter != mCannedResponses.end(); iter++ )
611  {
613  //send Set Canned Response packet
614  if( iter->second.isValid() )
615  {
616  sendCannedResponse( iter->first, iter->second.getCurrentName() );
617  }
618  }
619  }
620  //only send requested ids
621  else if( request.response_count > 0 && request.response_count <= 50 )
622  {
623  //loop through requested ids and send if valid
624  for( unsigned int i = 0; i < request.response_count; i++ )
625  {
626  if( mCannedResponses.contains( request.response_id[i] ) )
627  {
628  ClientListItem& item = mCannedResponses.get( request.response_id[i] );
629  if( item.isValid() )
630  {
631  //send Set Canned Response packet
632  sendCannedResponse( item.getId(), item.getCurrentName() );
633  }
634  }
635  }
636  }
637  break;
638  }
639  case FMI_ID_TEXT_MSG_STATUS: // 0x0041
640  {
643  memset( &status, 0, sizeof( status ) );
644  memcpy( &status, fmiPayload, minval( sizeof( status ), fmiPayloadSize ) );
645 
646  statusEvent->msg_id = MessageId( status.id_size, status.id );
647  statusEvent->message_status = (fmi_A604_message_status)status.status_code;
648 
650  break;
651  }
652 
653  case FMI_ID_SET_CANNED_MSG_RCPT: // 0x0051
654  {
656  memset( &receipt, 0, sizeof( receipt ) );
657  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
660  else if( receipt.result_code )
661  {
662  if( mCannedMessages.contains( receipt.message_id ) ) //is in map...otherwise there was an error
663  {
664  ClientListItem& item = mCannedMessages.get( receipt.message_id );
665  item.commitName();
667  }
668  }
669  break;
670  }
671 
672  case FMI_ID_DELETE_CANNED_MSG_RCPT: // 0x0053
673  {
675  memset( &receipt, 0, sizeof( receipt ) );
676  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
677  if( receipt.result_code )
678  {
679  mCannedMessages.remove( receipt.message_id );
681  }
682  break;
683  }
684  case FMI_ID_REFRESH_CANNED_MSG_LIST: // 0x0054
685  {
687  for( iter = mCannedMessages.begin(); iter != mCannedMessages.end(); iter++ )
688  {
689  if( iter->second.isValid() )
690  {
692  sendCannedMessage( iter->first, iter->second.getCurrentName() );
693  }
694  }
695  break;
696  }
697 #endif
698 
699 #if( FMI_SUPPORT_A611 )
700  case FMI_ID_LONG_TEXT_MSG_RCPT: // 0x0056
701  {
703  uint8 nextSeqNum;
704 
705  memset( &receipt, 0, sizeof( long_text_msg_receipt_data_type ) );
706  memcpy( &receipt, fmiPayload, minval( sizeof( long_text_msg_receipt_data_type ), fmiPayloadSize ) );
707  nextSeqNum = receipt.sequence_number + 1;
708 
709  // An error occurred.
710  if( receipt.result_code != LONG_TEXT_SUCCESS )
711  {
713  Event::post( EVENT_FMI_LONG_TEXT_MSG_ERROR, receipt.result_code, new MessageId( receipt.id_size, receipt.id ) );
714  }
715 
716  // The text message is not yet complete.
717  else if( ( nextSeqNum < cnt_of_array( mLongTextMessage ) ) &&
719  {
721  }
722 
723  // The text message is complete.
724  else
725  {
727  }
728 
729  break;
730  }
731 #endif
732 
733 #if( FMI_SUPPORT_A604 )
734  case FMI_ID_SORT_STOP_LIST_ACK: // 0x0111
735  {
737  for( iter = mA603Stops.begin(); iter != mA603Stops.end(); iter++ )
738  {
740  }
741  break;
742  }
743 #endif
744 
745 #if FMI_SUPPORT_A607
747  {
748  waypoint_rcpt_data_type receipt;
749  memset( &receipt, 0, sizeof( receipt ) );
750  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
751 
752  if( receipt.result_code )
753  {
754  if( mWaypoints.contains( receipt.unique_id ) ) //is in map...otherwise there was an error
755  {
756  WaypointListItem& item = mWaypoints.get( receipt.unique_id );
757  item.commitName();
759  }
760  }
761  break;
762  }
763 
765  {
767  uint16 uniqueId;
768 
769  memset( &receipt, 0, sizeof( receipt ) );
770  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
771 
772  uniqueId = receipt.unique_id;
773 
774  if( mWaypoints.contains( uniqueId ) ) // if the waypoint exists in the list, delete it.
775  {
776  mWaypoints.remove( uniqueId );
777  Event::post( EVENT_FMI_WAYPOINT_LIST_CHANGED ); // refresh the list
778  }
779 
780  txFmi( FMI_ID_WAYPOINT_DELETED_RCPT, (uint8*)&uniqueId, sizeof( uniqueId ) );
781  break;
782  }
783 
785  {
787  boolean listChanged = FALSE;
788 
789  memset( &receipt, 0, sizeof( receipt ) );
790  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
791 
792  for( int i = 0; i < 16; i++ )
793  {
794  if( receipt.cat_id & setbit( i ) )
795  {
796  mCategories.remove( i );
797  listChanged = TRUE;
798  }
799  }
800 
801  if( listChanged )
802  {
804  }
805  break;
806  }
808  {
809  category_rcpt_data_type receipt;
810  memset( &receipt, 0, sizeof( receipt ) );
811  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
812 
813  if( receipt.result_code )
814  {
815  if( mCategories.contains( receipt.id ) ) //is in map...otherwise there was an error
816  {
817  ClientListItem& item = mCategories.get( receipt.id );
818  item.commitName();
820  }
821  }
822  break;
823  }
824 #endif
825 
826 #if( FMI_SUPPORT_A603 )
827  case FMI_ID_ETA_DATA: //0x0201
828  {
829  eta_data_type etaDataPacket;
830  eta_data_receipt_type receipt;
831  memset( &etaDataPacket, 0, sizeof( etaDataPacket ) );
832  memcpy( &etaDataPacket, fmiPayload, minval( sizeof( etaDataPacket ), fmiPayloadSize ) );
833  receipt.unique_id = etaDataPacket.unique_id;
834  txFmi( FMI_ID_ETA_DATA_RCPT, (uint8*)&receipt, sizeof( receipt ) );
835 
836  if( etaDataPacket.distance_to_destination != INVALID32 &&
837  etaDataPacket.eta_time != INVALID32 )
838  {
839  double latitudeDegrees;
840  double longitudeDegrees;
841  time_type etaTimeLocal;
842  date_time_data_type dateTimeLocal;
843 
844  latitudeDegrees = UTIL_convert_semicircles_to_degrees( etaDataPacket.position_of_destination.lat );
845  if( latitudeDegrees < 0 )
846  {
847  sprintf( mEtaLatitude, "%08.6f °S", latitudeDegrees * -1 );
848  }
849  else
850  {
851  sprintf( mEtaLatitude, "%08.6f °N", latitudeDegrees );
852  }
853 
854  longitudeDegrees = UTIL_convert_semicircles_to_degrees( etaDataPacket.position_of_destination.lon );
855  if( longitudeDegrees < 0 )
856  {
857  sprintf( mEtaLongitude, "%08.6f °W", longitudeDegrees * -1 );
858  }
859  else
860  {
861  sprintf( mEtaLongitude, "%08.6f °E", longitudeDegrees );
862  }
863 
864  UTIL_convert_UTC_to_local( &etaDataPacket.eta_time, &etaTimeLocal );
865  UTIL_convert_seconds_to_time_type( &etaTimeLocal, &dateTimeLocal );
866  UTIL_format_time_string( &dateTimeLocal, mEtaTime, sizeof( mEtaTime ) );
867 
868  if( etaDataPacket.distance_to_destination > 1000 )
869  {
870  sprintf( mEtaDistance, "%.2f km", (float)etaDataPacket.distance_to_destination/1000 );
871  }
872  else
873  {
874  sprintf( mEtaDistance, "%d m", etaDataPacket.distance_to_destination );
875  }
876 
877  mActiveRoute = TRUE;
878  }
879  else
880  {
881  strcpy( mEtaTime, "invalid" );
882  strcpy( mEtaDistance, "" );
883  strcpy( mEtaLatitude, "" );
884  strcpy( mEtaLongitude, "" );
886  }
887  // notify user interface
889  break;
890  }
891 
892  case FMI_ID_STOP_STATUS: // 0x0211
893  {
894  stop_status_data_type stopStatus;
896  map<uint32, StopListItem>::iterator iter;
897 
898  memcpy( &stopStatus, fmiPayload, minval( sizeof( stopStatus ), fmiPayloadSize ) );
899 
900  //send receipt
901  receipt.unique_id = stopStatus.unique_id;
902  txFmi( FMI_ID_STOP_STATUS_RCPT, (uint8*)&receipt, sizeof( receipt ) );
903 
904  if( !mStopListInitialized )
905  {
906  // When the server starts up, it must ask for updates for all stops since
907  // the client can change their statuses and delete them when not connected
908  // to the server.
909  // Deleting a stop requires all the data structures to be set up correctly,
910  // but this status could be sent without any of the stop indexes in the
911  // list having been set up at all.
912  // So, stop status requests are sent out for all stops the server has in
913  // its save file when initializing the server. If the mStopListInitialized
914  // flag hasn't been set yet, we only care about deleted stops. We must
915  // remove them from the save file and stop id list. When all deleted stops
916  // are gone, we can safely use this update packet to assign the index in the
917  // stop list, as nothing will be sent for deleted stops anymore.
918  if( stopStatus.stop_status == STOP_STATUS_DELETED )
919  {
920  mA603Stops.remove( stopStatus.unique_id );
921  }
922  else
923  {
924  //flags for ETA display
925  if( stopStatus.stop_status == STOP_STATUS_ACTIVE )
926  {
927  mActiveStopId = stopStatus.unique_id;
928  }
929  else if( stopStatus.unique_id == mActiveStopId &&
930  stopStatus.stop_status != STOP_STATUS_ACTIVE )
931  {
934  }
935  }
936  }
937  //We are initialized, so either we have mIsValid data structures or nothing will be
938  //deleted. So we can proceed like normal.
939  else if( stopStatus.unique_id != INVALID32 &&
940  stopStatus.stop_index_in_list != INVALID16 )
941  {
942  //the stop id and index in list are valid, so update
943  mA603Stops.get( stopStatus.unique_id ).setStopStatus( stopStatus.stop_status );
944  if( mStopIndexInList.size() <= stopStatus.stop_index_in_list )
945  mStopIndexInList.resize( stopStatus.stop_index_in_list + 10, INVALID32 );
946  mStopIndexInList[stopStatus.stop_index_in_list] = stopStatus.unique_id;
947 
948  //flags for ETA display
949  if( stopStatus.stop_status == STOP_STATUS_ACTIVE )
950  mActiveStopId = stopStatus.unique_id;
951  else if( stopStatus.unique_id == mActiveStopId &&
952  stopStatus.stop_status != STOP_STATUS_ACTIVE )
953  {
955  }
956  }
957  else if( stopStatus.stop_index_in_list == INVALID16 &&
958  stopStatus.stop_status == STOP_STATUS_DELETED )
959  {
960  removeStopById( stopStatus.unique_id );
961  }
962  uint32 eventData = stopStatus.stop_status;
963  if( mActiveStopId == stopStatus.unique_id )
964  eventData |= setbit( 16 );
966  break;
967  }
968 
969 #endif
970 
971 #if( FMI_SUPPORT_A604 )
972  case FMI_ID_USER_INTERFACE_TEXT_RCPT: //0x0241
973  {
975 
976  memset( &receipt, 0, sizeof( receipt ) );
977  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
978 
979  if( !receipt.result_code )
981  break;
982  }
983 
984  case FMI_ID_MSG_THROTTLING_RESPONSE: // 0x0251
985  {
987 
988  memset( &response, 0, sizeof( response ) );
989  memcpy( &response, fmiPayload, minval( sizeof( response ), fmiPayloadSize ) );
990 
991  if( response.new_state != MESSAGE_THROTTLE_STATE_DISABLE &&
993  {
995  }
996  break;
997  }
998 #endif
999 
1000 #if( FMI_SUPPORT_A605 )
1001  case FMI_ID_MSG_THROTTLING_QUERY_RESPONSE: // 0x0253
1002  {
1004 
1005  memset( &list, 0, sizeof( list ) );
1006  memcpy( &list, fmiPayload, minval( sizeof( list ), fmiPayloadSize ) );
1007 
1008  uint16 throttleCount = minval( list.response_count, MAX_THROTTLED_PROTOCOLS );
1009  for( uint16 i = 0; i < throttleCount; ++i )
1010  {
1013  }
1015  break;
1016  }
1017 #endif
1018 
1019 #if( FMI_SUPPORT_A604 )
1020  case FMI_ID_PING: // 0x0260
1021  {
1022  mClientPingCount++;
1023  mLastClientPingTime = CTime::GetCurrentTime();
1024 
1025  txFmi( FMI_ID_PING_RESPONSE, NULL, 0 );
1026 
1028  break;
1029  }
1030  case FMI_ID_PING_RESPONSE: // 0x0261
1031  {
1032  mServerPingCount++;
1033  mLastServerPingTime = CTime::GetCurrentTime();
1034 
1036  break;
1037  }
1038 
1039  #if( FMI_SUPPORT_A610 )
1040  case FMI_ID_FILE_TRANSFER_START: // 0x0400
1041  {
1042  file_info_data_type file;
1043 
1044  memset( &file, 0, sizeof( file ) );
1045  memcpy( &file, fmiPayload, minval( sizeof( file ), fmiPayloadSize ) );
1046 
1048  (
1049  file
1050  );
1051  break;
1052  }
1053  case FMI_ID_FILE_DATA_PACKET: // 0x0401
1054  {
1055  file_packet_data_type data_packet;
1056 
1057  memset( &data_packet, 0, sizeof( data_packet ) );
1058  memcpy( &data_packet, fmiPayload, minval( sizeof( data_packet ), fmiPayloadSize ) );
1059 
1061  (
1062  data_packet.offset,
1063  data_packet.data_length,
1064  data_packet.file_data
1065  );
1066  break;
1067  }
1068  case FMI_ID_FILE_TRANSFER_END: // 0x0402
1069  {
1070  file_end_data_type file_end;
1071 
1072  memset( &file_end, 0, sizeof( file_end ) );
1073  memcpy( &file_end, fmiPayload, minval( sizeof( file_end ), fmiPayloadSize ) );
1074 
1075  endFileReceive();
1076 
1077  break;
1078  }
1079  #endif
1080 
1081  case FMI_ID_FILE_START_RCPT: // 0x0403
1082  {
1083  file_receipt_data_type receipt;
1084 
1085  memset( &receipt, 0, sizeof( receipt ) );
1086  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
1087 
1088  //check success
1089  if( receipt.result_code == 0 )
1090  {
1091  CFile file;
1092  if ( file.Open( CString( mFilePath ), CFile::modeRead ) )
1093  {
1094  file_packet_data_type data;
1096 
1097  memset( &data, 0, sizeof( data ) );
1098  data.data_length = (uint8) file.Read( (char*)data.file_data, 245 );
1099 
1100  memcpy( &mLastFilePacketSent, &data, sizeof( data ) );
1101  txFmi( FMI_ID_FILE_DATA_PACKET, (uint8*)&data, sizeof( data ) - sizeof( data.file_data ) + data.data_length );
1102 
1103  file.Close();
1104  }
1105  else
1107  }
1108  else
1111  break;
1112  }
1113  case FMI_ID_FILE_PACKET_RCPT: // 0x0404
1114  {
1115  packet_receipt_data_type receipt;
1116 
1117  memset( &receipt, 0, sizeof( receipt ) );
1118  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
1119 
1122 
1123  if( receipt.next_offset == mFileTransferSize || mStopFileTransfer == TRUE )
1124  {
1125  //transferring file data is complete or server is stopping manually
1126  //calculate and send crc
1127  file_end_data_type data;
1128  uint8* fileData;
1129  CFile file;
1130  if( !mStopFileTransfer && file.Open( CString( mFilePath ), CFile::modeRead ) )
1131  {
1132  fileData = new uint8[mFileTransferSize];
1133  file.Read( (char*)fileData, mFileTransferSize );
1134  data.crc = UTL_calc_crc32( fileData, mFileTransferSize, 0 );
1135  txFmi( FMI_ID_FILE_TRANSFER_END, (uint8*)&data, sizeof( data ) );
1136  file.Close();
1137  delete[] fileData;
1138  }
1139  else
1140  {
1144  }
1145  }
1146  else if( receipt.next_offset == receipt.offset )
1147  {
1148  //resend last packet
1149  txFmi
1150  (
1154  );
1155  }
1156  else if( receipt.next_offset == INVALID32 )
1157  {
1160  }
1161  else
1162  {
1163  // mIsValid offset...send next set of data
1164  CFile file;
1165  if( file.Open( CString( mFilePath ), CFile::modeRead ) )
1166  {
1167  file_packet_data_type data;
1168 
1169  file.Seek( receipt.next_offset, CFile::begin );
1170  memset( &data, 0, sizeof( data ) );
1171  data.offset = receipt.next_offset;
1172  data.data_length = (uint8) file.Read( (char*)data.file_data, 245 );
1173  memcpy( &mLastFilePacketSent, &data, sizeof( data ) );
1174  txFmi
1175  (
1177  (uint8*)&data,
1178  sizeof( data ) - sizeof( data.file_data ) + data.data_length
1179  );
1180  file.Close();
1181  }
1182  else
1183  {
1186  }
1187  }
1188  break;
1189  }
1190  case FMI_ID_FILE_END_RCPT: // 0x0405
1191  {
1192  file_receipt_data_type receipt;
1193 
1194  memset( &receipt, 0, sizeof( receipt ) );
1195  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
1196 
1197  //check success
1198  if( receipt.result_code == 0 )
1199  {
1201  }
1202  else
1205  break;
1206  }
1207  case FMI_ID_GPI_FILE_INFORMATION: // 0x0407
1208  {
1209  file_info_data_type fileInfo;
1210 
1211  memset( &fileInfo, 0, sizeof( fileInfo ) );
1212  memcpy( &fileInfo, fmiPayload, minval( sizeof( fileInfo ), fmiPayloadSize ) );
1213 
1214  mFileSize = fileInfo.file_size;
1216 
1217  memset( mFileVersion, 0, 16 );
1218  memcpy( mFileVersion, fileInfo.file_version, fileInfo.file_version_length );
1220  break;
1221  }
1223  {
1225  memset( &receipt, 0, sizeof( receipt ) );
1226  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
1228  {
1230  break;
1231  }
1232  else if( receipt.result_code )
1233  {
1234  if( mDriverStatuses.contains( receipt.status_id ) ) //found in map
1235  {
1236  ClientListItem& item = mDriverStatuses.get( receipt.status_id );
1237  item.commitName();
1239  }
1240  }
1241  break;
1242  }
1244  {
1246  memset( &receipt, 0, sizeof( receipt ) );
1247  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
1248  if( receipt.result_code )
1249  {
1250  mDriverStatuses.remove( receipt.status_id );
1252  }
1253  else
1254  {
1256  }
1257  break;
1258  }
1259  case FMI_ID_DRIVER_STATUS_LIST_REFRESH: //0x0804
1260  {
1262  for( iter = mDriverStatuses.begin(); iter != mDriverStatuses.end(); iter++ )
1263  {
1264  if( iter->second.isValid() )
1265  {
1267  sendDriverStatusListItem( iter->first, iter->second.getCurrentName() );
1268  }
1269  }
1270  break;
1271  }
1272  case FMI_ID_DRIVER_ID_UPDATE: // 0x0811
1273  {
1274  driver_id_data_type data;
1275  memset( &data, 0, sizeof( data ) );
1276  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1277 
1279  memset( &receipt, 0, sizeof( receipt ) );
1280  receipt.result_code = TRUE;
1281  receipt.status_change_id = data.status_change_id;
1282 
1283  strcpy( mDriverId[0], data.driver_id );
1285  txFmi( FMI_ID_DRIVER_ID_RCPT, (uint8*)&receipt, sizeof( receipt ) );
1286  break;
1287  }
1288  case FMI_ID_DRIVER_ID_RCPT: // 0x0812
1289  {
1291  memset( &receipt, 0, sizeof( receipt ) );
1292  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
1293  if( receipt.result_code && receipt.driver_idx < FMI_DRIVER_COUNT )
1294  {
1295  int index = receipt.driver_idx;
1296  strncpy( mDriverId[index], mSentDriverId, cnt_of_array( mDriverId[index] ) - 1 );
1297  mDriverId[index][cnt_of_array( mDriverId[index] ) - 1] = '\0';
1299  }
1300  break;
1301  }
1302 #if( FMI_SUPPORT_A607 )
1304  {
1306  memset( &data, 0, sizeof( data ) );
1307  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1308 
1310  memset( &receipt, 0, sizeof( receipt ) );
1311  receipt.status_change_id = data.status_change_id;
1312  receipt.driver_idx = data.driver_idx;
1313  receipt.result_code = TRUE;
1314 
1315  if( data.driver_idx >= FMI_DRIVER_COUNT )
1316  {
1317  receipt.result_code = FALSE;
1318  }
1319  else if( 0 == strlen( data.driver_id ) )
1320  {
1321  // not logged in
1322  receipt.result_code = TRUE;
1323  }
1324  else if( mUsePasswords )
1325  {
1326  if( mDriverLogins.contains( data.driver_id ) )
1327  {
1328  DriverLoginItem & login = mDriverLogins.get( data.driver_id );
1329  char actualPassword[ sizeof( data.password ) ];
1330  WideCharToMultiByte( CP_UTF8, 0, login.getPassword().GetBuffer(), -1, actualPassword, sizeof( actualPassword ), NULL, NULL );
1331  if( 0 != strcmp( data.password, actualPassword ) )
1332  {
1333  // incorrect password
1334  receipt.result_code = FALSE;
1335  }
1336  }
1337  else
1338  {
1339  // driver ID not found
1340  receipt.result_code = FALSE;
1341  }
1342  }
1343 
1344  if( receipt.result_code )
1345  {
1346  strcpy( mDriverId[data.driver_idx], data.driver_id );
1348  }
1349 
1350  txFmi( FMI_ID_DRIVER_ID_RCPT, (uint8*)&receipt, sizeof( receipt ) );
1351  break;
1352  }
1353 #endif
1354  case FMI_ID_DRIVER_STATUS_UPDATE: // 0x0821
1355  {
1356  driver_status_data_type status;
1358 
1359  memset( &status, 0, sizeof( status ) );
1360  memcpy( &status, fmiPayload, minval( sizeof( status ), fmiPayloadSize ) );
1361  memset( &receipt, 0, sizeof( receipt ) );
1362 
1363  receipt.status_change_id = status.status_change_id;
1364  receipt.result_code = procDriverStatusUpdate( status.driver_status );
1365 
1366  txFmi( FMI_ID_DRIVER_STATUS_RCPT, (uint8*)&receipt, sizeof( receipt ) );
1367  break;
1368  }
1369  case FMI_ID_DRIVER_STATUS_RCPT: // 0x0822
1370  {
1372 
1373  memset( &receipt, 0, sizeof( receipt ) );
1374  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
1375 
1376  if( receipt.result_code )
1377  {
1379  }
1380  break;
1381  }
1382 #endif // FMI_SUPPORT_A604
1383 #if( FMI_SUPPORT_A606 )
1384  case FMI_SAFE_MODE_RESP: // 0x0901
1385  {
1387  memset( &receipt, 0, sizeof( receipt ) );
1388 
1389  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
1390  if( receipt.result_code == FALSE )
1391  {
1393  }
1394  break;
1395  }
1396 #endif // FMI_SUPPORT_A606
1397 #if( FMI_SUPPORT_A607 )
1398  case FMI_ID_DRIVER_STATUS_UPDATE_D607: // 0x0823
1399  {
1402 
1403  memset( &status, 0, sizeof( status ) );
1404  memcpy( &status, fmiPayload, minval( sizeof( status ), fmiPayloadSize ) );
1405  memset( &receipt, 0, sizeof( receipt ) );
1406 
1407  receipt.status_change_id = status.status_change_id;
1408  receipt.result_code = procDriverStatusUpdate( status.driver_status, status.driver_idx );
1409  receipt.driver_idx = status.driver_idx;
1410 
1411  txFmi( FMI_ID_DRIVER_STATUS_RCPT, (uint8*)&receipt, sizeof( receipt ) );
1412  break;
1413  }
1414 #endif // FMI_SUPPORT_A607
1415 #if( FMI_SUPPORT_A608 )
1416  case FMI_SPEED_LIMIT_RCPT: //0X1001
1417  {
1419 
1420  memset( &receipt, 0, sizeof( receipt ) );
1421  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
1422 
1424 
1425  break;
1426  }
1427  case FMI_SPEED_LIMIT_ALERT: //0X1002
1428  {
1431 
1432  memset( &alert, 0, sizeof( alert ) );
1433  memcpy( &alert, fmiPayload, minval( sizeof( alert ), fmiPayloadSize ) );
1434 
1435  receipt.timestamp = alert.timestamp;
1436 
1437  txFmi( FMI_SPEED_LIMIT_ALERT_RCPT, (uint8*)&receipt, sizeof( receipt ) );
1438  break;
1439  }
1440 #endif //FMI_SUPPORT_A608
1441 
1442 #if( FMI_SUPPORT_A610 )
1443  case FMI_DRIVER_LOGIN_REQUEST: //0X1101
1444  {
1445  //validate username and password
1447  memset( &data, 0, sizeof( data ) );
1448  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1449 
1451  memset( &receipt, 0, sizeof( receipt ) );
1452  receipt.ui_timestamp = data.ui_timestamp;
1453  receipt.result_code = 1;
1454 
1455  if( 0 == strlen( data.driver_id ) )
1456  {
1457  // not logged in
1458  receipt.result_code = 1;
1459  }
1460  else if( mAOBRDDrivers.contains( data.driver_id ) )
1461  {
1462  AobrdDriverItem & driver = mAOBRDDrivers.get( data.driver_id );
1463  char actualPassword[ sizeof( data.driver_password ) ];
1464  WideCharToMultiByte( CP_UTF8, 0, driver.getPassword().GetBuffer(), -1, actualPassword, sizeof( actualPassword ), NULL, NULL );
1465  if( 0 != strcmp( data.driver_password, actualPassword ) )
1466  {
1467  // incorrect password
1468  receipt.result_code = 1;
1469  }
1470  else
1471  {
1472  receipt.result_code = 0;
1473  }
1474  }
1475  else
1476  {
1477  // driver ID not found
1478  receipt.result_code = 1;
1479  }
1480 
1481  txFmi( FMI_DRIVER_LOGIN_RESPONSE, (uint8*)&receipt, sizeof( receipt ) );
1482  break;
1483  }
1485  {
1487  memset( &data, 0, sizeof( data ) );
1488  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1489 
1490 #if( FMI_SUPPORT_A615 )
1491  if( NULL != strstr( mProtocols, "A615" ) )
1492  {
1494  break;
1495  }
1496 #endif
1497  char temp[256];
1498 
1500  memset( &receipt, 0, sizeof( receipt ) );
1501 
1502  if( 0 == strlen( data.driver_id ) )
1503  {
1504  //invalid request
1505  receipt.result_code = 1;
1506  }
1507  else if( mAOBRDDrivers.contains( data.driver_id ) )
1508  {
1509  AobrdDriverItem & driver = mAOBRDDrivers.get( data.driver_id );
1510 
1511  WideCharToMultiByte( mClientCodepage, 0, driver.getFirstName().GetBuffer(), -1, temp, 35, NULL, NULL );
1512  temp[34] = '\0';
1513  strcpy( receipt.first_name, temp );
1514 
1515  WideCharToMultiByte( mClientCodepage, 0, driver.getLastName().GetBuffer(), -1, temp, 35, NULL, NULL );
1516  temp[34] = '\0';
1517  strcpy( receipt.last_name, temp );
1518 
1519  strncpy( receipt.driver_id, data.driver_id, cnt_of_array( receipt.driver_id ) - 1 );
1520 
1521  WideCharToMultiByte( mClientCodepage, 0, driver.getCarrierName().GetBuffer(), -1, temp, 120, NULL, NULL );
1522  temp[119] = '\0';
1523  strcpy( receipt.carrier_name, temp );
1524 
1525  WideCharToMultiByte( mClientCodepage, 0, driver.getCarrierID().GetBuffer(), -1, temp, 8, NULL, NULL );
1526  temp[7] = '\0';
1527  strcpy( receipt.carrier_id, temp );
1528 
1529  receipt.long_term_rule_set = (uint8) driver.getLongTermRuleset();
1530  receipt.time_zone = (uint8) driver.getTimeZone();
1531  receipt.status = 0;
1532  receipt.result_code = 0;
1533  }
1534  else
1535  {
1536  // driver ID not found
1537  receipt.result_code = 1;
1538  }
1539 
1540  txFmi( FMI_DRIVER_PROFILE_DOWNLOAD_RESPONSE, (uint8*)&receipt, sizeof( receipt ) );
1541 
1542  break;
1543  }
1544  case FMI_DRIVER_STATUS_UPDATE_REQUEST: //0X1106
1545  {
1546  //decode driver ID
1548  memset( &data, 0, sizeof( data ) );
1549  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1550 
1552  memset( &receipt, 0, sizeof( receipt ) );
1553  strcpy( receipt.driver_id, data.driver_id );
1554 
1555  char file[MAX_PATH];
1556  sprintf( file, SAVE_CONVERTED_AOBRD_LOG, data.driver_id );
1557  fstream open_file( file, ios_base::binary | ios_base::in );
1558  if( open_file.good() )
1559  {
1560  open_file.close();
1561 
1562  //tell device that a file will be transmitted
1563  receipt.result_code = 0;
1564  txFmi( FMI_DRIVER_STATUS_UPDATE_RESPONSE, (uint8*)&receipt, sizeof( receipt ) );
1565 
1566  //convert and transmit file
1567  AobrdEventLogConverter converter;
1568  if( 0 < converter.convertToRaw( file, SAVE_AOBRD_LOG ) )
1569  {
1570  strcpy( file, SAVE_AOBRD_LOG );
1571 
1572  uint8 version[16];
1573  uint8 versionLength = (uint8)UTIL_hex_to_uint8( "00", version, 16 );
1574  sendFile( file, versionLength, version, (uint8)FMI_FILE_TYPE_AOBRD );
1575  }
1576  else
1577  {
1578  //tell device that there is no file because there is no content
1579  receipt.result_code = 1;
1580  txFmi( FMI_DRIVER_STATUS_UPDATE_RESPONSE, (uint8*)&receipt, sizeof( receipt ) );
1581  }
1582  }
1583  else
1584  {
1585  //tell device that there is no file
1586  receipt.result_code = 1;
1587  txFmi( FMI_DRIVER_STATUS_UPDATE_RESPONSE, (uint8*)&receipt, sizeof( receipt ) );
1588  }
1589 
1590  break;
1591  }
1592  case FMI_DRIVER_STATUS_UPDATE_RECEIPT: //0X1108
1593  {
1594  //there is no reaction to a positive or negative result here
1595  break;
1596  }
1597  case FMI_DOWNLOAD_SHIPMENTS_REQUEST: //0X1109
1598  {
1600  memset( &data, 0, sizeof( data ) );
1601  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1602 
1604  memset( &receipt, 0, sizeof( receipt ) );
1605  if( ( 0 == strlen( data.driver_id ) ) || !mAOBRDDrivers.contains( data.driver_id ) )
1606  {
1607  //invalid request
1609  strncpy( receipt.driver_id, data.driver_id, cnt_of_array( receipt.driver_id ) - 1 );
1610  txFmi( FMI_SHIPMENT_DOWNLOAD_RESPONSE, (uint8*)&receipt, sizeof( receipt ) );
1611  }
1612  else
1613  {
1614  AobrdDriverItem & driver = mAOBRDDrivers.get( data.driver_id );
1615  if( driver.getShipments().size() == 0 )
1616  {
1617  receipt.server_result_code = EMPTY_DATA;
1618  strncpy( receipt.driver_id, data.driver_id, cnt_of_array( receipt.driver_id ) - 1 );
1619  txFmi( FMI_SHIPMENT_DOWNLOAD_RESPONSE, (uint8*)&receipt, sizeof( receipt ) );
1620  }
1621  else
1622  {
1625  mAOBRDStopShipmentTxIndex = (int) driver.getShipments().size();
1627  }
1628  }
1629  break;
1630  }
1631  case FMI_SHIPMENT_DOWNLOAD_RECEIPT: //0X110B
1632  {
1634  memset( &data, 0, sizeof( data ) );
1635  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1636 
1637  if( FMI_LOGIN_NO_ERRORS == data.result_code )
1638  {
1640  }
1641  break;
1642  }
1643  case FMI_ANNOTATION_DOWNLOAD_REQUEST: //0X110D
1644  {
1646  memset( &data, 0, sizeof( data ) );
1647  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1648 
1650  memset( &record, 0, sizeof( record ) );
1651  strncpy( record.driver_id, data.driver_id, cnt_of_array( record.driver_id ) - 1 );
1652 
1653  if( ( 0 == strlen( data.driver_id ) ) || !mAOBRDDrivers.contains( data.driver_id ) )
1654  {
1655  //invalid request
1657  txFmi( FMI_ANNOTATION_DOWNLOAD_RESPONSE, (uint8*)&record, sizeof( record ) );
1658  }
1659  else
1660  {
1661  AobrdEventLogConverter aobrdLogFile;
1662  char source[_MAX_PATH];
1663  sprintf( source, SAVE_CONVERTED_AOBRD_LOG, record.driver_id );
1665 
1666  if( 0 == mAOBRDStopAnnotationTxIndex )
1667  {
1668  record.server_result_code = EMPTY_DATA;
1669  txFmi( FMI_ANNOTATION_DOWNLOAD_RESPONSE, (uint8*)&record, sizeof( record ) );
1670  }
1671  else
1672  {
1676  }
1677  }
1678  break;
1679  }
1680  case FMI_ANNOTATION_DOWNLOAD_RECEIPT: //0X110F
1681  {
1683  memset( &data, 0, sizeof( data ) );
1684  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1685 
1686  if( FMI_LOGIN_NO_ERRORS == data.result_code )
1687  {
1689  }
1690  break;
1691  }
1692 #endif //FMI_SUPPORT_A610
1693 #if FMI_SUPPORT_A612
1694  case FMI_CUSTOM_FORM_DEL_RECEIPT: //0X1201
1695  {
1697  memset( &data, 0, sizeof( data ) );
1698  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1699 
1700  if ( 0 == data.return_code )
1701  {
1702  // dispatch form deleted event
1704  }
1705  break;
1706  }
1707  case FMI_CUSTOM_FORM_MOVE_RECEIPT: //0X1203
1708  case FMI_CUSTOM_FORM_GET_POS_RECEIPT: //0X1205
1709  {
1711  memset( &data, 0, sizeof( data ) );
1712  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1713 
1714  if ( 0 == data.return_code )
1715  {
1716  // dispatch form position changed event
1718  }
1719  break;
1720  }
1721 #if FMI_SUPPORT_A621
1722  case FMI_CUSTOM_FORM_SHOW_RECEIPT: //0X01207
1723  {
1725  memset( &data, 0, sizeof( data ) );
1726  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1727 
1728  if ( 0 == data.return_code )
1729  {
1730  // dispatch form show success event
1732  }
1733  else
1734  {
1736  }
1737  break;
1738  }
1739 #endif //FMI_SUPPORT_A621
1740 #endif //FMI_SUPPORT_A612
1741 #if( FMI_SUPPORT_A614 )
1742  case FMI_STOP_CALC_ACK_REQUEST: //0X1220
1743  {
1744  stop_calc_ack_type data;
1745  memset( &data, 0, sizeof( data ) );
1746  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1747 
1748  stop_calc_ack_rcpt_type receipt;
1749  memset( &receipt, 0, sizeof( receipt ) );
1750  receipt.unique_id = data.unique_id;
1751  uint8 receiptSize = sizeof( receipt );
1752  txFmi( FMI_STOP_CALC_ACK_RECEIPT, (uint8*)&receipt, receiptSize );
1753 
1754  if ( 0 == data.result_code )
1755  {
1756  Event::post( EVENT_FMI_ROUTE_CALCULATED, data.unique_id, ( void * ) data.distance );
1757  }
1758  break;
1759  }
1760 #endif //FMI_SUPPORT_A614
1761 #if( FMI_SUPPORT_A616 )
1762  case FMI_SET_BAUD_RECEIPT: //0X0012
1763  {
1764  fmi_set_baud_receipt data;
1765  memset( &data, 0, sizeof( data ) );
1766  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1767 
1768  if( FMI_BAUD_RATE_OK == data.result_code )
1769  {
1770  switch( data.request_type )
1771  {
1773  {
1774  fmi_set_baud_request sync;
1775  memset( &sync, 0, sizeof( sync ) );
1776  sync.baud_rate_type = data.baud_rate_type;
1778 
1779  switch( data.baud_rate_type )
1780  {
1781  case FMI_BAUD_RATE_9600:
1782  {
1783  Sleep( 100 ); //give the device enough time to finish communicating
1785  txFmi( FMI_SET_BAUD_REQUEST, ( uint8* )&sync, sizeof( sync ), true );
1788  break;
1789  }
1790  case FMI_BAUD_RATE_38400:
1791  {
1792  Sleep( 100 ); //give the device enough time to finish communicating
1794  txFmi( FMI_SET_BAUD_REQUEST, ( uint8* )&sync, sizeof( sync ), true );
1797  break;
1798  }
1799  case FMI_BAUD_RATE_57600:
1800  {
1801  Sleep( 100 ); //give the device enough time to finish communicating
1803  txFmi( FMI_SET_BAUD_REQUEST, ( uint8* )&sync, sizeof( sync ), true );
1806  break;
1807  }
1808  }
1809  break;
1810  }
1812  {
1815  break;
1816  }
1817  }
1818  }
1819 
1820  break;
1821  }
1822 #endif //FMI_SUPPORT_A616
1823 #if FMI_SUPPORT_A622
1824  case FMI_DASHCAM_SETTINGS_LOCK_RECEIPT: //0X1601
1825  {
1827  memset( &data, 0, sizeof( data ) );
1828  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1829 
1831 
1832  break;
1833  }
1834  case FMI_DASHCAM_CONFIG_RECEIPT: //0X1603
1835  {
1837  memset( &data, 0, sizeof( data ) );
1838  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1839 
1841 
1842  break;
1843  }
1844  case FMI_DASHCAM_GET_SETTINGS_RESPONSE: //0X1605
1845  {
1847  memset( &data, 0, sizeof( data ) );
1848  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1849 
1851 
1853 
1854  break;
1855  }
1856  case FMI_DASHCAM_SET_NTFCTN_RECEIPT: //0X1607
1857  {
1859  memset( &data, 0, sizeof( data ) );
1860  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1861 
1863 
1864  break;
1865  }
1867  {
1869  memset( &data, 0, sizeof( data ) );
1870  memcpy( &data, fmiPayload, minval( sizeof( data ), fmiPayloadSize ) );
1871 
1873 
1875 
1876  break;
1877  }
1878  case FMI_DASHCAM_NTFCTN_REQUEST: //0X160A
1879  {
1880  fmi_dashcam_ntfctn_req_data_type incident_info;
1883  eventData->scposn.lat = INVALID_LAT;
1884 
1885  memset( &incident_info, 0, sizeof( incident_info ) );
1886  memcpy( &incident_info, fmiPayload, minval( sizeof( incident_info ), fmiPayloadSize ) );
1887 
1888  receipt.change_id = incident_info.origination_time;
1889  txFmi( FMI_DASHCAM_NTFCTN_RECEIPT, (uint8*)&receipt, sizeof( receipt ) );
1890 
1891  eventData->origination_time = incident_info.origination_time;
1892  eventData->ntfctn_type = incident_info.ntfctn_type;
1893  eventData->scposn.lat = incident_info.scposn.lat;
1894  eventData->scposn.lon = incident_info.scposn.lon;
1895 
1896  Event::post( EVENT_FMI_DASHCAM_NTFCTN, 0, eventData );
1897  break;
1898  }
1900  {
1903 
1904  memset( eventData, 0, sizeof( fmi_dashcam_ntfctn_incident_req_data_type ) );
1905  memcpy( eventData, fmiPayload, minval( sizeof( fmi_dashcam_ntfctn_incident_req_data_type ), fmiPayloadSize ) );
1906 
1907  receipt.change_id = eventData->origination_time;
1908  txFmi( FMI_DASHCAM_INCDNT_FILE_NTFCTN_RECEIPT, (uint8*)&receipt, sizeof( receipt ) );
1909 
1911  break;
1912  }
1913 #endif //FMI_SUPPORT_A622
1914 #if FMI_SUPPORT_A623
1915  case FMI_ID_ETA_MODE_RCPT: //0X0204
1916  {
1918  memset( &receipt, 0, sizeof( receipt ) );
1919  memcpy( &receipt, fmiPayload, minval( sizeof( receipt ), fmiPayloadSize ) );
1920 
1921  if( receipt.return_code == FMI_ETA_SETTING_SUCCESS )
1922  {
1923  mEtaMode = receipt.new_setting;
1924  }
1925 
1926  // notify user interface
1928 
1929  break;
1930  }
1931 #endif //FMI_SUPPORT_A623
1932 
1933  default:
1934  break;
1935  } //end of switch( fmiPacketId )
1936  break;
1937  } // end of case ID_FMI_PACKET
1938 #endif // FMI_SUPPORT_A602
1939  default:
1940  break;
1941  } // end of switch( rx_packet->id )
1942 
1943  return true;
1944 } // end of FmiApplicationLayer::rx()
1945 
1946 
1947 //----------------------------------------------------------------------
1952 //----------------------------------------------------------------------
1954  (
1955  const Packet * aPacket
1956  )
1957 {
1958  const GarminPacket* packet = dynamic_cast<const GarminPacket*>( aPacket );
1959 
1960  ASSERT( packet != NULL );
1961 
1962 #if( FMI_SUPPORT_A602 )
1963  switch( packet->mPacketId )
1964  {
1965  case ID_FMI_PACKET:
1966 #if( FMI_SUPPORT_A615 )
1967  case ID_HOSART_PACKET:
1968 #endif
1969  {
1970  fmi_id_type fmiPacketId = *(fmi_id_type *) packet->mPayload;
1971 #if( FMI_SUPPORT_A604 )
1972  const uint8* fmiPayload = packet->mPayload + sizeof( fmi_id_type );
1973 #endif
1974  switch( fmiPacketId )
1975  {
1976  case FMI_ID_ENABLE:
1977  mEnablePending = false;
1978  break;
1979 #if( FMI_SUPPORT_A604 )
1980  case FMI_ID_DATA_DELETION:
1981  {
1982  const data_deletion_data_type *delData = (const data_deletion_data_type *)fmiPayload;
1983  if( delData->data_type == DISABLE_FMI )
1984  {
1986  }
1987  }
1988  break;
1989 #endif
1990  default:
1991  break;
1992  }
1993  break;
1994  }
1995  default:
1996  break;
1997  }
1998 #endif
1999 }
2000 
2001 //----------------------------------------------------------------------
2005 //----------------------------------------------------------------------
2007  (
2008  bool aEnable
2009  )
2010 {
2011  if( aEnable )
2012  {
2014  }
2015  else
2016  {
2018  }
2019 }
2020 
2021 #if( FMI_SUPPORT_LEGACY )
2022 //----------------------------------------------------------------------
2029 //----------------------------------------------------------------------
2030 void FmiApplicationLayer::sendLegacyProductRequest()
2031 {
2032  ASSERT( mTransportLayer != NULL );
2033 
2034  mTransportLayer->tx( new GarminPacket( ID_PRODUCT_RQST, NULL, 0, this ), TRUE );
2035 }
2036 
2037 //----------------------------------------------------------------------
2047 //----------------------------------------------------------------------
2048 void FmiApplicationLayer::sendLegacyStop
2049  (
2050  double aDegreesLatitude,
2051  double aDegreesLongitude,
2052  char * aStopName
2053  )
2054 {
2055  legacy_stop_data_type stopPacket;
2056  uint8 payloadSize;
2057  sc_position_type stopPosition;
2058 
2059  memset( &stopPacket, 0, sizeof( stopPacket ) );
2060 
2061  _snprintf( stopPacket.text,
2062  sizeof( stopPacket.text ), aStopName );
2063 
2064  stopPosition.lat = UTIL_convert_degrees_to_semicircles( aDegreesLatitude );
2065  stopPosition.lon = UTIL_convert_degrees_to_semicircles( aDegreesLongitude );
2066 
2067  stopPacket.stop_position = stopPosition;
2068 
2069  payloadSize = offset_of( legacy_stop_data_type, text ) + (uint8)strlen( stopPacket.text ) + 1;
2070 
2071  ASSERT( mTransportLayer != NULL );
2072  mTransportLayer->tx( new GarminPacket( ID_LEGACY_STOP_MSG, (uint8*) &stopPacket, payloadSize, this ), FALSE );
2073 }
2074 
2075 //----------------------------------------------------------------------
2079 //----------------------------------------------------------------------
2080 void FmiApplicationLayer::sendLegacyTextMessage
2081  (
2082  char * aMessageText
2083  )
2084 {
2085  ASSERT( mTransportLayer != NULL );
2086 
2087  uint8 payloadSize = minval( 200, strlen( aMessageText ) + 1);
2088 
2089  mTransportLayer->tx( new GarminPacket( ID_LEGACY_TEXT_MSG, (uint8*) aMessageText, payloadSize, this ), FALSE );
2090 }
2091 #endif
2092 
2093 //----------------------------------------------------------------------
2095 //----------------------------------------------------------------------
2097 {
2099 }
2100 
2101 //----------------------------------------------------------------------
2105 //----------------------------------------------------------------------
2107 {
2108  ASSERT( mTransportLayer != NULL );
2110 }
2111 
2112 #if( FMI_SUPPORT_A602 )
2113 //----------------------------------------------------------------------
2124 //----------------------------------------------------------------------
2126  (
2127  double aDegreesLatitude,
2128  double aDegreesLongitude,
2129  char * aStopName
2130  )
2131 {
2132  A602_stop_data_type stopData;
2133  uint8 stopPayloadSize;
2134  sc_position_type position;
2135 
2136  memset( &stopData, 0, sizeof( stopData ) );
2137 
2138  _snprintf( stopData.text,
2139  sizeof( stopData.text ), aStopName );
2140 
2141  position.lat = UTIL_convert_degrees_to_semicircles( aDegreesLatitude );
2142  position.lon = UTIL_convert_degrees_to_semicircles( aDegreesLongitude );
2143 
2144  stopData.stop_position = position;
2145 
2146  time_type originationTime = UTIL_get_current_garmin_time();
2147  stopData.origination_time = originationTime;
2148  stopPayloadSize = offset_of( A602_stop_data_type, text ) + (uint8)strlen( stopData.text ) + 1;
2149 
2150  txFmi( FMI_ID_A602_STOP, (uint8*)&stopData, stopPayloadSize );
2151 }
2152 
2153 //----------------------------------------------------------------------
2165 //----------------------------------------------------------------------
2167  (
2168  fmi_id_type aFmiPacketId,
2169  char * aMessageText,
2170  const MessageId & aMessageId
2171  )
2172 {
2173  uint8 payloadSize;
2174 
2175  //all messages need a originationTime, so calculate it now
2176  time_type originationTime = UTIL_get_current_garmin_time();
2177 
2178  if( aFmiPacketId == FMI_ID_SERVER_OPEN_TXT_MSG )
2179  {
2181  memset( &textMessage, 0, sizeof( textMessage ) );
2182  textMessage.origination_time = originationTime;
2183  _snprintf
2184  (
2185  textMessage.text_message,
2186  sizeof( textMessage.text_message ),
2187  aMessageText
2188  );
2189  payloadSize = offset_of( A602_server_to_client_open_text_msg_data_type, text_message )
2190  + (uint8)strlen( textMessage.text_message )
2191  + 1;
2192  txFmi( aFmiPacketId, (uint8*)&textMessage, payloadSize );
2193  }
2194  else
2195  {
2197  memset( &textMessage, 0, sizeof( textMessage ) );
2198  textMessage.origination_time = originationTime;
2199  textMessage.id_size = aMessageId.getIdSize();
2200  memmove( textMessage.id, aMessageId.getId(), textMessage.id_size );
2201  _snprintf
2202  (
2203  textMessage.text_message,
2204  sizeof( textMessage.text_message ),
2205  aMessageText
2206  );
2207  payloadSize = offset_of( server_to_client_ack_text_msg_data_type, text_message )
2208  + (uint8)strlen( textMessage.text_message )
2209  + 1;
2210  txFmi( aFmiPacketId, (uint8*)&textMessage, payloadSize );
2211  }
2212 }
2213 
2214 //----------------------------------------------------------------------
2223 //----------------------------------------------------------------------
2225  (
2226  uint16 * aFeatureCodes,
2227  uint8 aFeatureCount
2228  )
2229 {
2230  fmi_features_data_type features;
2231  uint8 dataSize;
2232 
2233  if( aFeatureCount > 126 )
2234  {
2235  aFeatureCount = 126;
2236  }
2237 
2238  features.feature_count = aFeatureCount;
2239  features.reserved = 0;
2240  memset( features.features, 0, 126*sizeof( uint16 ) );
2241  memcpy( features.features, aFeatureCodes, aFeatureCount * sizeof( uint16 ) );
2242 
2243  dataSize = offset_of( fmi_features_data_type, features )
2244  + sizeof( uint16 ) * features.feature_count;
2245 
2246  if( mEnablePending )
2247  {
2248  ASSERT( mTransportLayer != NULL );
2250  }
2251  else
2252  {
2253  txFmi( FMI_ID_ENABLE, (uint8*)&features, dataSize, TRUE );
2254  }
2255 
2256  mEnablePending = true;
2257 }
2258 
2259 //----------------------------------------------------------------------
2269 //----------------------------------------------------------------------
2271  (
2272  uint16 aFmiPacketId,
2273  uint8* aFmiPayload,
2274  uint8 aFmiPayloadSize
2275  )
2276 {
2277  txFmi( aFmiPacketId, aFmiPayload, aFmiPayloadSize );
2278 }
2279 
2281  (
2282  fmi_id_type const aFmiPacketId,
2283  uint8 const * const aFmiPayload,
2284  uint8 const aFmiPayloadSize
2285  )
2286 {
2287  uint8 payloadSize;
2288  id_type freeformPacketId;
2289  fmi_id_type fmiPacketId;
2290  uint8 buffer[ MAX_PAYLOAD_SIZE ];
2291 
2292  payloadSize = aFmiPayloadSize;
2293  freeformPacketId = mFreeformFmiPacketId;
2294 #if( FMI_SUPPORT_A615 )
2295  if( mFreeformFmiPacketId == ID_HOSART_PACKET && aFmiPacketId == 0xDEAD )
2296  {
2297  freeformPacketId = ID_SET_TIME_PACKET;
2298  // don't send sub-packet ID for set time
2299  memcpy( &buffer[ 0 ], aFmiPayload, aFmiPayloadSize );
2300  }
2301  else
2302 #endif
2303  {
2304  payloadSize += sizeof( fmiPacketId );
2305  fmiPacketId = aFmiPacketId;
2306  memcpy( &buffer[ 0 ], &fmiPacketId, sizeof( fmiPacketId ) );
2307  memcpy( &buffer[ sizeof( fmiPacketId ) ], aFmiPayload, aFmiPayloadSize );
2308  }
2309 
2310  ASSERT( mTransportLayer != NULL );
2311  mTransportLayer->tx( new GarminPacket( freeformPacketId, buffer, payloadSize, this ), true );
2312 }
2313 //----------------------------------------------------------------------
2316 //----------------------------------------------------------------------
2318 {
2320 }
2321 #endif
2322 
2323 #if( FMI_SUPPORT_A603 )
2324 //----------------------------------------------------------------------
2328 //----------------------------------------------------------------------
2330 {
2331  uint32 uniqueId = 1;
2332 
2333  if( !mA603Stops.empty() )
2334  {
2335  //loop through the map and find an id hole
2337  for(; iter != mA603Stops.end(); iter++ )
2338  {
2339  if( iter->first != uniqueId ) //found a hole!
2340  {
2341  uniqueId = iter->first - 1; //leave the biggest hole so next
2342  break; //search can possibly be as fast (unless only one spot)
2343  }
2344  else
2345  uniqueId = iter->first + 1; //no hole yet, so use the next ID (maybe)
2346  }
2347  }
2348 
2349  ASSERT( !mA603Stops.contains( uniqueId ) );
2350 
2351  return uniqueId;
2352 }
2353 
2354 //----------------------------------------------------------------------
2362 //----------------------------------------------------------------------
2364  (
2365  uint32 aUniqueId
2366  )
2367 {
2368  for( uint16 i = 0; i < mStopIndexInList.size(); i++ )
2369  {
2370  if( mStopIndexInList[i] == aUniqueId )
2371  {
2372  removeStopByIndex( i );
2373  }
2374  }
2375 }
2376 
2377 //----------------------------------------------------------------------
2385 //----------------------------------------------------------------------
2387  (
2388  uint16 aStopIndex
2389  )
2390 {
2391  int i = 0;
2392  int size = (int)mStopIndexInList.size();
2393  mA603Stops.remove( mStopIndexInList[aStopIndex] );
2394  if( mA603Stops.empty() )
2395  {
2396  mStopIndexInList.clear();
2397  }
2398  else
2399  {
2400  //stops below the deleted stop need to be shifted up
2401  //check to make sure this isn't the last stop in the list
2402  if( aStopIndex + 1 < size )
2403  {
2404  //get id after deleted stop
2405  uint32 id = mStopIndexInList[aStopIndex + 1];
2406  while( id != INVALID32 )
2407  {
2408  //next index replaces previous index
2409  mStopIndexInList[aStopIndex + i] = id;
2410  i++;
2411  //get next id to replace
2412  if( aStopIndex + i + 1 < size )
2413  id = mStopIndexInList[aStopIndex + i + 1];
2414  else
2415  break; //if we are over running the vector we are done
2416  }
2417  //mark whatever was the last index as invalid (one less now)
2418  mStopIndexInList[aStopIndex + i] = INVALID32;
2419  }
2420  else
2421  {
2422  mStopIndexInList[aStopIndex] = INVALID32; //deleting last stop so nothing
2423  } //else needs to be done
2424  }
2425 }
2426 //----------------------------------------------------------------------
2434 //----------------------------------------------------------------------
2436  (
2437  double aLatitude,
2438  double aLongitude,
2439  char * aStopName,
2440  uint32 aStopId
2441  )
2442 {
2443  A603_stop_data_type stopData;
2444  uint8 stopPayloadSize;
2445  sc_position_type position;
2446  wofstream stopFile;
2447  TCHAR stopNameWide[200];
2448 
2449  memset( &stopData, 0, sizeof( stopData ) );
2450 
2451  _snprintf
2452  (
2453  stopData.text,
2454  minval( sizeof( stopData.text ) - 1, strlen( aStopName ) ),
2455  aStopName
2456  );
2457  //has to be null terminated
2458 
2459  position.lat = aLatitude;
2460  position.lon = aLongitude;
2461 
2462  stopData.stop_position = position;
2463  stopData.unique_id = aStopId;
2464 
2465  //update map
2466  StopListItem& stopListItem = mA603Stops.get( aStopId );
2467  MultiByteToWideChar( mClientCodepage, 0, stopData.text, -1, stopNameWide, 200 );
2468  stopListItem.setCurrentName( stopNameWide );
2469  stopListItem.setStopStatus( STOP_STATUS_UNREAD );
2470  stopListItem.setValid();
2471  mA603Stops.put( stopListItem );
2472 
2474  stopPayloadSize = offset_of( A603_stop_data_type, text )
2475  + (uint8)strlen( stopData.text )
2476  + 1;
2477  txFmi( FMI_ID_A603_STOP, (uint8*)&stopData, stopPayloadSize );
2478 }
2479 
2480 //----------------------------------------------------------------------
2485 //----------------------------------------------------------------------
2487  (
2488  uint32 aAutoArrivalTime,
2489  uint32 aAutoArrivalDistance
2490  )
2491 {
2492  auto_arrival_data_type autoArrival;
2493  autoArrival.stop_distance = aAutoArrivalDistance;
2494  autoArrival.stop_time = aAutoArrivalTime;
2495  txFmi( FMI_ID_AUTO_ARRIVAL, (uint8*)&autoArrival, sizeof( autoArrival ) );
2496 }
2497 
2498 #if( FMI_SUPPORT_A606 )
2499 //---------------------------------------------------------------------
2505 //---------------------------------------------------------------------
2507  (
2508  float aSpeed
2509  )
2510 {
2511  uint8 data_size;
2513  memset( &data, 0, sizeof( data ) );
2514 
2515  data.speed = aSpeed;
2516 
2517  data_size = sizeof( aSpeed );
2518  txFmi( FMI_SAFE_MODE,(uint8*)&data, data_size );
2519 }
2520 #endif
2521 
2522 //----------------------------------------------------------------------
2527 //----------------------------------------------------------------------
2529  (
2530  del_data aDelDataType
2531  )
2532 {
2533  // Perform the data deletion protocol
2535  data.data_type = aDelDataType;
2536  txFmi( FMI_ID_DATA_DELETION, (uint8*)&aDelDataType, sizeof( data ) );
2537 
2538  // Based on the requested data type, reset the server-side data
2539  switch( aDelDataType )
2540  {
2541 #if FMI_SUPPORT_A603
2542  case DELETE_ALL_STOPS:
2543  resetSavedStops();
2544  break;
2545 #endif
2546 
2547 #if FMI_SUPPORT_A604
2548  case DELETE_ALL_MESSAGES:
2550  break;
2551 
2554  break;
2555 
2558  break;
2559 
2562  break;
2563 
2564  case DISABLE_FMI:
2568  resetSavedStops();
2569 #if( FMI_SUPPORT_A607 )
2570  resetWaypoints();
2571 #endif
2572  break;
2573 #endif
2574 
2575 #if( FMI_SUPPORT_A607 )
2576  case DELETE_WAYPOINTS:
2577  resetWaypoints();
2578  break;
2579 #endif
2580 
2581  }
2582 }
2583 
2584 //----------------------------------------------------------------------
2587 //----------------------------------------------------------------------
2589 {
2590  txFmi( FMI_ID_ETA_DATA_REQUEST, NULL, 0 );
2591 }
2592 
2593 //----------------------------------------------------------------------
2596 //----------------------------------------------------------------------
2598  (
2599  FMI_eta_mode_type aModeType
2600  )
2601 {
2602  // Perform the ETA Mode request protocol
2603  txFmi( FMI_ID_ETA_MODE_REQUEST, (uint8*)&aModeType, sizeof( aModeType ) );
2604 }
2605 
2606 //----------------------------------------------------------------------
2611 //----------------------------------------------------------------------
2613  (
2614  uint16 aMoveToIndex,
2615  uint16 aMoveFromIndex
2616  )
2617 {
2618  uint32 moveToId;
2619  uint32 stopId;
2620 
2621  //starting out with stopId the stop that is being moved
2622  //and moveToId the stop at the index it will be moved to
2623  moveToId = mStopIndexInList[aMoveToIndex];
2624  stopId = mStopIndexInList[aMoveFromIndex];
2625  sendStopStatusRequest( stopId, REQUEST_MOVE_STOP, aMoveToIndex );
2626 
2627  // The client will not send stop aStopStatus updates (with the new
2628  // list index) under at least two known conditions:
2629  // 1. The stop aStopStatus protocol is throttled.
2630  // 2. The client software is older. (Prior to A604, clients only
2631  // send a stop aStopStatus for the stop indicated in the request, but
2632  // not for the other stops that were moved to make room.)
2633  // So, we need to update the position of all affected stops now.
2634  if( aMoveFromIndex < aMoveToIndex )
2635  {
2636  //moving down, so move and shift others up
2637  //starting at aMoveToIndex - i (where to move the selected stop)
2638  //and then moving up a position for each stop affected
2639  for( int i = 0; i <= aMoveToIndex - aMoveFromIndex; i++ )
2640  {
2641  mStopIndexInList[aMoveToIndex-i] = stopId;
2642  stopId = moveToId;
2643  if( i != aMoveToIndex - aMoveFromIndex )
2644  moveToId = mStopIndexInList[aMoveToIndex - i - 1];
2645  }
2646  }
2647  else if( aMoveToIndex < aMoveFromIndex )
2648  //move up, so move and shift others down
2649  //starting at aMoveToIndex + i (where to move the selected stop)
2650  //and then moving down a position for each stop affected
2651  {
2652  for( int i = 0; i <= aMoveFromIndex - aMoveToIndex; i++ )
2653  {
2654  mStopIndexInList[aMoveToIndex + i] = stopId;
2655  stopId = moveToId;
2656  if( i != aMoveFromIndex - aMoveToIndex )
2657  moveToId = mStopIndexInList[aMoveToIndex + i + 1];
2658  }
2659  }
2660 }
2661 
2662 //----------------------------------------------------------------------
2669 //----------------------------------------------------------------------
2671  (
2672  uint32 aStopId,
2673  stop_status_status_type aStopStatus,
2674  uint16 aMoveToIndex
2675  )
2676 {
2677  stop_status_data_type stopData;
2678  stopData.unique_id = aStopId;
2679  stopData.stop_status = aStopStatus;
2680  switch( aStopStatus )
2681  {
2682  //these 4 all do require stop index to be INVALID16
2683  case REQUEST_STOP_STATUS:
2685  case REQUEST_ACTIVATE_STOP:
2686  case REQUEST_DELETE_STOP:
2687  stopData.stop_index_in_list = INVALID16;
2688  break;
2689  case REQUEST_MOVE_STOP:
2690  stopData.stop_index_in_list = aMoveToIndex;
2691  break;
2692  default:
2693  ASSERT( false ); // probably a bug if control ever gets to here
2694  break;
2695  }
2696  txFmi( FMI_ID_STOP_STATUS_REQUEST, (uint8*) &stopData, sizeof( stopData ) );
2697 }
2698 
2699 #endif
2700 
2701 #if( FMI_SUPPORT_A611 )
2702 //----------------------------------------------------------------------
2713 //----------------------------------------------------------------------
2715  (
2716  const char * aMessageText,
2717  const MessageId & aMessageId,
2718  uint8 aMessageType
2719  )
2720 {
2722  {
2723  return false;
2724  }
2725 
2726  beginA611LongTextMessage(aMessageText, aMessageId, aMessageType);
2727  return true;
2728 }
2729 
2730 //----------------------------------------------------------------------
2742 //----------------------------------------------------------------------
2744  (
2745  const char * aMessageText,
2746  const MessageId & aMessageId,
2747  uint8 aMessageType
2748  )
2749 {
2750  // all messages need a origination time, so calculate it now
2751  time_type originationTime = UTIL_get_current_garmin_time();
2752 
2753  uint8 i;
2754  uint32 position;
2755  uint32 length = (uint32) strlen(aMessageText);
2756 
2757  for( i=0, position=0; position < length; i++, position += LONG_TEXT_MSG_CHUNK_SIZE )
2758  {
2759  uint8 textLength = (uint8) min( sizeof( mLongTextMessage[i].text_message ), length - position + 1 );
2760  memset( mLongTextMessage+i, 0, sizeof( mLongTextMessage[i] ) );
2761 
2762  mLongTextMessage[i].origination_time = originationTime;
2763  mLongTextMessage[i].id_size = aMessageId.getIdSize();
2764  mLongTextMessage[i].type = aMessageType;
2765  mLongTextMessage[i].finished_flag = position + LONG_TEXT_MSG_CHUNK_SIZE > length;
2767  memmove( mLongTextMessage[i].id, aMessageId.getId(), aMessageId.getIdSize() );
2768  memmove( mLongTextMessage[i].text_message, aMessageText + position, textLength );
2769 
2770  mLongTextMessagePayloadSize[i] = offset_of( long_text_msg_data_type, text_message ) + textLength;
2771  }
2772 
2775 }
2776 
2777 #endif
2778 
2779 #if( FMI_SUPPORT_A604 )
2780 //----------------------------------------------------------------------
2790 //----------------------------------------------------------------------
2792  (
2793  const char * aMessageText,
2794  const MessageId & aMessageId,
2795  uint8 aMessageType
2796  )
2797 {
2798  uint8 payloadSize;
2799 
2800  // all messages need a origination time, so calculate it now
2801  time_type originationTime = UTIL_get_current_garmin_time();
2802 
2804  memset( &textMessage, 0, sizeof( textMessage ) );
2805  textMessage.origination_time = originationTime;
2806  textMessage.id_size = aMessageId.getIdSize();
2807  memmove( textMessage.id, aMessageId.getId(), aMessageId.getIdSize() );
2808  _snprintf( textMessage.text_message, sizeof( textMessage.text_message ), aMessageText );
2809  payloadSize = offset_of( A604_server_to_client_open_text_msg_data_type, text_message )
2810  + (uint8)strlen( textMessage.text_message )
2811  + 1;
2812  textMessage.message_type = aMessageType;
2813  txFmi( FMI_ID_A604_OPEN_TEXT_MSG, (uint8*)&textMessage, payloadSize );
2814 }
2815 //----------------------------------------------------------------------
2832 //----------------------------------------------------------------------
2834  (
2835  const char * aMessageText,
2836  const MessageId & aMessageId,
2837  uint8 aResponseCount,
2838  const uint32 * aResponseList,
2839  uint8 aMessageType
2840  )
2841 {
2842  uint8 payloadSize;
2844 
2845 #if( FMI_SUPPORT_A611 )
2846  if( strlen( aMessageText ) > LONG_TEXT_MSG_CHUNK_SIZE - 1 )
2847  {
2849  {
2850  return false;
2851  }
2852  else
2853  {
2855  }
2856  }
2857 #endif
2858 
2859  mCannedResponseMessageType = aMessageType;
2860  strncpy( mCannedResponseMessageBody, aMessageText, cnt_of_array( mCannedResponseMessageBody ) - 1 );
2862 
2863  memset( &data, 0, sizeof( data ) );
2864  data.id_size = aMessageId.getIdSize();
2865  memcpy( data.id, aMessageId.getId(), data.id_size );
2866  data.response_count = (uint8) minval( 50, aResponseCount );
2867  memcpy( data.response_id, aResponseList, sizeof(uint32) * data.response_count );
2868 
2869  payloadSize = offset_of( canned_response_list_data_type, response_id ) + sizeof( uint32 ) * aResponseCount;
2870 
2871  txFmi( FMI_ID_SET_CANNED_RESP_LIST, (uint8*)&data, payloadSize );
2872  return true;
2873 }
2874 
2875 //----------------------------------------------------------------------
2880 //----------------------------------------------------------------------
2882  (
2883  uint32 aResponseId,
2884  CString aResponseText
2885  )
2886 {
2887  uint8 payloadSize;
2889  char temp[50];
2890 
2891  //Update the canned response list with the updated text.
2892  ClientListItem& responseItem = mCannedResponses.get( aResponseId );
2893  responseItem.setUpdateName( aResponseText );
2894  mCannedResponses.put( responseItem );
2895 
2896  //Build and send the packet
2897  memset( &data, 0, sizeof( data ) );
2898 
2899  WideCharToMultiByte( mClientCodepage, 0, aResponseText.GetBuffer(), -1, temp, 50, NULL, NULL );
2900  temp[49] = '\0';
2901  strcpy( data.response_text, temp );
2902 
2903  data.response_id = aResponseId;
2904  payloadSize = (uint8)( offset_of( canned_response_data_type, response_text ) + strlen( data.response_text ) + 1 );
2905  txFmi( FMI_ID_SET_CANNED_RESPONSE, (uint8*)&data, payloadSize );
2906 }
2907 
2908 //----------------------------------------------------------------------
2913 //----------------------------------------------------------------------
2915  (
2916  uint32 aMessageId,
2917  CString aMessageText
2918  )
2919 {
2920  uint8 payloadSize;
2922  char temp[50];
2923 
2924  //Update the canned message list on the server
2925  ClientListItem& listItem = mCannedMessages.get( aMessageId );
2926  listItem.setUpdateName( aMessageText );
2927  listItem.setId( aMessageId );
2928  mCannedMessages.put( listItem );
2929 
2930  //Build and send the packet
2931  memset( &data, 0, sizeof( data ) );
2932  WideCharToMultiByte( mClientCodepage, 0, aMessageText.GetBuffer(), -1, temp, 50, NULL, NULL );
2933  temp[49] = '\0';
2934 
2935  data.message_id = aMessageId;
2936  strcpy( data.message, temp );
2937  payloadSize = offset_of( canned_message_data_type, message ) + (uint8) strlen( data.message ) + 1;
2938  txFmi( FMI_ID_SET_CANNED_MSG, (uint8*)&data, payloadSize );
2939 }
2940 
2941 //----------------------------------------------------------------------
2945 //----------------------------------------------------------------------
2947  (
2948  uint32 aResponseId
2949  )
2950 {
2952  data.response_id = aResponseId;
2953  txFmi( FMI_ID_DELETE_CANNED_RESPONSE, (uint8*)&data, sizeof( data ) );
2954 }
2955 
2956 //----------------------------------------------------------------------
2960 //----------------------------------------------------------------------
2962  (
2963  uint32 aMessageId
2964  )
2965 {
2967  data.message_id = aMessageId;
2968  txFmi( FMI_ID_DELETE_CANNED_MSG, (uint8*)&data, sizeof( data ) );
2969 }
2970 
2971 //----------------------------------------------------------------------
2975 //----------------------------------------------------------------------
2977  (
2978  uint32 aStatusId
2979  )
2980 {
2982  deleteItem.status_id = aStatusId;
2983  txFmi( FMI_ID_DELETE_DRIVER_STATUS_LIST_ITEM, (uint8*)&deleteItem, sizeof( deleteItem ) );
2984 }
2985 
2986 //----------------------------------------------------------------------
2989 //----------------------------------------------------------------------
2991 {
2992  txFmi( FMI_ID_DRIVER_ID_REQUEST, NULL, 0 );
2993 }
2994 
2995 #if( FMI_SUPPORT_A607 )
2996 //----------------------------------------------------------------------
3000 //----------------------------------------------------------------------
3002  (
3003  uint8 aDriverIndex
3004  )
3005 {
3007  memset( &request, 0, sizeof( request ) );
3008  request.driver_idx = aDriverIndex;
3009 
3010  txFmi( FMI_ID_DRIVER_ID_REQUEST, (uint8*)&request, sizeof( request ) );
3011 }
3012 
3013 //----------------------------------------------------------------------
3017 //----------------------------------------------------------------------
3019  (
3020  uint8 aDriverIndex
3021  )
3022 {
3024  memset( &request, 0, sizeof( request ) );
3025  request.driver_idx = aDriverIndex;
3026 
3027  txFmi( FMI_ID_DRIVER_STATUS_REQUEST, (uint8*)&request, sizeof( request ) );
3028 }
3029 #endif
3030 
3031 //----------------------------------------------------------------------
3035 //----------------------------------------------------------------------
3037  (
3038  char * aDriverId
3039  )
3040 {
3041  uint8 payloadSize;
3042  time_type originationTime = UTIL_get_current_garmin_time();
3043 
3044  strncpy( mSentDriverId, aDriverId, cnt_of_array( mSentDriverId ) - 1 );
3045  mSentDriverId[cnt_of_array( mSentDriverId ) - 1] = '\0';
3046 
3047  driver_id_data_type data;
3048  memset( &data, 0, sizeof( data ) );
3049 
3050  //need to allow app to actually set this field
3051  data.status_change_id = originationTime;
3052  data.status_change_time = originationTime;
3053  strncpy( data.driver_id, aDriverId, cnt_of_array( data.driver_id ) - 1 );
3054  payloadSize = offset_of( driver_id_data_type, driver_id ) + (uint8)strlen( data.driver_id ) + 1;
3055 
3056  txFmi( FMI_ID_DRIVER_ID_UPDATE, (uint8*)&data, payloadSize );
3057 }
3058 
3059 //----------------------------------------------------------------------
3065 //----------------------------------------------------------------------
3067  (
3068  uint32 aStatusId,
3069  CString aStatusText
3070  )
3071 {
3072  uint8 payloadSize;
3073  char statusText[50];
3075 
3076  // Update the driver aStatusText list on the server side
3077  ClientListItem& listItem = mDriverStatuses.get( aStatusId );
3078  listItem.setUpdateName( aStatusText );
3079  mDriverStatuses.put( listItem );
3080 
3081  // Send the driver aStatusText item to the client
3082  memset( &data, 0, sizeof( data ) );
3083  WideCharToMultiByte( mClientCodepage, 0, aStatusText.GetBuffer(), -1, statusText, 50, NULL, NULL );
3084  statusText[49] = '\0';
3085 
3086  data.status_id = aStatusId;
3087  strcpy( data.status, statusText );
3088  payloadSize = offset_of( driver_status_list_item_data_type, status ) + (uint8)strlen( data.status ) + 1;
3089 
3090  txFmi( FMI_ID_SET_DRIVER_STATUS_LIST_ITEM, (uint8*)&data, payloadSize );
3091 }
3092 
3093 //----------------------------------------------------------------------
3096 //----------------------------------------------------------------------
3098 {
3099  txFmi( FMI_ID_DRIVER_STATUS_REQUEST, NULL, 0 );
3100 }
3101 
3102 //----------------------------------------------------------------------
3108 //----------------------------------------------------------------------
3110  (
3111  uint32 aDriverStatusId
3112  )
3113 {
3114  time_type originationTime = UTIL_get_current_garmin_time();
3115  mSentDriverStatus = aDriverStatusId;
3116 
3117  driver_status_data_type status;
3118  memset( &status, 0, sizeof( status ) );
3119 
3120  //need to make this an input
3121  status.status_change_id = originationTime;
3122 
3123  status.status_change_time = originationTime;
3124  status.driver_status = aDriverStatusId;
3125 
3126  txFmi( FMI_ID_DRIVER_STATUS_UPDATE, (uint8*)&status, sizeof( status ) );
3127 }
3128 
3129 //----------------------------------------------------------------------
3135 //----------------------------------------------------------------------
3137  (
3138  uint16 aPacketId,
3139  uint16 aThrottleState
3140  )
3141 {
3143  throttle.packet_id = aPacketId;
3144  throttle.new_state = aThrottleState;
3145 
3146  txFmi( FMI_ID_MSG_THROTTLING_COMMAND, (uint8*)&throttle, sizeof( throttle ) );
3147 }
3148 //----------------------------------------------------------------------
3162 //----------------------------------------------------------------------
3164  (
3165  char * aFilename,
3166  uint8 aVersionLength,
3167  uint8 * aVersion,
3168  uint8 aFileType,
3169  BOOL gzipIt
3170  )
3171 {
3172  CFileStatus status;
3173  CString strFilename( aFilename );
3174  if ( CFile::GetStatus( strFilename, status) )
3175  {
3176  file_info_data_type fileInfo;
3177  memset( &fileInfo, 0, sizeof( fileInfo ) );
3178  fileInfo.file_type = aFileType;
3179 
3180  fileInfo.file_version_length = aVersionLength;
3181  memcpy( &fileInfo.file_version, aVersion, minval( aVersionLength, 16 ) );
3182 
3183  if ( gzipIt )
3184  {
3185  //zip it to another file and transfer that
3187  mFilePath[cnt_of_array( mFilePath ) - 1] = '\0';
3188  gzFile zipFile = gzopen( mFilePath, "wb" );
3189  if ( NULL != zipFile )
3190  {
3191  CFile original;
3192  if ( original.Open( strFilename, CFile::modeRead ) )
3193  {
3194  BYTE buf[1024];
3195  int len = 0;
3196  while ( ( len = original.Read( ( void * ) buf, 1024 ) ) > 0 )
3197  {
3198  gzwrite( zipFile, buf, len );
3199  }
3200  original.Close();
3201  }
3202  gzclose( zipFile );
3203 
3204  CFile::GetStatus( _T( GZIPPED_TRANSFER_FILENAME ), status );
3205  }
3206  }
3207  else {
3208  strncpy( mFilePath, aFilename, cnt_of_array( mFilePath ) - 1 );
3209  mFilePath[cnt_of_array( mFilePath ) - 1] = '\0';
3210  }
3211 
3212  fileInfo.file_size = (uint32) status.m_size;
3213  mFileTransferSize = (uint32) status.m_size;
3214 
3217 
3218  #if( FMI_SUPPORT_A610 )
3219  mCurrentSendFileType = aFileType;
3220  #endif
3221 
3223  txFmi
3224  (
3226  (uint8*)&fileInfo,
3227  sizeof( fileInfo ) - sizeof( fileInfo.file_version ) + fileInfo.file_version_length
3228  );
3229  }
3230 }
3231 
3232 //----------------------------------------------------------------------
3235 //----------------------------------------------------------------------
3237 {
3239 }
3240 
3241 //----------------------------------------------------------------------
3247 //----------------------------------------------------------------------
3249 {
3253 } /* stopFileTransfer() */
3254 
3255 //----------------------------------------------------------------------
3258 //----------------------------------------------------------------------
3260 {
3261  txFmi( FMI_ID_PING, NULL, 0 );
3262 }
3263 
3264 //----------------------------------------------------------------------
3270 //----------------------------------------------------------------------
3272 {
3273  txFmi( FMI_ID_SORT_STOP_LIST, NULL, 0 );
3274 }
3275 
3276 //----------------------------------------------------------------------
3280 //----------------------------------------------------------------------
3282  (
3283  const MessageId & aMessageId
3284  )
3285 {
3287 
3288  memset( &request, 0, sizeof( request ) );
3289  request.id_size = aMessageId.getIdSize();
3290  memcpy( request.id, aMessageId.getId(), request.id_size );
3291 
3292  txFmi( FMI_ID_TEXT_MSG_STATUS_REQUEST, (uint8*)&request, sizeof( request ) );
3293 }
3294 
3295 //----------------------------------------------------------------------
3302 //----------------------------------------------------------------------
3304  (
3305  uint32 aElementId,
3306  char * aNewText
3307  )
3308 {
3310  uint8 payloadSize;
3311  uint8 textLength;
3312 
3313  memset( &uiText, 0, sizeof( uiText ) );
3314 
3315  uiText.text_element_id = aElementId;
3316 
3317  //Investigate the reliability of this operation
3318  textLength = minval( (uint8) strlen( aNewText ) + 1, 49 );
3319  memcpy( uiText.new_text, aNewText, textLength );
3320 
3321  //Investigate the reliability of this operation
3322  payloadSize = offset_of( user_interface_text_data_type, new_text ) + (uint8) strlen( uiText.new_text ) + 1;
3323 
3324  txFmi( FMI_ID_USER_INTERFACE_TEXT, (uint8*)&uiText, payloadSize );
3325 }
3326 
3327 #endif
3328 
3329 #if( FMI_SUPPORT_A608 )
3330 //---------------------------------------------------------------------
3339 //---------------------------------------------------------------------
3341  (
3342  uint8 aMode,
3343  uint8 aTimeOver,
3344  uint8 aTimeUnder,
3345  boolean aAlertUser,
3346  float aThreshold
3347  )
3348 {
3349  speed_limit_data_type data;
3350  data.mode = aMode;
3351  data.time_over = aTimeOver;
3352  data.time_under = aTimeUnder;
3353  data.alert_user = aAlertUser;
3354  data.threshold = aThreshold;
3355 
3356  txFmi( FMI_SPEED_LIMIT_SET,(uint8*)&data, sizeof( data ) );
3357 }
3358 #endif
3359 
3360 #if( FMI_SUPPORT_A605 )
3361 //----------------------------------------------------------------------
3364 //----------------------------------------------------------------------
3366 {
3367  txFmi( FMI_ID_MSG_THROTTLING_QUERY, NULL, 0 );
3368 }
3369 #endif
3370 
3371 #if FMI_SUPPORT_A607
3372 //----------------------------------------------------------------------
3382 //----------------------------------------------------------------------
3384  (
3385  uint16 aUniqueId,
3386  double aLat,
3387  double aLon,
3388  uint16 aSymbol,
3389  CString &aName,
3390  uint16 aCat,
3391  CString &aComment
3392  )
3393 {
3394  waypoint_data_type waypoint;
3395 
3396  waypoint.unique_id = aUniqueId;
3397  waypoint.posn.lat = UTIL_convert_degrees_to_semicircles( aLat );
3398  waypoint.posn.lon = UTIL_convert_degrees_to_semicircles( aLon );
3399  waypoint.symbol = aSymbol;
3400 
3401  //Update the waypoint list on the server
3402  WaypointListItem& listItem = mWaypoints.get( aUniqueId );
3403  listItem.setUpdateName( aName );
3404  listItem.setCategories( aCat );
3405  mWaypoints.put( listItem );
3406 
3407  waypoint.cat = aCat;
3408 
3409  WideCharToMultiByte( mClientCodepage, 0, aName.GetBuffer(), -1, waypoint.name, 30, NULL, NULL );
3410  waypoint.name[30] = '\0';
3411 
3412  WideCharToMultiByte( mClientCodepage, 0, aComment.GetBuffer(), -1, waypoint.comment, 50, NULL, NULL );
3413  waypoint.comment[50] = '\0';
3414 
3415  txFmi( FMI_ID_WAYPOINT, (uint8*)&waypoint, sizeof( waypoint ) );
3416 }
3417 
3418 //----------------------------------------------------------------------
3422 //----------------------------------------------------------------------
3424  (
3425  uint16 aUniqueId
3426  )
3427 {
3428  if( mWaypoints.contains( aUniqueId ) )
3429  {
3430  txFmi( FMI_ID_WAYPOINT_DELETE, (uint8*)&aUniqueId, sizeof( aUniqueId ) );
3431  mWaypoints.remove( aUniqueId );
3433  }
3434 }
3435 
3436 //----------------------------------------------------------------------
3440 //----------------------------------------------------------------------
3442  (
3443  uint16 aCatIdx
3444  )
3445 {
3447  bool update = false;
3448 
3449  for( iter = mWaypoints.begin(); iter != mWaypoints.end(); ++iter )
3450  {
3451  if( iter->second.getCategories() & aCatIdx )
3452  {
3453  update = true;
3454 
3455  // Set the waypoint as invalid, which will remove it from
3456  // the save file. The item cannot be removed from the
3457  // FileBackedMap because it is being iterated over.
3458  WaypointListItem& wpt = mWaypoints.get( iter->first );
3459  wpt.setValid( FALSE );
3460  }
3461  }
3462 
3463  if( update )
3464  {
3466  }
3467 
3468  txFmi( FMI_ID_DELETE_WAYPOINT_CAT, (uint8*)&aCatIdx, sizeof( aCatIdx ) );
3469 }
3470 
3471 //----------------------------------------------------------------------
3475 //----------------------------------------------------------------------
3477  (
3478  uint8 aCatId,
3479  CString &aCatName
3480  )
3481 {
3482  category_data_type category;
3483  category.id = aCatId;
3484 
3485  WideCharToMultiByte( mClientCodepage, 0, aCatName.GetBuffer(), -1, category.name, 16, NULL, NULL );
3486  category.name[16] = '\0';
3487 
3488  //Update the waypoint list on the server
3489  ClientListItem& listItem = mCategories.get( aCatId );
3490  listItem.setUpdateName( aCatName );
3491  mCategories.put( listItem );
3492 
3493  txFmi( FMI_ID_CREATE_WAYPOINT_CAT, (uint8*)&category, sizeof( category ) );
3494 }
3495 
3496 //----------------------------------------------------------------------
3500 //----------------------------------------------------------------------
3502  (
3503  const MessageId & aMessageId
3504  )
3505 {
3507 
3508  memset( &request, 0, sizeof( request ) );
3509  request.id_size = aMessageId.getIdSize();
3510  memcpy( request.id, aMessageId.getId(), request.id_size );
3511 
3512  txFmi( FMI_ID_TEXT_MSG_DELETE_REQUEST, (uint8*)&request, sizeof( request ) );
3513 }
3514 #endif
3515 
3516 #if( FMI_SUPPORT_A610 )
3517 //---------------------------------------------------------------------
3522 //---------------------------------------------------------------------
3524  (
3525  uint32 aOdometer
3526  )
3527 {
3529  memset( &data, 0, sizeof( data ) );
3530 
3531  data.odometer_value = aOdometer;
3532 
3533  txFmi( FMI_SET_ODOMETER_REQUEST, (uint8*)&data, sizeof( data ) );
3534 }
3535 
3536 //----------------------------------------------------------------------
3540 //----------------------------------------------------------------------
3542  {
3543  if( 0 == mAOBRDStopShipmentTxIndex )
3544  {
3545  return;
3546  }
3547 
3549  memset( &receipt, 0, sizeof( receipt ) );
3550 
3551  char temp[256];
3552  strncpy( receipt.driver_id, driver_id, cnt_of_array( receipt.driver_id ) - 1 );
3553 
3554  //ensure that the driver being acknowledged is the one that was first requested
3555  if( mAOBRDShipmentDriverId != driver_id )
3556  {
3558 
3559  txFmi( FMI_SHIPMENT_DOWNLOAD_RESPONSE, (uint8*)&receipt, sizeof( receipt ) );
3560  return;
3561  }
3562 
3563  //ensure that the iterator is still valid
3565  {
3566  receipt.server_result_code = EMPTY_DATA;
3567 
3568  txFmi( FMI_SHIPMENT_DOWNLOAD_RESPONSE, (uint8*)&receipt, sizeof( receipt ) );
3569 
3570  //reset iterator to zero so that no more messages are sent
3573  return;
3574  }
3575 
3577 
3578  AobrdDriverItem & driver = mAOBRDDrivers.get( receipt.driver_id );
3579  AobrdShipment shipment = driver.getShipments().at( mAOBRDCurrentShipmentTxIndex++ );
3580 
3581  //server timestamp
3582  receipt.server_timestamp = shipment.getServerTimestamp();
3583  //server start time
3584  receipt.server_start_time = shipment.getServerStartTime();
3585  //server end time
3586  receipt.server_end_time = shipment.getServerEndTime();
3587  //shipper name
3588  WideCharToMultiByte( mClientCodepage, 0, shipment.getShipperName().GetBuffer(), -1, temp, 40, NULL, NULL );
3589  temp[39] = '\0';
3590  strcpy( receipt.server_shipper_name, temp );
3591  //doc number
3592  WideCharToMultiByte( mClientCodepage, 0, shipment.getDocNumber().GetBuffer(), -1, temp, 40, NULL, NULL );
3593  temp[39] = '\0';
3594  strcpy( receipt.server_doc_number, temp );
3595  //commodity
3596  WideCharToMultiByte( mClientCodepage, 0, shipment.getCommodity().GetBuffer(), -1, temp, 40, NULL, NULL );
3597  temp[39] = '\0';
3598  strcpy( receipt.server_commodity, temp );
3599 
3600  //send it
3601  txFmi( FMI_SHIPMENT_DOWNLOAD_RESPONSE, (uint8*)&receipt, sizeof( receipt ) );
3602  }
3603 
3604 //----------------------------------------------------------------------
3608 //----------------------------------------------------------------------
3610  (
3611  const AobrdDriverItem & driver
3612  )
3613  {
3614 #if( FMI_SUPPORT_A615 )
3615  if( NULL != strstr( mProtocols, "A615" ) )
3616  {
3617  sendAOBRDDriverProfileV2( driver );
3618  return;
3619  }
3620 #endif
3621 
3622  char temp[256];
3623 
3625  memset( &receipt, 0, sizeof( receipt ) );
3626 
3627  WideCharToMultiByte( mClientCodepage, 0, driver.getFirstName().GetBuffer(), -1, temp, 35, NULL, NULL );
3628  temp[34] = '\0';
3629  strcpy( receipt.first_name, temp );
3630 
3631  WideCharToMultiByte( mClientCodepage, 0, driver.getLastName().GetBuffer(), -1, temp, 35, NULL, NULL );
3632  temp[34] = '\0';
3633  strcpy( receipt.last_name, temp );
3634 
3635  WideCharToMultiByte( mClientCodepage, 0, driver.getDriverId().GetBuffer(), -1, temp, 40, NULL, NULL );
3636  temp[39] = '\0';
3637  strcpy( receipt.driver_id, temp );
3638 
3639  WideCharToMultiByte( mClientCodepage, 0, driver.getCarrierName().GetBuffer(), -1, temp, 120, NULL, NULL );
3640  temp[119] = '\0';
3641  strcpy( receipt.carrier_name, temp );
3642 
3643  WideCharToMultiByte( mClientCodepage, 0, driver.getCarrierID().GetBuffer(), -1, temp, 8, NULL, NULL );
3644  temp[7] = '\0';
3645  strcpy( receipt.carrier_id, temp );
3646 
3647  receipt.long_term_rule_set = (uint8) driver.getLongTermRuleset();
3648  receipt.time_zone = (uint8) driver.getTimeZone();
3649  receipt.status = 0;
3650  receipt.result_code = 0;
3651 
3652  txFmi( FMI_DRIVER_PROFILE_UPDATE, (uint8*)&receipt, sizeof( receipt ) );
3653  }
3654 
3655 static bool convertAnnotationRecord( AobrdEventLogConverter * converter, std::vector<std::string> & record, void * data )
3656  {
3657  return converter->convertAnnotation( record, ( fmi_driver_annotation_data_type* ) data );
3658  }
3659 
3660 //----------------------------------------------------------------------
3664 //----------------------------------------------------------------------
3666  {
3667  if( 0 == mAOBRDStopAnnotationTxIndex )
3668  {
3669  return;
3670  }
3671 
3673  memset( &record, 0, sizeof( record ) );
3674 
3675  strncpy( record.driver_id, driver_id, cnt_of_array( record.driver_id ) - 1 );
3676 
3677  //ensure that the driver being acknowledged is the one that was first requested
3678  if( mAOBRDAnnotationDriverId != driver_id )
3679  {
3681 
3682  txFmi( FMI_ANNOTATION_DOWNLOAD_RESPONSE, (uint8*)&record, sizeof( record ) );
3683  return;
3684  }
3685 
3686  //ensure that the iterator is still valid
3688  {
3689  record.server_result_code = EMPTY_DATA;
3690 
3691  txFmi( FMI_ANNOTATION_DOWNLOAD_RESPONSE, (uint8*)&record, sizeof( record ) );
3692 
3693  //reset iterator to zero so that no more messages are sent
3696  return;
3697  }
3698 
3700 
3701  AobrdEventLogConverter aobrdLogFile;
3702  char source[_MAX_PATH];
3703  sprintf( source, SAVE_CONVERTED_AOBRD_LOG, record.driver_id );
3705 
3706  mAOBRDCurrentAnnotationTxIndex++;
3707 
3708  //send it
3709  txFmi( FMI_ANNOTATION_DOWNLOAD_RESPONSE, (uint8*)&record, sizeof( record ) );
3710  }
3711 
3712  //----------------------------------------------------------------------
3715  //----------------------------------------------------------------------
3717  (
3718  uint8 file_type
3719  ) const
3720  {
3721  switch ( file_type )
3722  {
3723 #if( FMI_SUPPORT_A610 )
3724  case FMI_FILE_TYPE_AOBRD:
3725  {
3726  return SAVE_RECEIVED_AOBRD_LOG;
3727  }
3728 #endif
3729 #if( FMI_SUPPORT_A612 )
3731  {
3733  }
3734 #endif
3735 #if( FMI_SUPPORT_A615 )
3736  case FMI_FILE_TYPE_IFTA:
3737  {
3738  return SAVE_RECEIVED_IFTA_FILE;
3739  }
3740 #endif
3741  default:
3742  return NULL;
3743  }
3744  }
3745 
3746  //----------------------------------------------------------------------
3749  //----------------------------------------------------------------------
3751  (
3752  const file_info_data_type & file
3753  )
3754  {
3755  mCurrentReceiptFile = file;
3756 
3757  // Delete the destination file if it already exists
3758  CString filename( getReceiveFilename( file.file_type ) );
3759 
3760  CFileStatus status;
3761  if( CFile::GetStatus( filename, status ) )
3762  {
3763  CFile::Remove( filename );
3764  }
3765 
3767 
3768  memset( &receipt, 0, sizeof( receipt ) );
3769 
3771  receipt.file_type = file.file_type;
3772  txFmi( FMI_ID_FILE_START_RCPT, (uint8*)&receipt, sizeof( receipt ) );
3773  }
3774 
3775  //----------------------------------------------------------------------
3780  //----------------------------------------------------------------------
3782  (
3783  uint32 offset,
3784  uint8 length,
3785  uint8 const* data
3786  )
3787  {
3788  packet_receipt_data_type receipt;
3789 
3790  memset( &receipt, 0, sizeof( receipt ) );
3791  receipt.offset = offset;
3792 
3793  const char * filename = getReceiveFilename( mCurrentReceiptFile.file_type );
3794 
3795  // Write out to file
3796  ofstream destinationFile( filename, ios_base::binary | ios_base::app );
3797  if( !destinationFile.good() )
3798  {
3799  destinationFile.close();
3800  receipt.next_offset = 0xFFFFFFFF;
3801  txFmi( FMI_ID_FILE_PACKET_RCPT, (uint8*)&receipt, sizeof( receipt ) );
3802  return;
3803  }
3804 
3805  if( ( offset + length ) > mCurrentReceiptFile.file_size )
3806  {
3807  /* Don't write past end of file, ask for packet again */
3808  destinationFile.close();
3809  receipt.next_offset = offset;
3810  txFmi( FMI_ID_FILE_PACKET_RCPT, (uint8*)&receipt, sizeof( receipt ) );
3811  return;
3812  }
3813 
3814  destinationFile.seekp( offset, ios::beg );
3815 
3816  if( !destinationFile.good() )
3817  {
3818  /* Error on seek to offset */
3819  destinationFile.close();
3820  receipt.next_offset = 0xFFFFFFFF;
3821  txFmi( FMI_ID_FILE_PACKET_RCPT, (uint8*)&receipt, sizeof( receipt ) );
3822  return;
3823  }
3824 
3825  destinationFile.write( (char*)data, length );
3826 
3827  if( !destinationFile.good() )
3828  {
3829  /* Error on write, ask for packet again */
3830  destinationFile.close();
3831  receipt.next_offset = offset;
3832  txFmi( FMI_ID_FILE_PACKET_RCPT, (uint8*)&receipt, sizeof( receipt ) );
3833  return;
3834  }
3835 
3836  destinationFile.close();
3837 
3838  receipt.next_offset = offset + length;
3839  txFmi( FMI_ID_FILE_PACKET_RCPT, (uint8*)&receipt, sizeof( receipt ) );
3840  }
3841 
3842  //----------------------------------------------------------------------
3845  //----------------------------------------------------------------------
3847  {
3849 
3850  memset( &receipt, 0, sizeof( receipt ) );
3851 
3852  // Simply return success code. The client does not handle error codes yet
3855  txFmi( FMI_ID_FILE_END_RCPT, (uint8*)&receipt, sizeof( receipt ) );
3856 
3857  switch ( mCurrentReceiptFile.file_type )
3858  {
3859 #if( FMI_SUPPORT_A610 )
3860  case FMI_FILE_TYPE_AOBRD:
3861  {
3863  break;
3864  }
3865 #endif
3866 #if( FMI_SUPPORT_A612 )
3868  {
3870  break;
3871  }
3872 #endif
3873 #if( FMI_SUPPORT_A615 )
3874  case FMI_FILE_TYPE_IFTA:
3875  {
3877  break;
3878  }
3879 #endif
3880  }
3881 
3882  memset( &mCurrentReceiptFile, 0, sizeof( mCurrentReceiptFile ) );
3883  }
3884 #endif
3885 
3886 #if( FMI_SUPPORT_A615 )
3887 //----------------------------------------------------------------------
3891  //----------------------------------------------------------------------
3893  (
3894  const AobrdDriverItem & driver
3895  )
3896  {
3897  char temp[256];
3898 
3900  memset( &receipt, 0, sizeof( receipt ) );
3901 
3902  WideCharToMultiByte( mClientCodepage, 0, driver.getFirstName().GetBuffer(), -1, temp, 35, NULL, NULL );
3903  temp[34] = '\0';
3904  strcpy( receipt.first_name, temp );
3905 
3906  WideCharToMultiByte( mClientCodepage, 0, driver.getLastName().GetBuffer(), -1, temp, 35, NULL, NULL );
3907  temp[34] = '\0';
3908  strcpy( receipt.last_name, temp );
3909 
3910  WideCharToMultiByte( mClientCodepage, 0, driver.getDriverId().GetBuffer(), -1, temp, 40, NULL, NULL );
3911  temp[39] = '\0';
3912  strcpy( receipt.driver_id, temp );
3913 
3914  WideCharToMultiByte( mClientCodepage, 0, driver.getCarrierName().GetBuffer(), -1, temp, 120, NULL, NULL );
3915  temp[119] = '\0';
3916  strcpy( receipt.carrier_name, temp );
3917 
3918  WideCharToMultiByte( mClientCodepage, 0, driver.getCarrierID().GetBuffer(), -1, temp, 8, NULL, NULL );
3919  temp[7] = '\0';
3920  strcpy( receipt.carrier_id, temp );
3921 
3922  receipt.long_term_rule_set = (uint8) driver.getLongTermRuleset();
3923  receipt.load_type_rule_set = (uint8) driver.getLoadTypeRuleset();
3924 
3925  receipt.time_zone = (uint8) driver.getTimeZone();
3926  receipt.adverse_condition_time = 0;
3927 
3928  receipt.status = 0;
3929  receipt.result_code = 0;
3930 
3931  txFmi( FMI_DRIVER_PROFILE_UPDATE_V2, (uint8*)&receipt, sizeof( receipt ) );
3932  }
3933 
3934  //----------------------------------------------------------------------
3938  //----------------------------------------------------------------------
3940  (
3941  const char * driverId
3942  )
3943  {
3944  char temp[256];
3945 
3947  memset( &receipt, 0, sizeof( receipt ) );
3948 
3949  if( 0 == strlen( driverId ) )
3950  {
3951  //invalid request
3952  receipt.result_code = 1;
3953  }
3954  else if( mAOBRDDrivers.contains( driverId ) )
3955  {
3956  AobrdDriverItem & driver = mAOBRDDrivers.get( driverId );
3957 
3958  WideCharToMultiByte( mClientCodepage, 0, driver.getFirstName().GetBuffer(), -1, temp, 35, NULL, NULL );
3959  temp[34] = '\0';
3960  strcpy( receipt.first_name, temp );
3961 
3962  WideCharToMultiByte( mClientCodepage, 0, driver.getLastName().GetBuffer(), -1, temp, 35, NULL, NULL );
3963  temp[34] = '\0';
3964  strcpy( receipt.last_name, temp );
3965 
3966  WideCharToMultiByte( mClientCodepage, 0, driver.getDriverId().GetBuffer(), -1, temp, 40, NULL, NULL );
3967  temp[39] = '\0';
3968  strcpy( receipt.driver_id, temp );
3969 
3970  WideCharToMultiByte( mClientCodepage, 0, driver.getCarrierName().GetBuffer(), -1, temp, 120, NULL, NULL );
3971  temp[119] = '\0';
3972  strcpy( receipt.carrier_name, temp );
3973 
3974  WideCharToMultiByte( mClientCodepage, 0, driver.getCarrierID().GetBuffer(), -1, temp, 8, NULL, NULL );
3975  temp[7] = '\0';
3976  strcpy( receipt.carrier_id, temp );
3977 
3978  receipt.long_term_rule_set = (uint8) driver.getLongTermRuleset();
3979  receipt.load_type_rule_set = (uint8) driver.getLoadTypeRuleset();
3980 
3981  receipt.time_zone = (uint8) driver.getTimeZone();
3982  receipt.status = 0;
3983  receipt.result_code = 0;
3984  }
3985  else
3986  {
3987  // driver ID not found
3988  receipt.result_code = 1;
3989  }
3990 
3991  txFmi( FMI_DRIVER_PROFILE_DOWNLOAD_RESPONSE_V2, (uint8*)&receipt, sizeof( receipt ) );
3992  }
3993 //----------------------------------------------------------------------
3997 //----------------------------------------------------------------------
3999  (
4000  const AobrdDriverItem & driver
4001  )
4002  {
4003  char temp[40];
4004 
4006  memset( &packet, 0, sizeof( packet ) );
4007 
4008  WideCharToMultiByte( mClientCodepage, 0, driver.getDriverId().GetBuffer(), -1, temp, 40, NULL, NULL );
4009  temp[39] = '\0';
4010  strcpy( packet.driver_id, temp );
4011 
4012  txFmi( FMI_AOBRD_DRIVER_LOGOFF_REQUEST, (uint8*)&packet, sizeof( packet ) );
4013  }
4014 #endif
4015 
4016 //----------------------------------------------------------------------
4025 //----------------------------------------------------------------------
4027  (
4028  float32 aNorthVelocity,
4029  float32 aEasstVelocity
4030  )
4031 {
4032  double speed;
4033  char direction[3];
4034 
4035  speed = UTIL_calc_2d_speed( aNorthVelocity, aEasstVelocity );
4036  UTIL_calc_2d_direction( aNorthVelocity, aEasstVelocity, direction, sizeof( direction ) );
4037 
4038  sprintf( mHorizontalVelocity, "%05.3f m/s %s", speed, direction );
4039 }
4040 
4041 //----------------------------------------------------------------------
4044 //----------------------------------------------------------------------
4046  (
4047  command_type const aCommandId
4048  )
4049 {
4050  ASSERT( mTransportLayer != NULL );
4051  mTransportLayer->tx( new GarminPacket( ID_COMMAND_BYTE, (uint8 *)&aCommandId, sizeof( aCommandId ), this ), FALSE );
4052 } /* txCommand() */
4053 
4054 #if( FMI_SUPPORT_A602 )
4055 //----------------------------------------------------------------------
4066 //----------------------------------------------------------------------
4068  (
4069  fmi_id_type const aFmiPacketId,
4070  uint8 const * const aData,
4071  uint8 const aSize,
4072  bool const aSendNow
4073  )
4074 {
4075  /*----------------------------------------------------------
4076  Local Variables
4077  ----------------------------------------------------------*/
4078  fmi_id_type fmiPacketId;
4079  uint8 buffer[ MAX_PAYLOAD_SIZE ];
4080 
4081  fmiPacketId = aFmiPacketId;
4082  memcpy( &buffer[ 0 ], &fmiPacketId, sizeof( fmiPacketId ) );
4083  memcpy( &buffer[ sizeof( fmiPacketId ) ], aData, aSize );
4084 
4085  ASSERT( mTransportLayer != NULL );
4086  mTransportLayer->tx( new GarminPacket( ID_FMI_PACKET, buffer, aSize + sizeof( fmiPacketId ), this ), aSendNow );
4087 } /* txFmi() */
4088 #endif // FMI_SUPPORT_A602
4089 
4090 #if( CDT_SUPPORT )
4091 //----------------------------------------------------------------------
4102 //----------------------------------------------------------------------
4103 void FmiApplicationLayer::txCdt
4104  (
4105  cdt_id_type const aCdtPacketId,
4106  uint8 const * const aData,
4107  uint8 const aSize,
4108  bool const aSendNow
4109  )
4110 {
4111  /*----------------------------------------------------------
4112  Local Variables
4113  ----------------------------------------------------------*/
4114  cdt_id_type cdtPacketId;
4115  uint8 buffer[ MAX_PAYLOAD_SIZE ];
4116 
4117  cdtPacketId = aCdtPacketId;
4118  memcpy( &buffer[ 0 ], &cdtPacketId, sizeof( cdtPacketId ) );
4119  memcpy( &buffer[ sizeof( cdtPacketId ) ], aData, aSize );
4120 
4121  ASSERT( mTransportLayer != NULL );
4122  mTransportLayer->tx( new GarminPacket( ID_CDT_PACKET, buffer, aSize + sizeof( cdtPacketId ), this ), aSendNow );
4123 } /* txCdt() */
4124 #endif // FMI_SUPPORT_CDT
4125 
4126 #if( FMI_SUPPORT_A603 )
4127 //----------------------------------------------------------------------
4130 //----------------------------------------------------------------------
4132 {
4133  mA603Stops.clear();
4134  mStopIndexInList.clear();
4135 }
4136 #endif
4137 
4138 #if( FMI_SUPPORT_A607 )
4139 //----------------------------------------------------------------------
4143 //----------------------------------------------------------------------
4145 {
4146  mWaypoints.clear();
4147  mCategories.clear();
4148 
4151 }
4152 #endif
4153 
4154 #if( FMI_SUPPORT_A604 )
4155 //----------------------------------------------------------------------
4158 //----------------------------------------------------------------------
4160 {
4162 
4164 }
4165 
4166 //----------------------------------------------------------------------
4169 //----------------------------------------------------------------------
4171 {
4173 }
4174 
4175 //----------------------------------------------------------------------
4178 //----------------------------------------------------------------------
4180 {
4182 
4184 }
4185 
4186 //----------------------------------------------------------------------
4189 //----------------------------------------------------------------------
4191 {
4193 
4195 }
4196 #endif
4197 
4198 #if FMI_SUPPORT_A607
4199 //----------------------------------------------------------------------
4204 //----------------------------------------------------------------------
4206  (
4207  char * aDriverId,
4208  uint8 aIndex
4209  )
4210 {
4211  uint8 payloadSize;
4212  time_type originationTime = UTIL_get_current_garmin_time();
4213 
4214  strncpy( mSentDriverId, aDriverId, cnt_of_array( mSentDriverId ) - 1 );
4215  mSentDriverId[cnt_of_array( mSentDriverId ) - 1] = '\0';
4216 
4218  memset( &data, 0, sizeof( data ) );
4219 
4220  //need to allow app to actually set this field
4221  data.status_change_id = originationTime;
4222  data.status_change_time = originationTime;
4223  data.driver_idx = aIndex;
4224  strncpy( data.driver_id, aDriverId, cnt_of_array( data.driver_id ) - 1 );
4225  payloadSize = offset_of( driver_id_D607_data_type, driver_id ) + (uint8)strlen( data.driver_id ) + 1;
4226 
4227  txFmi( FMI_ID_DRIVER_ID_UPDATE_D607, (uint8*)&data, payloadSize );
4228 }
4229 
4230 //----------------------------------------------------------------------
4237 //----------------------------------------------------------------------
4239  (
4240  uint32 aDriverStatusId,
4241  uint8 aIndex
4242  )
4243 {
4244  time_type originationTime = UTIL_get_current_garmin_time();
4245  mSentDriverStatus = aDriverStatusId;
4246 
4248  memset( &status, 0, sizeof( status ) );
4249 
4250  //need to make this an input
4251  status.status_change_id = originationTime;
4252 
4253  status.status_change_time = originationTime;
4254  status.driver_status = aDriverStatusId;
4255  status.driver_idx = aIndex;
4256 
4257  txFmi( FMI_ID_DRIVER_STATUS_UPDATE_D607, (uint8*)&status, sizeof( status ) );
4258 }
4259 #endif
4260 
4261 #if( FMI_SUPPORT_A604 )
4262 //----------------------------------------------------------------------
4268 //----------------------------------------------------------------------
4270  (
4271  uint32 aDriverStatusId,
4272  uint8 aDriverIndex
4273  )
4274 {
4275  boolean result = FALSE;
4276 
4277  if( aDriverIndex >= FMI_DRIVER_COUNT )
4278  {
4279  return FALSE;
4280  }
4281 
4282  if( aDriverStatusId == INVALID32 )
4283  {
4284  strcpy( mDriverStatus[aDriverIndex], "status not set" );
4285  result = TRUE;
4286  }
4287  else if( mDriverStatuses.contains( aDriverStatusId ) )
4288  {
4289  ClientListItem& item = mDriverStatuses.get( aDriverStatusId );
4290  if( item.isValid() )
4291  {
4292  WideCharToMultiByte( mClientCodepage, 0, item.getCurrentName().GetBuffer(), -1, mDriverStatus[aDriverIndex], 50, NULL, NULL );
4293  mDriverStatus[aDriverIndex][49] = '\0';
4294  result = TRUE;
4295  }
4296  }
4297 
4298  if( result )
4299  {
4301  }
4302  return result;
4303 }
4304 #endif
4305 
4306 #if( FMI_SUPPORT_A609 )
4307 //----------------------------------------------------------------------
4309 //----------------------------------------------------------------------
4311  {
4312  txFmi( FMI_REBOOT_DEVICE_REQUEST, NULL, 0 );
4313  }
4314 #endif
4315 
4316 #if( FMI_SUPPORT_A616 )
4318  {
4319  // ensure current rate variable is supported
4320  switch( mBaudRateSyncRateType )
4321  {
4322  case FMI_BAUD_RATE_9600:
4323  case FMI_BAUD_RATE_38400:
4324  case FMI_BAUD_RATE_57600:
4325  break;
4326  default:
4327  return;
4328  }
4329 
4330  fmi_set_baud_request sync;
4331  memset( &sync, 0, sizeof( sync ) );
4334  txFmi( FMI_SET_BAUD_REQUEST, ( uint8* )&sync, sizeof( sync ), true );
4335  }
4336 #endif
char text_message[200]
Message text (variable length, null-terminated string)
Definition: fmi.h:1162
fmi_A604_message_status message_status
The status of the text message.
Definition: EventId.h:166
file_info_data_type mCurrentReceiptFile
Current file being received.
void sendAOBRDDriverDownloadResponseV2(const char *driverId)
Send an AOBRD driver profile V2 to the device per request from device.
time_type origination_time
Time when the message was created by the client.
Definition: fmi.h:1178
void sendAutoArrival(uint32 aArrivalTime, uint32 aArrivalDistance)
Send a request to update the auto-arrival preferences.
uint32 status_change_id
unique identifier
Definition: fmi.h:1488
double UTIL_calc_2d_speed(float32 aNorthVelocity, float32 aEastVelocity)
Determine the two-dimensional velocity.
Definition: util.cpp:674
BOOL isValid() const
Check whether this item is valid.
char mEtaTime[13]
String containing the ETA time from the client, or "invalid".
boolean result_code
TRUE if the operation was successful, FALSE otherwise.
Definition: fmi.h:1702
uint32 msg_ack_type
The response selected by the user.
Definition: fmi.h:1151
Data type for the Server to Client Open Text Message Receipt Packet ID.
Definition: fmi.h:1342
uint8 mCannedResponseMessageType
The message_type for the server to client canned text message.
uint8 id[16]
The message ID.
Definition: fmi.h:1546
sint32 UTIL_convert_degrees_to_semicircles(double aDegrees)
Converts a latitude/longitude from degrees to semicircles.
Definition: util.cpp:204
sint32 longitude
Longitude of the device sending the message.
Definition: EventId.h:156
Data type for the Set Odometer Request Packed ID (0X1100) from server to client.
Definition: fmi.h:1736
Payload of FMI_ID_SERVER_OPEN_TXT_MSG packet.
Definition: fmi.h:1125
uint32 response_id[50]
List of responses that are allowed.
Definition: fmi.h:1384
Data type for Get Dashcam Notification Settings Packet ID (0X1609) from client to server...
Definition: fmi.h:2310
void sendA607DriverIdRequest(uint8 aDriverIndex)
Ask the client for the current Driver ID.
CString getPassword() const
Get item&#39;s password.
Payload for FMI_ID_ENABLE.
Definition: fmi.h:1115
#define INVALID16
Placeholder for an invalid 16-bit value.
Definition: fmi.h:142
void resetSavedStops()
Clear the stop list on the server.
#define SAVE_DRIVER_LOGINS
File name of the saved driver IDs/passwords.
void sendProductRequest()
Send an FMI Product ID request.
void UTIL_convert_gps_time_to_seconds(const gps_time_type *aGpsTime, time_type *aSeconds)
Converts from gps_time to Garmin time.
Definition: util.cpp:233
uint8 id_size
Number of significant bytes in the message ID.
Definition: fmi.h:1544
#define SAVE_CAN_RESP
File name of the saved canned response data.
Data type for the Annotation Download Receipt Packet ID (0X110E) from client to server.
Definition: fmi.h:1862
bool mUsePasswords
If true, driver password support is enabled.
int mAOBRDCurrentShipmentTxIndex
Iterator for shipments being sent to device.
uint32 unique_id
Definition: fmi.h:1944
uint16 response_count
Number of protocols in the response_list.
Definition: fmi.h:1600
void setId(const key_type &aId)
Set item&#39;s ID.
void calculate2DVelocity(float32 aNorthVelocity, float32 aEastVelocity)
Calculate and format a 2D velocity given the north and east components.
void sendAOBRDDriverProfileV2(const AobrdDriverItem &driver)
Push an AOBRD driver profile V2 to the device.
const_iterator begin()
Iterator positioned at the first element in the map.
Definition: FileBackedMap.h:59
char name[16+1]
Category name, null terminated.
Definition: fmi.h:1694
uint8 file_type
File type.
Definition: fmi.h:1278
char name[30+1]
Waypoint name, null-terminated.
Definition: fmi.h:1672
void beginA611LongTextMessage(const char *aMessageText, const MessageId &aMessageId, uint8 aMessageType)
Send the first packet of an A611 server to client long text message.
void sendA607DriverStatusRequest(uint8 aDriverIndex)
Ask the client for the current Driver Status.
uint16 fmi_id_type
Fleet Management packet ID (first two bytes of payload when Garmin packet ID == ID_FMI_PACKET) ...
Definition: fmi.h:272
sc_position_type stop_position
Location of the stop.
Definition: fmi.h:1194
char server_shipper_name[40]
Definition: fmi.h:1826
char text_message[200]
Message text, variable length, null-terminated string, 200 bytes max.
Definition: fmi.h:1337
sc_position_type scposn
Definition: fmi.h:2331
void sendUnitIdRequest()
Request the Unit ID (ESN) from the client.
virtual bool setBaudRate(uint32 aBaudRate)
Set the baud rate.
Definition: SerialPort.cpp:504
uint8 request_type
Definition: fmi.h:2127
uint8 mLongTextMessagePayloadSize[10]
Indicates the lengths of the long text message packets.
uint8 id_size
id_size from the canned_response_list_data_type
Definition: fmi.h:1399
void txFmi(fmi_id_type const aFmiPacketId, uint8 const *const aFmiPayload, uint8 const aFmiPayloadSize, bool const aSendNow=false)
Transmit FMI packet (packet ID = ID_FMI_BYTE)
Element of the array returned in Garmin ID_PROTOCOL_ARRAY (A001) or FMI_ID_PROTOCOL_DATA (A602) packe...
Definition: fmi.h:1108
Data type for the Delete Message Status Packet ID.
Definition: fmi.h:1723
char mPvtLongitude[14]
Longitude in degrees from the last PVT packet, as an ASCII null-terminated string.
char tag
Type of protocol (e.g., &#39;A&#39;, D&#39;)
Definition: fmi.h:1110
sc_position_type posn
Waypoint position.
Definition: fmi.h:1670
uint8 baud_rate_type
Definition: fmi.h:2128
Data type for Driver ID Update Packet ID.
Definition: fmi.h:1417
time_type timestamp
Time the alert was generated.
Definition: fmi.h:1630
Data structure to holds an AOBRD shipment info. Used by the FmiApplicationLayer to provision shipment...
Definition: AobrdShipment.h:23
Data type for the Message Status Packet ID.
Definition: fmi.h:1551
uint8 result_code
Result code, a valid speed_limit_alert_result_data_type.
Definition: fmi.h:1651
boolean result_code
True if the update was successful.
Definition: fmi.h:1444
uint8 id[16]
Message ID from the canned_response_list_data_type.
Definition: fmi.h:1402
Data type for File Transfer End.
Definition: fmi.h:1323
sint16 mClientSoftwareVersion
Raw software version reported by the client.
void put(T &aValue)
Add (or replace) an item in the map.
int mAOBRDCurrentAnnotationTxIndex
Iterator for annotations being sent to device.
time_type getServerTimestamp() const
Get item&#39;s server timestamp.
aobrd_download_receipt_result_code result_code
Definition: fmi.h:1865
Payload of FMI_ID_A602_STOP packet.
Definition: fmi.h:1220
void endFileReceive()
Save received file chunk.
uint8 id_size
Number of significant bytes in the message ID.
Definition: fmi.h:1716
uint16 getTimeZone() const
Get item&#39;s time zone.
char text[51]
Text/description of the stop. Variable length, null-terminated string.
Definition: fmi.h:1224
uint32 status_change_id
unique identifier
Definition: fmi.h:1479
uint16 unique_id
Server-assigned unique ID from the FMI_ID_WAYPOINT packet.
Definition: fmi.h:1680
Data type for the Driver Profile Data Packet ID (0X1103) from client to server.
Definition: fmi.h:1760
Data type for Dashcam Notification Packet ID (0X160C) from client to server (request) ...
Definition: fmi.h:2337
uint32 mFileTransferBytesDone
Number of bytes of the file that have been transferred so far.
uint32 status_id
status_id from the driver_status_list_item_data_type or driver_status_list_item_delete_data_type ...
Definition: fmi.h:1462
double_position_type position
Current position of the client.
Definition: fmi.h:1072
void sendDriverIdRequest()
Ask the client for the current Driver ID.
char mSentDriverId[50]
The last driver ID that was sent to the client.
Data type for the FMI Safe Mode setup Packet ID.
Definition: fmi.h:1608
boolean finished_flag
Definition: fmi.h:1885
#define FMI_SUPPORT_A623
If true, app was built with support for A622 protocols.
Definition: fmi.h:93
FileBackedMap< DriverLoginItem > mDriverLogins
Map of allowed driver IDs and passwords.
bool sendCannedResponseTextMessage(const char *aMessageText, const MessageId &aMessageId, uint8 aResponseCount, const uint32 *aResponseList, uint8 aMessageType)
Initiate the canned response text message protocol.
uint32 crc
CRC of entire file as computed by UTL_calc_crc32.
Definition: fmi.h:1325
void UTIL_format_date_string(const date_time_data_type *aDateTime, char *aResultString, int aResultStringSize)
Format a date as a string.
Definition: util.cpp:657
uint32 unique_id
Unique ID of the A603 stop.
Definition: fmi.h:1203
char driver_id[50]
New driver ID (null terminated string)
Definition: fmi.h:1423
uint8 response_count
Number of elements in response_id array.
Definition: fmi.h:1381
uint32 UTL_calc_crc32(uint8 const *const data, uint32 const size, uint32 const initial_value)
Compute and finalize a 32-bit in one shot.
Definition: utl_crc.cpp:78
char new_text[50]
Text to display.
Definition: fmi.h:1564
sint32 latitude
Latitude of the device sending the message.
Definition: EventId.h:155
char mDriverStatus[FMI_DRIVER_COUNT][50]
Last driver status received from the client.
uint8 message_type
Message type, a valid a604_message_type.
Definition: fmi.h:1334
uint32 status_change_id
status_change_id from the driver_status_data_type
Definition: fmi.h:1499
uint16 cat_id
Category that was deleted (0-15)
Definition: fmi.h:1708
void startFileReceive(const file_info_data_type &file_size)
Save received file chunk.
uint8 time_over
Seconds until speeding event begins.
Definition: fmi.h:1641
CString getDriverId() const
Get the driver ID as a CString.
CString getFirstName() const
Get item&#39;s first name.
Garmin serial packet.
Definition: GarminPacket.h:26
Payload of FMI_ID_CLIENT_TXT_MSG_RCPT packet.
Definition: fmi.h:1167
uint16 features[126]
Array of feature IDs.
Definition: fmi.h:1119
char driver_id[50]
New driver ID (null terminated string, 50 bytes max)
Definition: fmi.h:1411
Payload of FMI_ID_A607_CLIENT_OPEN_TXT_MSG packet.
Definition: fmi.h:1176
#define SAVE_AOBRD_LOG
File name of the compressed AOBRD log.
boolean result_code
True if the update was successful.
Definition: fmi.h:1617
boolean result_code
True if the update was successful.
Definition: fmi.h:1463
uint8 id_type
Garmin packet ID.
Definition: garmin_types.h:101
uint8 driver_idx
Index of driver changed.
Definition: fmi.h:1445
char mEtaLatitude[14]
String representing the latitude in decimal degrees (and N or S)
void sendStopMoveRequest(uint16 aMoveToIndex, uint16 aMoveFromIndex)
Send a stop move request.
char message[50]
Message text, variable length, null terminated (50 bytes max)
Definition: fmi.h:1520
void sendA607DriverIdUpdate(char *aDriverId, uint8 aIndex)
Send an A607 Driver ID Update to the client.
FMI_eta_setting_rcode return_code
Definition: fmi.h:2360
Definition: fmi.h:954
uint16 symbol
Waypoint symbol.
Definition: fmi.h:1669
Data type for Dashcam Notification Packet ID (0X1606) from client to server (request) ...
Definition: fmi.h:2328
FileBackedMap< ClientListItem > mCannedResponses
Map of canned response IDs to names.
char comment[50+1]
Waypoint comment, null-terminated.
Definition: fmi.h:1673
CTime mLastClientPingTime
Last time when a client to server ping was received.
CString getCurrentName() const
Get the current name of this item.
STL namespace.
uint32 next_offset
offset of next data the server should send, or 0xFFFFFFFF for an error
Definition: fmi.h:1318
void sendNextAOBRDShipment(char *driver_id)
Send next AOBRD shipment to device.
void sendFmiPacket(uint16 aFmiPacketId, uint8 *aFmiPayload, uint8 aFmiPayloadSize)
Send an arbitrary FMI packet.
Data type for Route Calculation ACK Receipt Packet ID (0X1221) from server to client.
Definition: fmi.h:1951
uint32 status_change_id
Unique ID for this driver ID change.
Definition: fmi.h:1419
bool convertAnnotation(std::vector< std::string > &record, fmi_driver_annotation_data_type *annotation)
Convert an Annotation record to structure sent to FMI device.
uint8 mFileVersionLength
Number of significant bytes in mFileVersion.
#define maxval(_x, _y)
The larger of _x and _y.
Definition: util_macros.h:100
uint32 message_id
The message ID.
Definition: EventId.h:150
uint32 mActiveStopId
Unique ID of the active stop.
Payload for Garmin ID_UNIT_ID packet.
Definition: fmi.h:1093
Data type for File Data Packet ID.
Definition: fmi.h:1305
void UTIL_format_time_string(const date_time_data_type *aDateTime, char *aResultString, int aResultStringSize)
Converts a time structure (date_time_data_type) to a time string representation.
Definition: util.cpp:575
uint8 result_code
Result of operation.
Definition: fmi.h:1288
uint8 id[16]
Message ID that this list is for.
Definition: fmi.h:1383
uint8 file_version_length
Number of significant bytes in file_version.
Definition: fmi.h:1277
uint16 product_id
Product ID of the client.
Definition: fmi.h:1102
CString mAOBRDAnnotationDriverId
Driver ID for annotations being sent to device.
bool mLongTextMessageInProgress
Indicates whether a long text message is in progress.
uint16 stop_index_in_list
The stop index in list.
Definition: fmi.h:1205
uint32 response_id[50]
Canned response IDs.
Definition: fmi.h:1392
Data type for the User Interface Text Packet ID.
Definition: fmi.h:1561
void sendMessageThrottlingUpdate(uint16 aPacketId, uint16 aNewState)
Sends an update to the client to tell it whether to enable or disable a protocol. ...
uint8 id_size
ID size of message being responded to.
Definition: fmi.h:1181
const_iterator end()
Iterator positioned after the last element in the map.
Definition: FileBackedMap.h:67
MessageId message_id
The message ID that was ACKed.
Definition: EventId.h:143
bool contains(const key_type &aKey)
Check whether the specified key is in the map.
Definition: FileBackedMap.h:78
uint16 new_state
New state, see message_throttling_state_type for valid values.
Definition: fmi.h:1582
#define cnt_of_array(_a)
The number of elements in _a.
Definition: util_macros.h:90
time_type status_change_time
timestamp of status change
Definition: fmi.h:1489
char mEtaDistance[13]
Null-terminated ASCII string containing the distance to the current destination, including units...
uint32 unique_id
unique_id from client_to_server_open_text_msg_data_type
Definition: fmi.h:1169
Packet receipt for Packet Receipt Packet ID.
Definition: fmi.h:1315
#define offset_of(_s, _m)
The offset of _m from the beginning of _s.
Definition: util_macros.h:84
uint32 status_id
ID for the driver status list item to delete.
Definition: fmi.h:1472
#define FALSE
Definition: garmin_types.h:46
const key_type & getId() const
Get item&#39;s ID.
void sendDriverIdUpdate(char *aDriverId)
Send a Driver ID Update to the client.
uint16 countRecords(const char *source, evt_log_reason type)
Count records by type.
Data type for the User Interface Text Receipt Packet ID.
Definition: fmi.h:1569
void sendCreateWaypointCat(uint8 aCatId, CString &aCatName)
Create waypoint category.
Data type for the A604 Server to Client Open Text Message Packet ID.
Definition: fmi.h:1330
Utility for converting between raw AOBRD data to human- readable CSV file. Used to attempt to auto-co...
void sendEnable(uint16 *aFeatureCodes=NULL, uint8 aFeatureCount=0)
Transmit an FMI Enable packet, and clear any error state.
void commitName()
Commit the item name.
void sendA602TextMessage(fmi_id_type aFmiPacketId, char *aMessageText, const MessageId &aMessageId)
Send a server to client text message, for all A602 FMI protocols.
double UTIL_convert_radians_to_degrees(double aRadians)
Converts a latitude/longitude from radians to degrees.
Definition: util.cpp:247
void sendDeleteCannedMessageRequest(uint32 aMessageId)
Send a request to the client to delete a canned message.
bool sendA611LongTextMessage(const char *aMessageText, const MessageId &aMessageId, uint8 aMessageType)
Send an A611 server to client long text message.
Data type for the Shipment Download Receipt Packet ID (0X110B) from client to server.
Definition: fmi.h:1835
FileBackedMap< StopListItem > mA603Stops
Map of unique ID to stop details for all A603 stops on the client.
boolean result_code
Result code. TRUE if success, FALSE otherwise.
Definition: fmi.h:1346
uint8 id_size
Number of significant bytes in the message ID.
Definition: fmi.h:1553
void sendTextMessageStatusRequest(const MessageId &aMessageId)
Ask the server for the aStopStatus of a text message.
bool mRefreshingCannedResponses
If TRUE, FmiApplicationLayer is handling a request to refresh the canned response list...
void sendAOBRDOdometerValue(uint32 aOdometer)
Send AOBRD Odometer value to device.
uint32 unique_id
Unique ID of the stop for use with the Stop Status protocol.
Definition: fmi.h:1195
uint8 status_code
Message status, see fmi_A604_message_status for valid values.
Definition: fmi.h:1554
float32 altitude
Altitude above the WGS84 ellipsoid, in meters.
Definition: fmi.h:1066
MessageId msg_id
The message ID.
Definition: EventId.h:165
uint16 getLoadTypeRuleset() const
Get item&#39;s load type ruleset.
void setValid(BOOL aValid=TRUE)
Set this item as valid.
virtual bool rx(const Packet *aPacket)
Handle a packet received from the client.
Data type for the Driver Status Update Receipt packet.
Definition: fmi.h:1497
void sendWaypoint(uint16 aUniqueId, double aLat, double aLon, uint16 aSymbol, CString &aName, uint16 aCat, CString &aComment)
Send a waypoint.
Data type for the Text Message Ack Receipt Packet ID.
Definition: fmi.h:1587
Data structure to hold details of an A603 stop that the server needs to keep.
Definition: StopListItem.h:21
bool mStopFileTransfer
Flag to indicate that the user wants to stop the file transfer.
Data type for the Delete Canned Message Packet ID.
Definition: fmi.h:1525
Data type for Driver ID Update Packet ID.
Definition: fmi.h:1407
message_throttling_data_type response_list[60]
One element for each protocol with ID and state.
Definition: fmi.h:1601
uint32 unit_id
Unit ID (ESN) of the client.
Definition: fmi.h:1095
Data type for the ETA Data Receipt Packet ID.
Definition: fmi.h:1258
id_type mFreeformFmiPacketId
Defaults to ID_FMI_PACKET unless overridden on command line.
void sendA602Stop(double aLatitude, double aLongitude, char *aStopName)
Initiates the A602 stop protocol.
uint32 status_change_id
Unique ID for this driver ID change.
Definition: fmi.h:1409
uint32 mFileTransferSize
Total number of bytes in the file being transferred.
#define TRUE
Definition: garmin_types.h:45
List of canned responses that the client requests updated text for.
Definition: fmi.h:1389
FileBackedMap< InboxListItem > mSentCannedResponseMessages
List of message IDs for canned response text messages.
time_type origination_time
Time when the stop was originated by the server.
Definition: fmi.h:1193
Payload of FMI_ID_STOP_STATUS and FMI_ID_STOP_STATUS_REQUEST packets.
Definition: fmi.h:1201
CTime mLastServerPingTime
Last time when a server to client ping was received.
Data type for the Driver Login Data Packet ID (0X1101) from client to server.
Definition: fmi.h:1743
FileBackedMap< AobrdDriverItem > mAOBRDDrivers
Map of allowed driver IDs and passwords.
Data type for Driver ID Request Packet ID.
Definition: fmi.h:1432
char mClientUnitId[11]
Null-terminated ASCII string containing the Unit ID (ESN) of the client.
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
void removeStopByIndex(uint16 aDeletedStopIndex)
Remove a deleted stop.
signed short int sint16
16-bit signed integer
Definition: garmin_types.h:57
void continueFileReceive(uint32 offset, uint8 length, uint8 const *data)
Save received file chunk.
void sendEtaRequest()
Send a request for ETA data.
Date & time data type with separate fields for month, day, year, hour, minute, and second...
Definition: garmin_types.h:150
TransportLayer * mTransportLayer
The next layer down in the stack.
float32 up_velocity
Up velocity in m/s, negative is down.
Definition: fmi.h:1075
double UTIL_convert_semicircles_to_degrees(sint32 aSemicircles)
Converts a latitude/longitude from semicircles to degrees.
Definition: util.cpp:260
Data type for the User Interface Text Receipt Packet ID.
Definition: fmi.h:1615
char ack_text[50]
Text of the ack (OK, Yes, No, or a canned response)
Definition: EventId.h:144
void sendDeleteDriverStatusListItem(uint32 aDriverStatusId)
Initiate the Delete Driver Status List Item protocol.
uint32 response_id
Unique ID of this canned response.
Definition: fmi.h:1355
sint32 lat
latitude in semicircles
Definition: garmin_types.h:126
time_type status_change_time
Time when the driver ID changed.
Definition: fmi.h:1420
#define MAX_THROTTLED_PROTOCOLS
Maximum number of protocols that can be throttled.
Definition: fmi.h:132
#define INVALID32
Placeholder for an invalid 32-bit value.
Definition: fmi.h:139
void sendSetSpeedLimitAlerts(uint8 aMode, uint8 aTimeOver, uint8 aTimeUnder, boolean aAlertUser, float aThreshold)
Set FMI speed limit alerts.
char mPvtDate[11]
Date from the last PVT packet, as an ASCII null-terminated string of the form MM/DD/YYYY.
bool mActiveRoute
If TRUE, the client has a stop active.
time_type getServerStartTime() const
Get item&#39;s server start time.
uint8 id[16]
The message ID from the server to client open text message.
Definition: fmi.h:1348
time_type status_change_time
timestamp of status change
Definition: fmi.h:1480
float64 lat
latitude in radians, positive is north
Definition: garmin_types.h:137
uint16 packet_id
First packet ID in the protocol to throttle.
Definition: fmi.h:1581
message_throttling_data_type mThrottledProtocols[60]
Response from the last Message Throttling Query Protocol.
void setCurrentName(CString aName)
Set the current name of the stop.
Data type for the Message Status Request Packet ID.
Definition: fmi.h:1714
CString getCarrierName() const
Get item&#39;s carrier name.
Payload of server to client messages requiring a response (A602)
Definition: fmi.h:1134
time_type origination_time
Time when the message was sent by the client.
Definition: fmi.h:1160
FMI_eta_mode_type new_setting
Definition: fmi.h:2359
char text_message[200]
The message text (variable length, null terminated, 200 bytes max)
Definition: fmi.h:1128
Payload of FMI_ID_TEXT_MSG_ACK packet.
Definition: fmi.h:1145
CString getShipperName() const
Get item&#39;s shipper name.
#define SAVE_AOBRD_DRIVERS
File name of the saved AOBRD driver info.
#define minval(_x, _y)
The smaller of _x and _y.
Definition: util_macros.h:95
codepage_type mClientCodepage
Code page used for encoding of text fields when communicating with the client.
uint8 time_under
Seconds until speeding event ends.
Definition: fmi.h:1642
time_type adverse_condition_time
Definition: fmi.h:2046
time_type timestamp
Timestamp of the alert that is being acknowledged.
Definition: fmi.h:1659
uint16 UTIL_hex_to_uint8(const char *aHexString, uint8 *aBinaryData, uint16 aMaxBytes)
Convert a hexadecimal ASCII string to an array of uint8.
Definition: util.cpp:323
#define SAVE_STOPS
File name of the saved stops data.
uint8 data_length
length of file_data (0..245)
Definition: fmi.h:1308
uint16 getLongTermRuleset() const
Get item&#39;s long term ruleset.
uint8 id_size
Number of significant bytes of the message ID.
Definition: fmi.h:1137
void clear()
Remove all elements from the map.
Definition: FileBackedMap.h:88
char mPvtEastWestVelocity[15]
East-west velocity in meters per second from the last PVT packet, as an ASCII null-terminated string...
uint32 stop_time
Minimum stop time before auto-arrival is activated, in seconds.
Definition: fmi.h:1242
bool empty()
Check whether the map is empty.
Data type for Dashcam Get Settings Packet ID (0X1605) from client to server.
Definition: fmi.h:2290
uint32 unique_id
Unique ID generated by client.
Definition: fmi.h:1161
FmiApplicationLayer(id_type freeformFmiPacketId)
Constructor.
int mAOBRDStopShipmentTxIndex
Iterator end for shipments being sent to device.
float float32
32-bit IEEE-format floating point data. (1 sign bit, 8 exponent bits, and 23 mantissa bits) ...
Definition: garmin_types.h:70
#define setbit(_b)
A bit mask with one bit set and the rest cleared.
Definition: util_macros.h:30
Data type for the Set Canned Message Packet ID.
Definition: fmi.h:1517
uint32 driver_status
ID corresponding to the new driver status.
Definition: fmi.h:1490
char mProtocols[PROTOCOL_SIZE]
Null-terminated ASCII string containing the protocols supported by the client.
Data type for the Message Status Request Packet ID.
Definition: fmi.h:1542
bool mUseMultipleDrivers
If true, multiple driver support is enabled.
#define FMI_SUPPORT_A607
If true, app was build with support for A607 protocols.
Definition: fmi.h:42
Data type for FMI_ID_WAYPOINT packet.
Definition: fmi.h:1666
char mPvtTime[13]
Time from the last PVT packet.
void sendStopStatusRequest(uint32 aStopId, stop_status_status_type aStopStatus, uint16 aMoveToIndex=INVALID16)
Initiate the Stop Status protocol to update an A603 stop.
int mServerPingCount
Number of server-to-client pings sent; can be reset by the user.
#define SAVE_SENT_CAN
File name of the saved sent canned response message data.
char mHorizontalVelocity[15]
2-D velocity in the horizontal plane in meters per second from the last PVT packet, as an ASCII null-terminated string
void sendUserInterfaceText(uint32 aElementId, char *aText)
Request that the text of a particular user interface text element be changed.
sint32 week_number_days
Days since December 31st, 1989 to beginning of week (i.e., this is a Sunday)
Definition: garmin_types.h:145
Payload of FMI_ID_CLIENT_OPEN_TXT_MSG packet.
Definition: fmi.h:1158
void setUpdateName(CString aName)
Set pending name.
#define SAVE_RECEIVED_AOBRD_LOG
#define FMI_DRIVER_COUNT
Number of supported drivers.
Definition: fmi.h:147
void sendFreeformFmiPacket(fmi_id_type const aFmiPacketId, uint8 const *const aFmiPayload, uint8 const aFmiPayloadSize)
float32 east_velocity
East velocity in m/s, negative is west.
Definition: fmi.h:1073
#define SAVE_CAN_MSG
File name of the saved canned message data.
Data type for Long Text Message Request Packet ID (0X0055) from server to client. ...
Definition: fmi.h:1873
uint8 driver_idx
Driver index to change.
Definition: fmi.h:1434
Payload of FMI_ID_A603_STOP packet.
Definition: fmi.h:1191
char text[200]
Text (description) of stop. Variable length, null-terminated string.
Definition: fmi.h:1196
void remove(const key_type &aKey)
Remove an item from the map.
static SerialPort * getInstance()
Get the one and only serial port object.
Definition: SerialPort.cpp:36
void txCommand(command_type const aCommandId)
Transmit Garmin command packet (packet ID = ID_COMMAND_BYTE)
bool mRefreshingCannedMessages
If TRUE, FmiApplicationLayer is handling a request to refresh the canned message list.
#define FMI_SUPPORT_A616
If true, app was built with support for A616 protocols.
Definition: fmi.h:72
int mAOBRDStopAnnotationTxIndex
Iterator end for annotations being sent to device.
sc_position_type position_of_destination
Location of destination.
Definition: fmi.h:1253
time_type origination_time
Definition: fmi.h:1876
Definition: fmi.h:955
void sendCannedMessage(uint32 aMessageId, CString aMessageText)
Transmit a new or updated canned message to the client.
Data type for Baud Rate Change Receipt Packet ID (0x0012) from client to server.
Definition: fmi.h:2124
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
#define FMI_SUPPORT_A603
If true, app was build with support for A603 protocols.
Definition: fmi.h:30
uint8 driver_idx
Index of the driver to update.
Definition: fmi.h:1501
char mDriverId[FMI_DRIVER_COUNT][50]
Last driver ID received from the client.
bool mStopListInitialized
If TRUE, the stop list has been initialized.
void sendDeleteCannedResponseRequest(uint32 aResponseId)
Send a request to the client to delete a canned response.
#define FMI_SUPPORT_A602
If true, app was build with support for A602 protocols.
Definition: fmi.h:27
#define FMI_SUPPORT_A611
If true, app was built with support for A611 protocols.
Definition: fmi.h:57
signed long int sint32
32-bit signed integer
Definition: garmin_types.h:59
uint32 getNextStopId()
Find an available stop ID.
void sendNextAOBRDAnnotation(char *driver_id)
Send next AOBRD annotation to device.
uint8 result_code
Definition: fmi.h:1946
uint8 mPayload[MAX_PAYLOAD_SIZE]
The payload, before DLE stuffing.
Definition: GarminPacket.h:49
uint8 file_version[16]
Server-defined version string.
Definition: fmi.h:1280
Data type for the Shipment Download Response Packet ID (0X110A) from server to client.
Definition: fmi.h:1821
uint8 result_code
Enum indicating result code, see canned_response_list_result for valid values.
Definition: fmi.h:1400
Data type for the Speed Limit Alert Receipt Packet ID.
Definition: fmi.h:1657
uint8 mFileVersion[16]
file version (FMI_GPI_FILE_INFORMATION)
uint8 id[16]
ID of message being responded to.
Definition: fmi.h:1183
Data type for Custom Forms Packet ID (0X1203, 0X1205) from client to server.
Definition: fmi.h:1931
Data type for the Annotation Download Response Packet ID (0X110D) from server to client.
Definition: fmi.h:1850
static bool convertAnnotationRecord(AobrdEventLogConverter *converter, std::vector< std::string > &record, void *data)
CString getLastName() const
Get item&#39;s last name.
Data type for AOBRD Driver Logoff Request Packet ID (0X1310) from server to client.
Definition: fmi.h:2071
Data type for Delete Driver Status List Item Receipt.
Definition: fmi.h:1470
#define SAVE_RECEIVED_FORM_SUBMIT
File name of the saved custom form submission file.
uint8 mBaudRateSyncRateType
Mark which baud rate is currently being synced.
Data type for Driver ID Receipt packet.
Definition: fmi.h:1441
#define FMI_SUPPORT_A610
If true, app was build with support for A610(AOBRD) protocols.
Definition: fmi.h:54
char status[50]
Text displayed for the item (variable length, null terminated, 50 bytes max)
Definition: fmi.h:1454
CString getCommodity() const
Get item&#39;s commodity.
#define INVALID_LAT
placeholder for invalid latitude value
Definition: fmi.h:136
Data type for the Speed Limit Alert Packet ID.
Definition: fmi.h:1625
uint32 mFileSize
file size (FMI_GPI_FILE_INFORMATION)
uint32 offset
offset of data received
Definition: fmi.h:1317
FileBackedMap< ClientListItem > mDriverStatuses
Map of driver status IDs to names.
unsigned short int uint16
16-bit unsigned integer
Definition: garmin_types.h:64
boolean alert_user
Audibly alert the driver.
Definition: fmi.h:1643
Data type for the A607 Driver Status Update packet.
Definition: fmi.h:1486
void sendDriverStatusListItem(uint32 aDriverStatusId, CString aDriverStatusText)
Initiate the Set Driver Status List Item protocol.
Definition: fmi.h:953
void rebootDevice()
Send a command to the attached device to reboot it.
time_type server_timestamp
Definition: fmi.h:1823
id_type mPacketId
A complete serial packet.
Definition: GarminPacket.h:44
Data type for Baud Rate Change Request Packet ID (0x0011) from server to client.
Definition: fmi.h:2116
float32 speed
FMI safe mode speed.
Definition: fmi.h:1610
Abstract base class for a packet of data.
Definition: Packet.h:18
char mCannedResponseMessageBody[TEXT_MSG_BUFFER_MAX_SIZE]
The message text for the server to client canned text message.
char mPVTFixType[9]
GPS fix type from the last PVT packet, interpreted as an null-terminated ASCII string.
void resetCannedResponseMessages()
Clear the canned response text messages on the server.
boolean result_code
True if the update was successful.
Definition: fmi.h:1572
time_type origination_time
Origination time on the client.
Definition: EventId.h:151
Payload for Garmin ID_PVT_DATA packet.
Definition: fmi.h:1064
CString mAOBRDShipmentDriverId
Driver ID for shipments being sent to device.
virtual void tx(Packet *aPacket, bool aSendNow)=0
Transmit a packet.
Data type for Custom Forms Packet ID (0X1201) from client to server.
Definition: fmi.h:1915
void sendEnablePvtCommand(bool aEnable)
Send an Enable PVT or Disable PVT command.
uint8 id_size
Number of significant bytes of the message ID.
Definition: fmi.h:1148
void sendDeleteWaypointCat(uint16 aCatIdx)
Delete waypoint category.
void resetCannedMessages()
Clear the canned messages on the server.
void sendA603Stop(double aLatitude, double aLongitude, char *aStopName, uint32 aStopId)
Initiates the A603 stop protocol.
uint16 stop_status
The stop status.
Definition: fmi.h:1204
void sendDriverStatusRequest()
Asks the client for the current driver status.
char message_text[200]
Message sent by the client.
Definition: EventId.h:152
Stores the name associated with a list item that is sent to the client.
sc_position_type scposn
Position when the text message was created by the client.
Definition: fmi.h:1179
char driver_id[50]
Definition: fmi.h:1762
uint32 offset
offset of this data from the beginning of the file
Definition: fmi.h:1307
Data type for the Set Driver Status List Item and Delete Driver Status List Item Receipt packets...
Definition: fmi.h:1460
Data type for the Set Driver Status List Item packet.
Definition: fmi.h:1451
Data type for the Driver Profile Data Packet ID (0X1104) from server to client.
Definition: fmi.h:1767
MessageId link_id
ID of server-to-client message that this is a reply for.
Definition: EventId.h:154
time_type status_change_time
Time when the driver ID changed.
Definition: fmi.h:1410
bool mEnablePending
If true, the FMI Enable protocol is in progress.
void sendDriverStatusUpdate(uint32 aDriverStatusId)
Initiate the Driver Status Update protocol.
uint8 baud_rate_type
Definition: fmi.h:2119
Data type for the Message Throttling Command Packet ID and Message Throttling Response Packet ID...
Definition: fmi.h:1579
Data type for the FMI_ID_WAYPOINT_RCPT packet.
Definition: fmi.h:1678
Data structure to holds an AOBRD driver info. Used by the FmiApplicationLayer to validate logins when...
#define SAVE_WAYPOINTS
File name of the saved waypoint data.
void setCategories(uint16 val)
Set the waypoint&#39;s categories.
uint32 data_type
Type of data to delete, see del_data for valid values.
Definition: fmi.h:1267
void clearError()
Clear any communication error.
Data type for the File Transfer Start Packet ID.
Definition: fmi.h:1274
sint16 software_version
Software version * 100 (312 means version 3.12)
Definition: fmi.h:1103
uint32 distance_to_destination
Distance to destination, in meters, or 0xFFFFFFFF if no active destination.
Definition: fmi.h:1252
Data type for Dashcam Notifictation Packet ID (0X160A) from server to client (receipt) ...
Definition: fmi.h:2321
Structure containing details for a client to server text message.
Definition: EventId.h:148
uint32 unique_id
Uniquely identifies the ETA message.
Definition: fmi.h:1250
uint32 unique_id
Unique ID from eta_data_type.
Definition: fmi.h:1260
transfer_state mFileTransferState
State of the current file transfer (in progress, completed, etc.)
sc_position_type stop_position
Location of the stop.
Definition: fmi.h:1223
const char * getReceiveFilename(uint8 file_type) const
Determine which filename to store a received file under.
boolean result_code
TRUE if the operation was successful, FALSE otherwise.
Definition: fmi.h:1681
virtual void onAck(const Packet *aPacket)
Callback when a packet is ACKed by the client.
Data type for the Annotation Download Request Packet ID (0X110C) from client to server.
Definition: fmi.h:1843
Data type for Long Test Message Receipt Packet ID (0X0056) from client to server. ...
Definition: fmi.h:1899
Transport layer in the OSI communication model.
Data type for the Speed Limit Alerts setup Receipt Packet ID.
Definition: fmi.h:1649
int mClientPingCount
Number of client-to-server pings received; can be reset by the user.
void sendAOBRDDriverProfile(const AobrdDriverItem &driver)
Send an AOBRD driver profile to the device.
char mPvtNorthSouthVelocity[15]
North-south velocity in meters per second from the last PVT packet, as an ASCII null-terminated strin...
Data type for the ETA Data Packet ID.
Definition: fmi.h:1248
uint8 id_size
Size of the message ID.
Definition: fmi.h:1380
Map whose contents are also saved to a file.
Definition: FileBackedMap.h:32
const std::vector< AobrdShipment > & getShipments() const
Get the list of shipments.
virtual ~FmiApplicationLayer()
Destructor.
Data type for the Set Canned Response Packet ID.
Definition: fmi.h:1353
uint16 stop_status_status_type
Enumeration for Stop Status protocol.
Definition: fmi.h:962
char password[20]
Driver password (null terminated string). Optional if driver password support is not enabled...
Definition: fmi.h:1424
uint8 id_size
Size of the message ID.
Definition: fmi.h:1589
Indicates a latitude and longitude in semicircles.
Definition: garmin_types.h:124
time_type origination_time
Origination time of the message.
Definition: fmi.h:1136
#define GZIPPED_TRANSFER_FILENAME
Name of transient file for storing the gzipped version of a file to transfer.
FileBackedMap< ClientListItem > mCategories
Map of waypoint category IDs to names.
const uint8 * getId() const
Return a reference to the bytes of the message ID.
Definition: MessageId.cpp:144
void sendDeleteWaypoint(uint16 aUniqueId)
Delete a waypoint.
bool mRefreshingDriverStatusList
If TRUE, FmiApplicationLayer is handling a request to refresh the driver status list.
uint32 text_element_id
ID of the user interface element being changed.
Definition: fmi.h:1563
void setStopStatus(stop_status_status_type aStatus)
Set the stop status.
Data type for the Driver Profile Data Packet ID (0X1110) from server to client and Driver Profile Dat...
Definition: fmi.h:2037
uint8 id[16]
The message ID.
Definition: fmi.h:1556
unsigned char uint8
8-bit unsigned integer
Definition: garmin_types.h:62
Data type for Route Calculation ACK Packet ID (0X1220) from client to server.
Definition: fmi.h:1942
time_type origination_time
Origination time when the server sent the stop to the client.
Definition: fmi.h:1222
uint32 message_id
ID of the canned message.
Definition: fmi.h:1535
uint8 mPayloadSize
Size of the payload, before DLE stuffing.
Definition: GarminPacket.h:46
uint8 getIdSize() const
Return the size of the message ID.
Definition: MessageId.cpp:152
void sendMessageDeleteRequest(const MessageId &aMessageId)
Ask the server to delete a text message.
void sendCannedResponse(uint32 aResponseId, CString aResponseText)
Transmit a new or updated canned response to the client.
Data type for the FMI_ID_CREATE_WAYPOINT_CAT packet.
Definition: fmi.h:1691
#define LONG_TEXT_MSG_CHUNK_SIZE
Maximum number of bytes in one segment of an A611 Long Text Message.
Definition: fmi.h:167
Payload for Garmin ID_PRODUCT_DATA (A000) and FMI FMI_ID_PRODUCT_ID_DATA (A602) packet.
Definition: fmi.h:1100
void resetDriverStatusList()
Clear the driver statuses on the server.
char mEtaLongitude[14]
String representing the longitude in decimal degrees (and E or W)
sint16 leap_seconds
Number of leap seconds as of the current time.
Definition: fmi.h:1077
uint32 message_id
ID of the canned message to delete.
Definition: fmi.h:1527
uint16 unique_id
Server-assigned unique ID for the waypoint.
Definition: fmi.h:1668
virtual void retry()=0
Retry the last transmit.
Data type for the ETA Data Receipt Packet ID.
Definition: fmi.h:2356
uint32 message_id
Unique identifier and sort key for this canned message.
Definition: fmi.h:1519
Data type for the Driver Status Log response Packet ID (0X1107) from server to client.
Definition: fmi.h:1805
char mPvtUpDownVelocity[15]
Up-down velocity in meters per second from the last PVT packet, as an ASCII null-terminated string...
void sendEtaModeRequest(FMI_eta_mode_type aModeType)
Send an ETA mode request.
uint8 id
Waypoint category (0-15)
Definition: fmi.h:1701
time_type eta_time
Estimated time of arrival, or 0xFFFFFFFF if no active destination.
Definition: fmi.h:1251
boolean result_code
Result (true if successful, false otherwise)
Definition: fmi.h:1536
void sendFile(char *aFilename, uint8 aVersionLength, uint8 *aVersion, uint8 aFileType, BOOL gzipIt=FALSE)
Start a file transfer protocol.
time_type UTIL_get_current_garmin_time()
Get the current server time in Garmin format.
Definition: util.cpp:603
void sendStopSortRequest()
Sends a sort stop list request to the client.
uint32 unique_id
unique_id from the stop_status_data_type.
Definition: fmi.h:1212
boolean result_code
True if the update was successful.
Definition: fmi.h:1500
Abstract base class for the application layer in the OSI model.
sint16 data
Protocol number.
Definition: fmi.h:1111
uint32 mSentDriverStatus
The last driver status that was sent to the client.
Data type for the Message Throttling Query Response Packet ID.
Definition: fmi.h:1598
uint32 status_id
Unique identifier and sort key for the status item.
Definition: fmi.h:1453
FileBackedMap< ClientListItem > mCannedMessages
Map of canned message IDs to names.
uint16 mClientProductId
Numeric product ID reported by the client.
Structure containing details for a text message status from the client.
Definition: EventId.h:163
uint8 id_size
Size of the message ID.
Definition: fmi.h:1345
Data type for the Driver Status Log Update Data Packet ID (0X1106) from client to server...
Definition: fmi.h:1798
char response_text[50]
Response text to display on client (variable length, null terminated string)
Definition: fmi.h:1356
void sendDataDeletionRequest(del_data aDataType)
Send a data deletion request and remove the appropriate data from the server.
uint32 file_size
Size of the file, in bytes.
Definition: fmi.h:1276
Data type for the Set Canned Message Receipt Packet ID and Delete Canned Message Receipt Packet ID...
Definition: fmi.h:1533
boolean result_code
TRUE if message was deleted, FALSE if message was not found.
Definition: fmi.h:1726
Data type for the Delete Canned Response Packet ID.
Definition: fmi.h:1361
time_type getServerEndTime() const
Get item&#39;s server end time.
void UTIL_calc_2d_direction(float32 aNorthVelocity, float32 aEastVelocity, char *aCardinalDirection, int aCardinalDirectionSize)
Determine the nearest cardinal aCardinalDirection.
Definition: util.cpp:692
time_type origination_time
Time the message was sent from the server.
Definition: fmi.h:1332
#define FMI_SUPPORT_A604
If true, app was build with support for A604 protocols.
Definition: fmi.h:33
time_type server_start_time
Definition: fmi.h:1824
Data type for the FMI_ID_CREATE_WAYPOINT_CAT_RCPT packet.
Definition: fmi.h:1699
uint8 driver_idx
Driver index to change.
Definition: fmi.h:1421
uint32 status_change_id
status_change_id from the driver_id_data_type
Definition: fmi.h:1443
Data type for File Start Receipt Packet ID and File End Receipt Packet ID.
Definition: fmi.h:1286
float64 lon
longitude in radians, positive is east
Definition: garmin_types.h:138
void resetWaypoints()
Clear the waypoint and waypoint category lists on the server.
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 removeStopById(uint32 aStopId)
Find the index of the deleted stop corresponding to a stop ID.
boolean result_code
True if the operation was successful.
Definition: fmi.h:1372
std::vector< uint32 > mStopIndexInList
Vector relating the stop list to unique_ids.
char mPvtLatitude[14]
Latitude in degrees from the last PVT packet, as an ASCII null-terminated string. ...
void stopFileTransfer()
Stop a file transfer protocol.
sint32 time_of_week
Seconds since 12:00 AM Sunday.
Definition: garmin_types.h:146
Data type for Custom Forms Packet ID (0X1207) from client to server.
Definition: fmi.h:2238
uint8 id[16]
The message ID.
Definition: fmi.h:1718
file_packet_data_type mLastFilePacketSent
The last file packet that was sent.
T & get(const key_type &aKey)
Get the item by key.
void sendGpiFileInfoRequest()
Send a GPI File Information Request to the client.
uint16 command_type
Garmin command ID (payload when packet ID == ID_COMMAND_BYTE)
Definition: fmi.h:260
Structure containing details for a text message ACK from the client.
Definition: EventId.h:141
void sendPing()
Send a ping packet to the client.
Tracks a waypoint that has been sent to the client.
CString getPassword() const
Set the ID (key) of this item.
uint8 file_type
File type.
Definition: fmi.h:1299
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
uint32 response_id
The canned response ID from the set or delete.
Definition: fmi.h:1371
fmi_A604_message_status
Enum for A604 message status protocol.
Definition: fmi.h:894
Payload of FMI_ID_AUTO_ARRIVAL packet.
Definition: fmi.h:1240
uint8 result_code
Definition: fmi.h:2126
void sendA607DriverStatusUpdate(uint32 aDriverStatusId, uint8 aIndex)
Initiate the A607 Driver Status Update protocol.
del_data
Enumeration for Data Deletion protocol.
Definition: fmi.h:982
void sendA604TextMessage(const char *aMessageText, const MessageId &aMessageId, uint8 aMessageType=A604_MESSAGE_TYPE_NORMAL)
Send an A604 server to client open text message.
time_type origination_time
Time when the client sent the message.
Definition: fmi.h:1127
#define SAVE_STATUS
File name of the saved driver status list data.
unsigned long int uint32
32-bit unsigned integer
Definition: garmin_types.h:66
char text_message[200]
Message text (variable length, null-terminated string)
Definition: fmi.h:1184
Data type for the Driver Status Update packet.
Definition: fmi.h:1477
uint32 convertToRaw(const char *source, const char *dest)
Convert CSV file to raw.
sint32 lon
longitude in semicircles
Definition: garmin_types.h:127
boolean procDriverStatusUpdate(uint32 aDriverStatusId, uint8 aDriverIndex=0)
Process a Driver Status Update from the client.
uint8 result_code
Result of operation.
Definition: fmi.h:1298
uint8 id[16]
message ID
Definition: fmi.h:1150
Data type for the FMI_ID_DELETE_WAYPOINT_CAT_RCPT packet.
Definition: fmi.h:1706
uint32 time_type
Absolute time (number of seconds since 12/31/1989 12:00 am UTC)
Definition: garmin_types.h:97
FileBackedMap< WaypointListItem > mWaypoints
Map of waypoint IDs to names.
Data type for the Driver Login Data Packet ID (0X1102) from server to client.
Definition: fmi.h:1752
uint8 id_size
Number of significant bytes in the message ID.
Definition: fmi.h:1333
Data type for the Canned Response List Packet ID.
Definition: fmi.h:1378
uint32 response_count
Number of responses in the array; if 0, all responses need refresh.
Definition: fmi.h:1391
uint8 id[16]
Message ID.
Definition: fmi.h:1591
char mPvtAltitude[13]
Altitude in meters from the last PVT packet, as an ASCII null-terminated string.
#define SAVE_CATEGORIES
File name of the saved category data.
uint32 response_id
The canned response ID to delete.
Definition: fmi.h:1363
uint8 feature_count
Number of feature IDs in features[].
Definition: fmi.h:1117
Inbox List Item.
Definition: InboxListItem.h:19
Data type for Canned Response List Packet ID.
Definition: fmi.h:1397
#define SAVE_RECEIVED_IFTA_FILE
uint8 request_type
Definition: fmi.h:2118
Data type for the Data Deletion Packet ID.
Definition: fmi.h:1265
long_text_msg_data_type mLongTextMessage[10]
Contains the data for the most recent long text message.
void sendFmiSafeModeSpeed(float speed)
Set FMI safe mode speed.
char mFilePath[200]
Path to the file that is being transferred to the client.
uint8 driver_idx
Index of driver to change.
Definition: fmi.h:1491
Encapsulation of a message ID.
Definition: MessageId.h:26
uint8 reserved
Set to 0.
Definition: fmi.h:1118
#define MAX_PAYLOAD_SIZE
Maximum payload size, before DLE stuffing.
Definition: garmin_types.h:21
Payload of FMI_ID_STOP_STATUS_RCPT packet.
Definition: fmi.h:1210
uint8 mCurrentSendFileType
Current file type for file being sent.
void sendMessageThrottlingQuery()
Initiate the Message Throttling Query protocol.
#define SAVE_CONVERTED_AOBRD_LOG
File name of the saved AOBRD driver event log.
Data structure to holds an allowed driver login (ID and password). Used by the FmiApplicationLayer to...
uint8 FMI_eta_mode_type
Definition: fmi.h:1045
uint16 type_of_gps_fix
Enum for type of GPS fix, see gps_fix_type.
Definition: fmi.h:1070
float32 north_velocity
North velocity in m/s, negative is south.
Definition: fmi.h:1074
uint8 mEtaMode
Unique ID of the active stop.
uint8 file_data[245]
file data, variable length
Definition: fmi.h:1310
uint32 week_number_days
Days from UTC December 31st, 1989 to beginning of current week.
Definition: fmi.h:1078
Data type for the Set Canned Response Receipt Packet ID and Delete Canned Response Receipt Packet ID...
Definition: fmi.h:1369
float64 time_of_week
Seconds since Sunday 12:00 AM (excludes leap seconds)
Definition: fmi.h:1071
char text_message[200]
Text message (variable length, null-terminated string, 200 bytes max)
Definition: fmi.h:1140
Data type for Dashcam Settings Packet ID (0X1601, 0X1603, 0x1607) from client to server.
Definition: fmi.h:2257
uint32 driver_status
ID corresponding to the new driver status.
Definition: fmi.h:1481
void sendAOBRDDriverLogoff(const AobrdDriverItem &driver)
Send an AOBRD driver logoff command to the device.
uint32 unique_id
Unique ID generated by client.
Definition: fmi.h:1180
uint32 stop_distance
Minimum distance to destination before auto-arrival is activated, in meters.
Definition: fmi.h:1243
uint8 id
Waypoint category.
Definition: fmi.h:1693
Data type for File Start Receipt Packet ID and File End Receipt Packet ID when sent from Server...
Definition: fmi.h:1296
uint16 cat
Waypoint categories, bit-mapped.
Definition: fmi.h:1671
uint32 distance
Definition: fmi.h:1945
static void post(EventId aEventId, uint32 aEventData=0, void *aEventDataPtr=NULL, BOOL handleNow=FALSE)
Posts a message to all windows that have registered to get events.
Definition: Event.cpp:67
float threshold
Speed over speed limit when speeding event begins.
Definition: fmi.h:1644
uint8 mode
Mode, a valid speed_limit_alert_mode_type.
Definition: fmi.h:1640
void resetCannedResponses()
Clear the canned responses on the server.
CString getDocNumber() const
Get item&#39;s document number.
Encapsulates the fields of a GPS time for conversion.
Definition: garmin_types.h:143
CString getCarrierID() const
Get item&#39;s carrier ID.
Data type for the Speed Limit Alerts setup Packet ID.
Definition: fmi.h:1638