source: trunk/ETSI-Testsuites/ETSI_auto_IOT/adapter/src/UEUserGuide/UEUserGuideFrm.cs

Last change on this file was 22, checked in by rings, 14 years ago
  • Property svn:executable set to *
File size: 18.7 KB
Line 
1using System;
2using System.Collections.Generic;
3using System.ComponentModel;
4using System.Data;
5using System.Drawing;
6using System.Linq;
7using System.Text;
8using System.Windows.Forms;
9using System.Configuration;
10using System.Xml;
11
12namespace UEUserGuide
13{
14    public partial class UEUserGuideFrm : Form
15    {
16        ///////////////////////////////////////////////////////////////////////
17        #region Delegates
18
19        public delegate void UpdateUICallBack(string trigger, IList<string> paramsList);
20
21        #endregion Delegates
22
23        ///////////////////////////////////////////////////////////////////////
24        #region Internal fields
25
26        ///////////////////////////////////////////////////////////////////////
27        #region Application settings
28
29        /// <summary>
30        /// IP address.
31        /// </summary>
32        private string _address;
33
34        /// <summary>
35        /// IP port.
36        /// </summary>
37        private int _port = -1;
38
39        /// <summary>
40        /// IP address.
41        /// </summary>
42        private Uri _messagesFilePath;
43
44        #endregion Application settings
45
46        ///////////////////////////////////////////////////////////////////////
47        #region Network part
48
49        /// <summary>
50        /// Server instance.
51        /// </summary>
52        private NetworkHelper _server = null;
53
54        /// <summary>
55        /// Event set to terminate the background thread.
56        /// </summary>
57        System.Threading.ManualResetEvent _terminated;
58
59        #endregion Network part
60
61        /// User guides messages values list.
62        /// </summary>
63        private IDictionary<string, MessageParms> _parms;
64
65        /// <summary>
66        /// Event set when user action is achieved.
67        /// </summary>
68        private System.Threading.ManualResetEvent _userActionCompleted;
69
70        private DialogResult _userResponse;
71
72        #endregion Internal fields
73
74        ///////////////////////////////////////////////////////////////////////
75        #region ctors
76
77        /// <summary>
78        /// Default ctor.
79        /// </summary>
80        public UEUserGuideFrm()
81        {
82            // Initialize logger.
83            Logger.Instance.Initialize("UEUserGuide");
84
85            _userActionCompleted = new System.Threading.ManualResetEvent(false);
86
87            InitializeComponent();
88        }
89
90        #endregion ctors
91
92        private void UEUserGuideFrm_Load(object sender, EventArgs e)
93        {
94            // Set UI state.
95            ResetUI();
96
97            // Load application settings.
98            try
99            {
100                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
101                AppSettingsSection appSettings = (AppSettingsSection)config.GetSection("appSettings");
102                _address = appSettings.Settings["IpAddress"].Value;
103                _port = int.Parse(appSettings.Settings["IpPort"].Value);
104                _messagesFilePath = new Uri(appSettings.Settings["MessagesFile"].Value);
105                Text = appSettings.Settings["Title"].Value;
106                // Sanity check.
107                if (!System.IO.File.Exists(_messagesFilePath.LocalPath))
108                {
109                    throw new System.IO.FileNotFoundException(_messagesFilePath.LocalPath);
110                }
111            }
112            catch (Exception x)
113            {
114                MessageBox.Show(
115                    string.Format("Failed to load application settings.\r\n{0}", x),
116                    this.Text,
117                    MessageBoxButtons.OK,
118                    MessageBoxIcon.Error);
119                Close();
120                return;
121            }
122
123            // Load message database.
124            ReloadParameters();
125            if ((_parms == null) || (_parms.Count == 0))
126            {
127                MessageBox.Show("Invalid content of 'UserGuidesMessages.xml' file", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
128                Close();
129                return;
130            }
131
132            // Start TCP/IP listener.
133            try
134            {
135                _server = new NetworkHelper();
136                if (!_server.Initialize(_address, _port))
137                {
138                    MessageBox.Show("Failed to initialize networl communications", this.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
139                    Close();
140                    return;
141                }
142                _serverParms.Text = string.Format("Listen on {0}:{1}", _address, _port);
143                _server.Start();
144            }
145            catch (Exception x)
146            {
147                MessageBox.Show(
148                    string.Format("Failed to start listener, please check IP address/port number information in application cconfiguration file.\r\n{0}", x),
149                    this.Text,
150                    MessageBoxButtons.OK,
151                    MessageBoxIcon.Error);
152                Close();
153                return;
154            }
155
156            _terminated = new System.Threading.ManualResetEvent(false);
157            _processNetworkClient.RunWorkerAsync();
158
159            _btReload.Visible = true;
160
161            _messagesFile.Text = _messagesFilePath.LocalPath;
162        }
163
164        private void _btReload_Click(object sender, EventArgs e)
165        {
166            ReloadParameters();
167            ResetUI();
168        }
169
170        private void _btOK_Click(object sender, EventArgs e)
171        {
172            _btOK.Enabled = false;
173            _btFailed.Enabled = false;
174            _userResponse = DialogResult.OK;
175            _userActionCompleted.Set();
176        }
177
178        private void _btYes_Click(object sender, EventArgs e)
179        {
180            _btYes.Enabled = false;
181            _btNo.Enabled = false;
182            _userResponse = DialogResult.Yes;
183            _userActionCompleted.Set();
184        }
185
186        private void _btNo_Click(object sender, EventArgs e)
187        {
188            _btYes.Enabled = false;
189            _btNo.Enabled = false;
190            _userResponse = DialogResult.No;
191            _userActionCompleted.Set();
192        }
193
194        private void _btFailed_Click(object sender, EventArgs e)
195        {
196            _btOK.Enabled = false;
197            _btFailed.Enabled = false;
198            _userResponse = DialogResult.Cancel;
199            _userActionCompleted.Set();
200        }
201
202        private void _btResetUI_Click(object sender, EventArgs e)
203        {
204            ResetUI();
205        }
206
207        private void _btQuit_Click(object sender, EventArgs e)
208        {
209            _userActionCompleted.Set();
210
211            // Stop TCP/IP listener.
212            if (_server != null)
213            {
214                _server.Stop();
215                _server = null;
216            }
217
218            // Terminate application.
219            Close();
220        }
221
222
223        /// <summary>
224        /// Method called to relaod User guides messages.
225        /// </summary>
226        public void ReloadParameters()
227        {
228            XmlDocument parmsDoc = new XmlDocument();
229            parmsDoc.Load(_messagesFilePath.LocalPath);
230            // Get the strategy to use.
231            XmlNodeList nodes = parmsDoc.SelectNodes("descendant::UserGuideMessages/Strategies").Item(0).ChildNodes;
232            string strategy = null;
233            foreach (XmlNode node in nodes)
234            {
235                if ((node.Attributes != null) && (node.Attributes.Count != 0) && !string.IsNullOrEmpty(node.Attributes[0].Value))
236                {
237                    strategy = node.Attributes[0].Value;
238                    break;
239                }
240            }
241            if (!string.IsNullOrEmpty(strategy))
242            {
243                // Apply the strategy.
244                nodes = parmsDoc.SelectNodes(string.Format("descendant::UserGuideMessages/{0}", strategy)).Item(0).ChildNodes;
245                if ((nodes == null) || (nodes.Count == 0))
246                {
247                    // The response is empty.
248                    _parms = null;
249                }
250                else
251                {
252                    _parms = new Dictionary<string, MessageParms>();
253                    foreach (XmlNode item in nodes)
254                    {
255                        if ((item.NodeType == XmlNodeType.Comment) || (item.Attributes == null) || (item.Attributes.Count != 2))
256                        {
257                            // TODO: Add logs.
258                            continue;
259                        }
260                        _parms.Add(item.Name, new MessageParms(item.Attributes.GetNamedItem("Text").Value.Replace("\\n", System.Environment.NewLine).Replace("\\t", "    "), item.Attributes.GetNamedItem("Actions").Value));
261                    }
262                    if (_parms.Count == 0)
263                    {
264                        _parms = null;
265                    }
266                }
267            }
268            else
269            {
270                _parms = null;
271            }
272        }
273
274        /// <summary>
275        ///
276        /// </summary>
277        /// <param name="sender"></param>
278        /// <param name="e"></param>
279        private void _processNetworkClient_DoWork(object sender, DoWorkEventArgs e)
280        {
281            try
282            {
283                // Enter the listening loop.
284                while (!_terminated.WaitOne(5, false))
285                {
286                    if (Logger.Instance.IsDebugLevelSet) Logger.Instance.DebugLogger("_processNetworkClient_DoWork: Waiting for a connection...");
287                    // Perform a blocking call to accept requests.
288                    NetworkHelper client = _server.AcceptClient();
289                    System.Threading.ThreadPool.QueueUserWorkItem(ProcessNewConnection, new ProcessNewConnectionArgs(client));
290                }
291            }
292            catch (System.Net.Sockets.SocketException s)
293            {
294                Logger.Instance.ErrorLogger("_processNetworkClient_DoWork: {0}", s);
295            }
296
297            e.Result = (object)true;
298            if (Logger.Instance.IsInfoLevelSet) Logger.Instance.InfoLogger("_processNetworkClient_DoWork: Terminated.");
299        }
300
301        /// <summary>
302        /// Process the new accepted connection.
303        /// </summary>
304        /// <param name="parms">Connection instance.</param>
305        private void ProcessNewConnection(object parms)
306        {
307            // Sanity check.
308            if (!(parms is ProcessNewConnectionArgs))
309            {
310                Logger.Instance.ErrorLogger("ProcessNewConnection: Wrong parameters.");
311                return;
312            }
313            ProcessNewConnectionArgs args = parms as ProcessNewConnectionArgs;
314
315            if (Logger.Instance.IsDebugLevelSet) Logger.Instance.DebugLogger("ProcessNewConnection: Connected.");
316
317            try
318            {
319                // Buffer for reading data.
320                string readBytes;
321                // Read data.
322                int length = args.Client.Receive(out readBytes);
323                byte[] buffer = System.Text.Encoding.ASCII.GetBytes(readBytes.ToCharArray(), 0, length);
324                if (length == -1)
325                {
326                    // Exit loop.
327                    Logger.Instance.ErrorLogger("ProcessNewConnection: Receive datas failed.");
328                }
329                else if (length != 0)
330                {
331                    if (Logger.Instance.IsDebugLevelSet) Logger.Instance.DebugLogger("ProcessNewConnection: Receive datas ({0}).", length);
332                    // Convert byte into string.
333                    int index = 0;
334                    // Get ID
335                    int id = BitConverter.ToInt16(buffer, index);
336                    index += sizeof(short);
337                    // Decode full length.
338                    int totalLength = BitConverter.ToInt16(buffer, index);
339                    index += sizeof(int);
340                    // Decode the trigger command.
341                    length = BitConverter.ToInt32(buffer, index); // Decode length;
342                    index += sizeof(int);
343                    string trigger = Encoding.ASCII.GetString(buffer, index, length); // Decode datas.
344                    index += trigger.Length;
345                    // Decode the parameters.
346                    int paramsNum = BitConverter.ToInt32(buffer, index); // Decode length;
347                    index += sizeof(int);
348                    // Read the parameters.
349                    IList<string> parmsList = new List<string>();
350                    for (int i = 0; i < paramsNum; i++)
351                    {
352                        length = BitConverter.ToInt32(buffer, index); // Decode length;
353                        index += sizeof(int);
354                        string str = Encoding.ASCII.GetString(buffer, index, length); // Decode datas.
355                        index += str.Length;
356                        parmsList.Add(str);
357                    }
358                    if (!string.IsNullOrEmpty(trigger))
359                    {
360                        // Update UI in multi-threaded mode.
361                        IAsyncResult result = this.BeginInvoke(new UpdateUICallBack(UpdateUI), trigger, parmsList);
362                        // Wait for the WaitHandle to become signaled.
363                        result.AsyncWaitHandle.WaitOne();
364                        // Wait for user action done.
365                        _userActionCompleted.WaitOne(30000);
366                    }
367                    else
368                    {
369                        _userResponse = DialogResult.Cancel;
370                    }
371                    // Send response message
372                    byte[] response = new byte[1] { (byte)_userResponse };
373                    args.Client.Send(BitConverter.ToString(response));
374                    // Wait for disconnection
375                    args.Client.Receive(out buffer);
376                }
377            }
378            catch (Exception x)
379            {
380                Logger.Instance.ErrorLogger("ProcessNewConnection: {0}", x);
381            }
382            finally
383            {
384                // Shutdown and end connection.
385                if (Logger.Instance.IsDebugLevelSet) Logger.Instance.DebugLogger("ProcessNewConnection: Close connection.");
386                args.Client.Close();
387            }
388        }
389
390        private void UpdateUI(string trigger, IList<string> paramsList)
391        {
392            _message.Focus();
393            _userActionCompleted.Reset();
394            string action = "OkCancel";
395            if (_parms.ContainsKey(trigger))
396            {
397                string message = _parms[trigger].Text;
398                if (!((paramsList.Count == 0) || ((paramsList.Count == 1) && (paramsList[0] == "*"))))
399                {
400                    message += "\n\tParameters:\n";
401                    foreach (string item in paramsList)
402                    {
403                        message += string.Format("\t\t{0}\n", item);
404                    }
405                }
406                _message.Text = message;
407                action = _parms[trigger].Action;
408            }
409            else
410            {
411                _message.Text = trigger;
412            }
413            switch (action)
414            {
415                case "OkCancel":
416                    _btOK.Enabled = true;
417                    _btOK.Visible = true;
418                    _btFailed.Visible = true;
419                    _btFailed.Enabled = true;
420                    _btYes.Visible = false;
421                    _btNo.Visible = false;
422                    break;
423                case "YesNo":
424                    _btOK.Visible = false;
425                    _btFailed.Visible = false;
426                    _btYes.Visible = true;
427                    _btYes.Enabled = true;
428                    _btNo.Visible = true;
429                    _btNo.Enabled = true;
430                    break;
431                default:
432                    ResetUI();
433                    break;
434            }
435        }
436
437        private void ResetUI()
438        {
439            _message.Text = "";
440            _message.Lines = null;
441            _btOK.Visible = false;
442            _btFailed.Visible = false;
443            _btYes.Visible = false;
444            _btNo.Visible = false;
445            _btOK.Enabled = true;
446            _btFailed.Enabled = true;
447            _btYes.Enabled = true;
448            _btNo.Enabled = true;
449        }
450    }
451
452    ///////////////////////////////////////////////////////////////////////
453    #region Class helpers part
454
455    /// <summary>
456    /// This class describes the user guides messages associated to each trigger.
457    /// </summary>
458    class MessageParms
459    {
460        ///////////////////////////////////////////////////////////////////////
461        #region Internal part
462
463        /// <summary>
464        /// Parameter type.
465        /// </summary>
466        private string _text;
467
468        /// <summary>
469        /// Parameter value.
470        /// </summary>
471        private string _action;
472
473        #endregion Internal part
474
475        ///////////////////////////////////////////////////////////////////////
476        #region Accessors part
477
478        /// <summary>
479        /// Gets the parameter type.
480        /// </summary>
481        public string Text { get { return _text; } }
482
483        /// <summary>
484        /// Gets the parameter value.
485        /// </summary>
486        public string Action { get { return _action; } }
487
488        #endregion Accessors part
489
490        ///////////////////////////////////////////////////////////////////////
491        #region Ctors part
492
493        /// <summary>
494        /// Default ctor.
495        /// </summary>
496        public MessageParms()
497        {
498            _text = null;
499            _action = null;
500        }
501
502        /// <summary>
503        /// Builder ctor.
504        /// </summary>
505        /// <param name="text"></param>
506        /// <param name="action"></param>
507        public MessageParms(string text, string action)
508        {
509            _text = text;
510            _action = action;
511        }
512
513        #endregion Ctors part
514    }
515
516    /// <summary>
517    /// Internal class helper.
518    /// </summary>
519    class ProcessNewConnectionArgs
520    {
521        /// <summary>
522        /// New accepted connection reference.
523        /// </summary>
524        private NetworkHelper _client;
525        /// <summary>
526        /// Gets the new accepted connection reference.
527        /// </summary>
528        public NetworkHelper Client { get { return _client; } }
529
530        /// <summary>
531        /// Builder ctor.
532        /// </summary>
533        /// <param name="client">New accepted connection reference.</param>
534        public ProcessNewConnectionArgs(NetworkHelper client)
535        {
536            _client = client;
537        }
538    }
539
540    #endregion Class helpers part
541
542}
Note: See TracBrowser for help on using the repository browser.