Garmin Fleet Management Controller  2.19.0
CCdtPingDlg.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 *
3 * MODULE NAME:
4 * CCdtPingDlg.cpp
5 *
6 * Copyright 2014 by Garmin Ltd. or its subsidiaries.
7 *---------------------------------------------------------------------
8 * $NoKeywords$
9 *********************************************************************/
10 #include "stdafx.h"
11 #include "CCdtPingDlg.h"
12 
13 #if( CDT_SUPPORT )
14 
15 // CCdtPingDlg dialog
16 
17 IMPLEMENT_DYNAMIC(CCdtPingDlg, CDialog)
18 
19 enum TimerIdType
20 {
21  PING_TIMER_ID = 1
22 };
23 
24 BEGIN_MESSAGE_MAP(CCdtPingDlg, CDialog)
25  ON_WM_SIZE()
26  ON_MESSAGE( WM_EVENT( EVENT_CDT_PING_RECEIVED ), OnCDTPingReceived )
27  ON_BN_CLICKED(IDC_TOGGLE_PROCESS, &CCdtPingDlg::OnBnClickedToggleProcess)
28  ON_WM_TIMER()
29  ON_BN_CLICKED(IDC_CLEAR_RESULTS, &CCdtPingDlg::OnBnClickedClearResults)
30 END_MESSAGE_MAP()
31 
32 //----------------------------------------------------------------------
34 //----------------------------------------------------------------------
35 CCdtPingDlg::CCdtPingDlg(CWnd* pParent, FmiApplicationLayer & aCom)
36  : CDialog( CCdtPingDlg::IDD, pParent ),
37  mCom( aCom )
38  , mTimer( 0 )
39  , mInterval( 1000 )
40  , mPayloadSize( 0 )
41  , mRepeatIterations( 1 )
42  , mRepeatFixed( FALSE )
43  , mClearOnStart( TRUE )
44  {
45  }
46 
47 //----------------------------------------------------------------------
49 //----------------------------------------------------------------------
50 CCdtPingDlg::~CCdtPingDlg()
51 {
52  for( int i=0; i<mResults.GetCount(); i++ )
53  {
54  delete mResults[i];
55  }
56  mResults.RemoveAll();
57 }
58 
59 //----------------------------------------------------------------------
62 //----------------------------------------------------------------------
63 void CCdtPingDlg::DoDataExchange(CDataExchange* pDX)
64  {
65  CDialog::DoDataExchange(pDX);
66  DDX_Text(pDX, IDC_INTERVAL, mInterval);
67  DDV_MinMaxUInt(pDX, mInterval, 100, 5000);
68  DDX_Text(pDX, IDC_PAYLOAD_SIZE, mPayloadSize);
69  DDV_MinMaxUInt(pDX, mPayloadSize, 0, 246);
70  DDX_Text(pDX, IDC_REPEAT_ITERATIONS, mRepeatIterations);
71  DDV_MinMaxUInt(pDX, mRepeatIterations, 1, 1000);
72  DDX_Radio(pDX, IDC_REPEAT_INDEFINITELY, mRepeatFixed);
73  DDX_Control(pDX, IDC_PING_RESULTS, mResultsView);
74  DDX_Check(pDX, IDC_CLEAR_ON_START, mClearOnStart);
75  }
76 
77 //----------------------------------------------------------------------
80 //----------------------------------------------------------------------
81 BOOL CCdtPingDlg::OnInitDialog()
82  {
83  CDialog::OnInitDialog();
84 
85  mResultsView.InsertColumn( 0, _T( "Sent On" ), LVCFMT_LEFT, 120);
86  mResultsView.InsertColumn( 1, _T( "Responded On" ), LVCFMT_RIGHT, 120 );
87  mResultsView.InsertColumn( 2, _T( "Elapsed Time" ), LVCFMT_RIGHT, 100 );
88  mResultsView.InsertColumn( 3, _T( "Match" ), LVCFMT_CENTER, 50 );
89 
90  (( CSpinButtonCtrl*) GetDlgItem( IDC_REPEAT_ITERATIONS_SPINNER ) )->SetRange( 1, 1000 );
91  (( CSpinButtonCtrl*) GetDlgItem( IDC_INTERVAL_SPINNER ) )->SetRange( 100, 5000 );
92  (( CSpinButtonCtrl*) GetDlgItem( IDC_PAYLOAD_SIZE_SPINNER ) )->SetRange( 0, 246 );
93 
94  OnBnClickedClearResults();
95 
96  return TRUE;
97  }
98 
99 //----------------------------------------------------------------------
101 //----------------------------------------------------------------------
102 void CCdtPingDlg::OnBnClickedClearResults()
103  {
104  for( int i=0; i<mResults.GetCount(); i++ )
105  {
106  delete mResults[i];
107  }
108  mResults.RemoveAll();
109 
110  mResultsView.DeleteAllItems();
111  GetDlgItem( IDC_TOTAL_DELIVERED_STATIC )->SetWindowText( _T( "" ) );
112  GetDlgItem( IDC_AVG_ELAPSED_TIME_STATIC )->SetWindowText( _T( "" ) );
113  GetDlgItem( IDC_TOTAL_MISMATCHED_STATIC )->SetWindowText( _T( "" ) );
114  }
115 
116 //----------------------------------------------------------------------
118 //----------------------------------------------------------------------
119 void CCdtPingDlg::OnBnClickedToggleProcess()
120  {
121  if( mTimer == 0 )
122  {
123  if( !UpdateData() )
124  {
125  return;
126  }
127  if( mClearOnStart )
128  {
129  OnBnClickedClearResults();
130  }
131  mIteration = 0;
132  mTimer = SetTimer( PING_TIMER_ID, mInterval, NULL );
133  OnTimer( PING_TIMER_ID );
134  }
135  else
136  {
137  KillTimer( mTimer );
138  mTimer = 0;
139  }
140 
141  setStarted( mTimer != 0 );
142  }
143 
144 //----------------------------------------------------------------------
146 //----------------------------------------------------------------------
147 void CCdtPingDlg::setStarted( BOOL started )
148  {
149  GetDlgItem( IDC_TOGGLE_PROCESS )->SetWindowText( started ? _T( "Stop" ) : _T( "Start" ) );
150  GetDlgItem( IDC_REPEAT_INDEFINITELY )->EnableWindow( !started );
151  GetDlgItem( IDC_REPEAT_FIXED )->EnableWindow( !started );
152  GetDlgItem( IDC_REPEAT_ITERATIONS )->EnableWindow( !started );
153  GetDlgItem( IDC_REPEAT_ITERATIONS_SPINNER )->EnableWindow( !started );
154  GetDlgItem( IDC_INTERVAL )->EnableWindow( !started );
155  GetDlgItem( IDC_INTERVAL_SPINNER )->EnableWindow( !started );
156  GetDlgItem( IDC_PAYLOAD_SIZE )->EnableWindow( !started );
157  GetDlgItem( IDC_PAYLOAD_SIZE_SPINNER )->EnableWindow( !started );
158  }
159 
160 //----------------------------------------------------------------------
162 //----------------------------------------------------------------------
163 void CCdtPingDlg::OnTimer
164  (
165  UINT aTimerId
166  )
167 {
168  switch ( aTimerId )
169  {
170  case PING_TIMER_ID:
171  {
172  if( !mRepeatFixed || mIteration < mRepeatIterations )
173  {
174  COleDateTime now = COleDateTime::GetCurrentTime();
175  CdtPingTestPacket * packet = new CdtPingTestPacket( mPayloadSize );
176  mResults.Add( packet );
177  mCom.txCdt( CDT_PING_REQUEST, packet->GetPayload(), packet->GetPayloadSize() );
178  mIteration++;
179  mResultsView.InsertItem( mResultsView.GetItemCount(), now.Format( _T( "%Y-%m-%d %H.%M.%S" ) ) );
180  }
181  else
182  {
183  KillTimer( mTimer );
184  mTimer = 0;
185  setStarted( FALSE );
186  }
187  break;
188  }
189  }
190 }
191 
192 //----------------------------------------------------------------------
197 //----------------------------------------------------------------------
198 LRESULT CCdtPingDlg::OnCDTPingReceived( WPARAM wParam, LPARAM lParam)
199  {
200  DWORD tickCount = GetTickCount();
201  COleDateTime now = COleDateTime::GetCurrentTime();
202  sint16 cdtPayloadSize = (sint16) wParam;
203  uint8 const * cdtPayload = (uint8 const *) lParam;
204 
205  //must have at least the size of id field to be handled here
206  if( cdtPayloadSize < sizeof( DWORD ) )
207  {
208  return 0;
209  }
210  DWORD id = 0;
211  memcpy( &id, cdtPayload, sizeof( DWORD ) );
212  for( int i=0; i<mResults.GetCount(); i++ )
213  {
214  if( mResults[i]->GetId() == id )
215  {
216  mResults[i]->CompareResponse( tickCount, cdtPayloadSize, cdtPayload );
217  mResultsView.SetItemText( i, 1, now.Format( _T( "%Y-%m-%d %H.%M.%S" ) ) );
218  CString elapsed;
219  elapsed.Format( _T( "%d" ), mResults[i]->GetElapsedTimeMillis() );
220  mResultsView.SetItemText( i, 2, elapsed );
221  mResultsView.SetItemText( i, 3, mResults[i]->IsResponseMatched() ? _T( "yes" ) : _T( "no" ) );
222  break;
223  }
224  }
225 
226  double totalElapsed = 0;
227  int totalDelivered = 0;
228  int totalMismatched = 0;
229  for( int i=0; i<mResults.GetCount(); i++ )
230  {
231  if( mResults[i]->IsResponded() )
232  {
233  totalDelivered++;
234  totalElapsed += mResults[i]->GetElapsedTimeMillis();
235  if( !mResults[i]->IsResponseMatched() )
236  {
237  totalMismatched++;
238  }
239  }
240  }
241  CString delivered;
242  delivered.Format( _T( "%d/%d" ), totalDelivered, mResults.GetCount() );
243  GetDlgItem( IDC_TOTAL_DELIVERED_STATIC )->SetWindowText( delivered );
244  if( totalDelivered > 0 )
245  {
246  CString avgElapsed;
247  avgElapsed.Format( _T( "%.0f" ), totalElapsed / (double) totalDelivered );
248  GetDlgItem( IDC_AVG_ELAPSED_TIME_STATIC )->SetWindowText( avgElapsed );
249  }
250  CString mismatched;
251  mismatched.Format( _T( "%d" ), totalMismatched );
252  GetDlgItem( IDC_TOTAL_MISMATCHED_STATIC )->SetWindowText( mismatched );
253  return 0;
254  }
255 
256 static COleDateTime epoch(1970,1,1,0,0,0);
257 
258 //----------------------------------------------------------------------
260 //----------------------------------------------------------------------
261 CdtPingTestPacket::CdtPingTestPacket( UINT payloadSize ) :
262  mPayloadSize( min( sizeof( mPayload ) - sizeof( DWORD ), payloadSize ) ),
263  mRespondedOn( 0 ),
264  mResponseMatched( FALSE )
265  {
266  mId = GetTickCount();
267  memcpy( mPayload, &mId, sizeof( DWORD ) );
268  for( int i=0; i<mPayloadSize; i++ )
269  {
270  mPayload[i + sizeof( DWORD )] = rand() % 256;
271  }
272  mPayloadSize += sizeof( DWORD );
273  }
274 
275 CdtPingTestPacket::~CdtPingTestPacket() {}
276 
277 //----------------------------------------------------------------------
279 //----------------------------------------------------------------------
280 void CdtPingTestPacket::CompareResponse( DWORD respondedOn, const uint8 rightSize, const uint8 * right )
281  {
282  mRespondedOn = respondedOn;
283  if( rightSize == mPayloadSize )
284  {
285  for( int i=0; i<mPayloadSize; i++ )
286  {
287  if( mPayload[i] != right[i] )
288  {
289  return;
290  }
291  }
292  mResponseMatched = TRUE;
293  }
294  }
295 
296 //----------------------------------------------------------------------
298 //----------------------------------------------------------------------
299 int CdtPingTestPacket::GetElapsedTimeMillis()
300  {
301  if( mRespondedOn != 0 )
302  {
303  return mRespondedOn - mId;
304  }
305 
306  return 0;
307  }
308 
309 #endif
#define IDC_PAYLOAD_SIZE
Definition: resource.h:507
#define IDC_REPEAT_ITERATIONS_SPINNER
Definition: resource.h:509
#define IDC_REPEAT_ITERATIONS
Definition: resource.h:505
#define IDC_REPEAT_FIXED
Definition: resource.h:504
#define IDC_PING_RESULTS
Definition: resource.h:508
#define FALSE
Definition: garmin_types.h:46
#define TRUE
Definition: garmin_types.h:45
signed short int sint16
16-bit signed integer
Definition: garmin_types.h:57
#define IDC_PAYLOAD_SIZE_SPINNER
Definition: resource.h:515
#define IDC_TOTAL_DELIVERED_STATIC
Definition: resource.h:512
Serial communication controller for Garmin and FMI packets.
#define IDC_INTERVAL_SPINNER
Definition: resource.h:510
unsigned char uint8
8-bit unsigned integer
Definition: garmin_types.h:62
#define IDC_CLEAR_RESULTS
Definition: resource.h:502
#define IDC_INTERVAL
Definition: resource.h:506
#define IDC_AVG_ELAPSED_TIME_STATIC
Definition: resource.h:513
#define IDC_TOTAL_MISMATCHED_STATIC
Definition: resource.h:514
#define IDC_TOGGLE_PROCESS
Definition: resource.h:501
#define WM_EVENT(_event)
Translation from an application event to the corresponding Windows message.
TimerIdType
Timer ID values used in the application.
#define IDC_CLEAR_ON_START
Definition: resource.h:511
#define IDC_REPEAT_INDEFINITELY
Definition: resource.h:503