Garmin Fleet Management Controller  2.19.0
CCdtChatDlg.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 *
3 * MODULE NAME:
4 * CCdtChatDlg.cpp
5 *
6 * Copyright 2014 by Garmin Ltd. or its subsidiaries.
7 *---------------------------------------------------------------------
8 * $NoKeywords$
9 *********************************************************************/
10 #include "stdafx.h"
11 #include "CCdtChatDlg.h"
12 #include "comdef.h"
13 
14 #if( CDT_SUPPORT )
15 
16 // the limit imposed on a single message, which will get separated into
17 // chunks if greater than packet payload length
18 #define MAX_INPUT_LENGTH 1024
19 
20 // CCdtChatDlg dialog
21 
22 IMPLEMENT_DYNAMIC(CCdtChatDlg, CDialog)
23 
24 BEGIN_MESSAGE_MAP(CCdtChatDlg, CDialog)
25  ON_WM_SIZE()
26  ON_MESSAGE( WM_EVENT( EVENT_CDT_PACKET_RECEIVED ), OnCDTPacketReceived )
27 END_MESSAGE_MAP()
28 
29 //----------------------------------------------------------------------
31 //----------------------------------------------------------------------
32 CCdtChatDlg::CCdtChatDlg(CWnd* pParent, FmiApplicationLayer & aCom)
33  : CDialog( CCdtChatDlg::IDD, pParent ),
34  mCom( aCom )
35  {
36  }
37 
38 //----------------------------------------------------------------------
40 //----------------------------------------------------------------------
41 CCdtChatDlg::~CCdtChatDlg()
42 {
43  CoUninitialize();
44 }
45 
46 //----------------------------------------------------------------------
49 //----------------------------------------------------------------------
50 void CCdtChatDlg::DoDataExchange(CDataExchange* pDX)
51  {
52  CDialog::DoDataExchange(pDX);
53  DDX_Control( pDX, IDC_CDT_CHAT_LOG, mBrowser );
54  DDX_Control( pDX, IDC_CDT_CHAT_INPUT, mInputField );
55  }
56 
57 //----------------------------------------------------------------------
60 //----------------------------------------------------------------------
61 BOOL CCdtChatDlg::OnInitDialog()
62  {
63  CoInitialize(NULL);
64 
65  CDialog::OnInitDialog();
66 
67  mInputField.SetLimitText( MAX_INPUT_LENGTH );
68 
69  CRect rect1, rect2;
70  mBrowser.GetClientRect( &rect1 );
71  GetClientRect( &rect2 );
72  mPadding = ( rect2.Width() - rect1.Width() ) / 2;
73  mInputField.GetClientRect( &rect1 );
74  mInputHeight = rect1.Height();
75 
76  _variant_t flags( 0L, VT_I4 );
77  _variant_t target_frame_name( "" );
78  _variant_t post_data( "" );
79  _variant_t headers( "" );
80  mBrowser.Navigate( _T( "about:blank" ), &flags, &target_frame_name, &post_data, &headers );
81  //navigating to chat-starter.html will not work because later using browser.WriteContent will
82  //overwrite the chat-starter.html content and therefore lose all styling
83  CFile starterFile;
84  if ( starterFile.Open( _T( "cdt\\chat-starter.html" ), CFile::modeRead ) )
85  {
86  char buf[1024 + 1];
87  UINT readLen;
88  while( 0 < ( readLen = starterFile.Read( buf, 1024 ) ) )
89  {
90  buf[ readLen ] = 0;
91  mBrowser.WriteContent( CString( buf ) );
92  }
93  starterFile.Close();
94  }
95 
96  updateSize();
97 
98  return TRUE;
99  }
100 
101 //----------------------------------------------------------------------
103 //----------------------------------------------------------------------
104 __packed struct chat_msg_header
105  {
106  uint8 type;
107  uint8 chunkId;
108  uint8 reserved[2]; //byte alignment padding
109  uint32 id;
110  };
111 
112 //the header structure is the same size and format as the full chat message
113 //structure up until the body buffer so that the header can be read to
114 //decide if the packet is a full message or not
115 __packed struct chat_msg
116  {
117  uint8 type;
118  uint8 chunkId;
119  uint8 bodyLength;
120  uint8 reserved; //byte alignment padding
121  uint32 id;
122  //for simplicity of processing, ensure that this holds an even number
123  uint8 body[ MAX_CDT_PAYLOAD - sizeof( chat_msg_header ) ];
124  };
125 
126 static COleDateTime epoch(1970,1,1,0,0,0);
127 
128 // CCdtChatDlg message handlers
129 //----------------------------------------------------------------------
133 //----------------------------------------------------------------------
134 void CCdtChatDlg::OnOK()
135 {
136  //should get here by using Enter key in input field or by clicking Send
137  if( 0 == mInputField.GetWindowTextLengthW() )
138  {
139  return;
140  }
141 
142  TCHAR text[ MAX_INPUT_LENGTH + 1 ];
143  mInputField.GetWindowText( text, sizeof( text ) );
144  int byteLength = _tcslen( text ) * sizeof( TCHAR );
145  uint8 converted[ MAX_INPUT_LENGTH * sizeof( TCHAR ) ];
146  memset( converted, 0, sizeof( converted ) );
147  memcpy( converted, (void*)text, byteLength );
148  chat_msg payload;
149  payload.type = 0;
150  COleDateTime currentTime = COleDateTime::GetCurrentTime();
151  COleDateTimeSpan diff = currentTime - epoch;
152  payload.id = diff.GetTotalSeconds();
153  payload.chunkId = 0;
154  payload.reserved = 0;
155 
156  CString formatted;
157  formatted.Format(
158  _T( "<div class='sent' id='%u'><span class='ts'>%s</span>" ),
159  payload.id,
160  currentTime.Format( _T( "%Y-%m-%d %H.%M.%S" ) )
161  );
162  TRACE1( "sent chat message %u\n", payload.id );
163 
164  TCHAR chunk[ MAX_CDT_PAYLOAD ];
165 
166  for( int i=0; i<byteLength; i += sizeof( payload.body ) )
167  {
168  memset( &payload.body, 0, sizeof( payload.body ) );
169  payload.bodyLength = min( byteLength - i, sizeof( payload.body ) );
170  memcpy( &payload.body, &converted[i], payload.bodyLength );
171  mCom.txCdt( CDT_DATA_TRANSFER, (uint8*)&payload, sizeof( chat_msg_header ) + payload.bodyLength );
172 
173  memset( chunk, 0, sizeof( chunk ) );
174  memcpy( chunk, &converted[i], payload.bodyLength );
175  formatted.AppendFormat(
176  _T( "<span class='chunk' chunk-id='%d'>%s</span>" ),
177  payload.chunkId,
178  chunk
179  );
180 
181  payload.chunkId++;
182  }
183  mBrowser.WriteContent( formatted );
184  mBrowser.WriteContent( _T( "</div><div class='clear'></div>\n" ) );
185 
186  mInputField.SetWindowTextW( _T( "" ) );
187  mInputField.SetFocus();
188 }
189 
190 //----------------------------------------------------------------------
192 //----------------------------------------------------------------------
193 LRESULT CCdtChatDlg::OnCDTPacketReceived( WPARAM wParam, LPARAM lParam)
194  {
195  //TODO if it was a chat packet, then display
196  sint16 cdtPayloadSize = (sint16) wParam;
197  uint8 const * cdtPayload = (uint8 const *) lParam;
198 
199  //must have at least the size of a chat message header to be handled here
200  if( cdtPayloadSize < sizeof( chat_msg_header ) )
201  {
202  return 0;
203  }
204 
205  chat_msg packet;
206  memset( &packet, 0, sizeof( chat_msg ) );
207  memcpy( &packet, cdtPayload, cdtPayloadSize );
208 
209  switch( packet.type )
210  {
211  case 0:
212  {
213  //ACK the message
214  chat_msg_header ack;
215  memset( &ack, 0, sizeof( chat_msg_header ) );
216  ack.type = 1;
217  ack.id = packet.id;
218  ack.chunkId = packet.chunkId;
219  mCom.txCdt( CDT_DATA_TRANSFER, (uint8*)&ack, sizeof( chat_msg_header ) );
220 
221  //display in chat log
222  TCHAR text[ MAX_CDT_PAYLOAD + 1 ];
223  memset( text, 0, sizeof( text ) );
224  memcpy( (void*)text, (void*)&packet.body, cdtPayloadSize - sizeof( chat_msg_header ) );
225  CString formatted;
226  formatted.Format(
227  _T( "<div class='received' received-msg-id='%u'><span class='ts'>%s</span><span class='body'>%s</span></div><div class='clear'></div>\n" ),
228  packet.id,
229  COleDateTime::GetCurrentTime().Format( _T( "%Y-%m-%d %H.%M.%S" ) ),
230  text
231  );
232  mBrowser.WriteContent( formatted );
233  break;
234  }
235  case 1:
236  {
237  TRACE1( "received ACK for sent chat message %u\n", packet.id );
238  CStringArray args;
239  CString sentMessageId;
240  sentMessageId.Format( _T( "%u" ), packet.id );
241  args.Add( sentMessageId );
242  CString chunkId;
243  chunkId.Format( _T( "%d" ), packet.chunkId );
244  args.Add( chunkId );
245  mBrowser.InvokeScript( _T( "setDelivered" ), &args );
246  break;
247  }
248  }
249 
250  return 0;
251  }
252 
253 //----------------------------------------------------------------------
267 //----------------------------------------------------------------------
268 void CCdtChatDlg::OnSize
269  (
270  UINT aType,
271  int aClientWidth,
272  int aClientHeight
273  )
274 {
275  CDialog::OnSize( aType, aClientWidth, aClientHeight );
276 
277  if ( NULL == mBrowser.GetSafeHwnd() )
278  {
279  return;
280  }
281 
282  updateSize();
283  }
284 
285 //----------------------------------------------------------------------
287 //----------------------------------------------------------------------
288 void CCdtChatDlg::updateSize()
289  {
290  CRect rect;
291  GetClientRect( &rect );
292 
293  mBrowser.MoveWindow(
294  rect.left + mPadding,
295  rect.top + mPadding,
296  rect.Width() - ( 2 * mPadding ),
297  rect.Height() - ( ( 3 * mPadding ) + mInputHeight )
298  );
299  mInputField.MoveWindow(
300  rect.left + mPadding,
301  rect.Height() - ( mPadding + mInputHeight ),
302  rect.Width() - ( ( 3 * mPadding ) + mInputHeight),
303  mInputHeight
304  );
305  GetDlgItem( IDOK )->MoveWindow(
306  rect.right - ( mPadding + mInputHeight ),
307  rect.Height() - ( mPadding + mInputHeight ),
308  mInputHeight,
309  mInputHeight
310  );
311 }
312 
313 #endif
#define IDC_CDT_CHAT_LOG
Definition: resource.h:500
#define IDC_CDT_CHAT_INPUT
Definition: resource.h:499
#define TRUE
Definition: garmin_types.h:45
signed short int sint16
16-bit signed integer
Definition: garmin_types.h:57
Serial communication controller for Garmin and FMI packets.
unsigned char uint8
8-bit unsigned integer
Definition: garmin_types.h:62
#define WM_EVENT(_event)
Translation from an application event to the corresponding Windows message.
unsigned long int uint32
32-bit unsigned integer
Definition: garmin_types.h:66