SECI  1
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Properties Events
LabViewMessageQueue.cs
Go to the documentation of this file.
1 using System;
2 using System.Collections;
3 using System.Collections.Generic;
4 using System.Text;
5 using System.IO;
6 using Seci.Definitions;
7 
8 namespace Seci.Standard
9 {
16  public static class MessageQueue
17  {
18  private static String _filePath; // The location of the Message Panel VI
19 
21  private static SerialisableList<MessageInfo> _messages = new SerialisableList<MessageInfo>();
22 
23  //Timeouts
24  private static int _timeoutTime = 1; // If message is set to time out then use this value (in minutes).
25  private static int _defaultPeriod = 60; // If message is not set to time out then delete after this many minutes.
26 
27  //Properties
28  public static SerialisableList<MessageInfo> Messages { get { return _messages; } }
29 
33  public static void InitialiseMessQVI()
34  {
35  _filePath = Status.MessagePanelVI;
36 
37  //Load VI
38  LabView.LabViewApp.LoadVI(_filePath, true);
39 
40  //Start it running
41  LabView.LabViewApp.StartVI(_filePath);
42  }
43 
47  public static void ShowVI()
48  {
49  LabView.LabViewApp.ShowVI(_filePath);
50  }
51 
55  public static void HideVI()
56  {
57  LabView.LabViewApp.HideVI(_filePath);
58  }
59 
66  public static Boolean UpdateMessages()
67  {
68  Boolean updates = removeMessages();
69  Boolean newmessages = getMessageQ();
70 
71  return (newmessages || updates);
72  }
73 
82  private static Boolean getMessageQ()
83  {
84  //Take the message panel off hold and then wait for the done flag.
85  //Basically when the panel is taken off hold it reads the queue and
86  //then the done light comes on.
87  Boolean MessagesChanged = false;
88 
89  try
90  {
91  LabView.LabViewApp.SetValue(_filePath, "Hold", false);
92 
93  int counter = 0;
94 
95  while (LabView.LabViewApp.GetValue(_filePath, "Done")[0].ToLower() != "true")
96  {
97  System.Threading.Thread.Sleep(50);
98  counter++;
99 
100  //Safety valve - if this takes too long assume the VI has a problem
101  if (counter > 500)
102  {
103  //Problem, so throw exception
104  throw new LabView.LabViewException("getErrorQ - Could not get information from message panel VI.");
105  }
106  }
107 
108  //Reset the duplicate counts
109  for (int i = 0; i < _messages.Count; ++i)
110  {
111  _messages[i].Count = 1;
112  }
113 
114  //brief pause to allow LabVIEW to catch up
115  System.Threading.Thread.Sleep(250);
116 
117  //Process the queue
118  Object[] temp = LabView.LabViewApp.GetCluster(_filePath, "Queue");
119 
120  for (int i = 0; i < temp.GetLength(0); ++i)
121  {
122  Object[] Qmember = (Object[])temp[i];
123 
124  MessageInfo newMess = new MessageInfo();
125 
126  newMess.Message = Qmember[0].ToString();
127  newMess.OriginalMess = Qmember[0].ToString();
128  newMess.YesText = Qmember[1].ToString();
129  newMess.NoText = Qmember[2].ToString();
130  newMess.Timeout = (Boolean)Qmember[3];
131  newMess.WaitForResponse = (Boolean)Qmember[4];
132  newMess.VIName = Qmember[5].ToString();
133  newMess.UserReplied = (Boolean)Qmember[6];
134  newMess.Timestamp = Qmember[8].ToString();
135 
136  if (newMess.UserReplied)
137  {
138  //Just in case an answered question slips through
139  continue;
140  }
141 
142  //Replace \n \r chars in Message with spaces
143  newMess.Message = newMess.Message.Replace('\n', ' ');
144  newMess.Message = newMess.Message.Replace('\r', ' ');
145 
146  //See if error already exists by comparing VIname and Message
147  Boolean duplicate = false;
148 
149  for (int j = 0; j < _messages.Count; ++j)
150  {
151  if ((_messages[j].Message == newMess.Message) && (_messages[j].VIName == newMess.VIName))
152  {
153  //it is a duplicate, so increase count
154  if (_messages[j].Timestamp != newMess.Timestamp)
155  {
156  _messages[j].Count += 1;
157  if (_messages[j].Count > 1000)
158  {
159  //Just in case
160  _messages[j].Count = 1000;
161  }
162  }
163  duplicate = true;
164  break;
165  }
166  }
167 
168  if (duplicate)
169  {
170  MessagesChanged = true;
171  }
172  else
173  {
174  //Set time added
175  newMess.TimeAdded = DateTime.Now;
176  _messages.Add(newMess);
177 
178  //Log the message
179  Seci.Helpers.ErrorLogger.LabViewError(newMess.VIName, newMess.Message);
180 
181  //Flag that the messages have changed
182  MessagesChanged = true;
183  }
184  }
185  }
186  catch (Exception err)
187  {
188  Seci.Helpers.ErrorLogger.SeciError("getMessageQ", err);
189  }
190 
191  return MessagesChanged;
192  }
193 
199  private static Boolean removeMessages()
200  {
201  //Send the data back to the message panel VI
202  Boolean anyReplies = false;
203 
204  try
205  {
206  //First create a cluster from the message array list
207  Object[] qVals = LabView.LabViewApp.GetCluster(_filePath, "Queue");
208 
209  List<int> repliedTo = new List<int>();
210 
211  for (int i = 0; i < _messages.Count; ++i)
212  {
213  for (int j = 0; j < qVals.GetLength(0); ++j)
214  {
215  Object[] Qmember = (Object[])qVals[j];
216 
217  //Message = Qmember[0]
218  //VI = Qmember[5]
219  //Replied = Qmember[6]
220  //Response = Qmember[7]
221 
222  if (_messages[i].UserReplied && _messages[i].Message == Qmember[0].ToString() && _messages[i].VIName == Qmember[5].ToString())
223  {
224  //Then we have a reply
225  anyReplies = true;
226  Qmember[6] = true;
227  Qmember[7] = _messages[i].Response;
228  repliedTo.Add(i);
229  }
230  else if (_messages[i].Timeout == true && _messages[i].Message == Qmember[0].ToString() && _messages[i].VIName == Qmember[5].ToString())
231  {
232  //Set to timeout
233  if (_messages[i].TimeAdded <= DateTime.Now.Subtract(new TimeSpan(0, 0, _timeoutTime, 0, 0)))
234  {
235  if (!_messages[i].UserReplied)
236  {
237  //Mark for removal, by replying false
238  Qmember[6] = true;
239  Qmember[7] = false;
240  anyReplies = true;
241  repliedTo.Add(i);
242  }
243  }
244  }
245  else if (_messages[i].TimeAdded <= DateTime.Now.Subtract(new TimeSpan(0, 0, _defaultPeriod, 0, 0)))
246  {
247  //Not set to timeout
248  if (!_messages[i].UserReplied)
249  {
250  //Mark for removal, by replying false
251  Qmember[6] = true;
252  Qmember[7] = false;
253  anyReplies = true;
254  repliedTo.Add(i);
255  }
256  }
257 
258  qVals[j] = Qmember;
259  }
260  }
261 
262  LabView.LabViewApp.SetCluster(_filePath, "Queue", qVals);
263 
264  //remove any messages where the user responded and the response has been sent to the VI
265  for (int i = repliedTo.Count - 1; i >= 0; i--)
266  {
267  if (_messages.Count > repliedTo[i])
268  {
269  _messages.RemoveAt(repliedTo[i]);
270  }
271  }
272  }
273  catch (Exception err)
274  {
275  Seci.Helpers.ErrorLogger.SeciError("removeMessages", err);
276  }
277 
278  return anyReplies;
279  }
280 
287  public static void SendReply(String questionMessage, String source, Boolean reply)
288  {
289  //Find the message number
290  int messNumb = -1;
291 
292  for (int i = 0; i < _messages.Count; ++i)
293  {
294  if ((questionMessage == _messages[i].Message) && (source == _messages[i].VIName))
295  {
296  //Found the right message
297  messNumb = i;
298  break;
299  }
300  }
301 
302  if (messNumb != -1)
303  {
304  //Change message to show that the user has replied
305  _messages[messNumb].Response = reply;
306  _messages[messNumb].UserReplied = true;
307 
308  //Log reply
309  Seci.Helpers.ErrorLogger.LabViewError(_messages[messNumb].VIName, _messages[messNumb].Message + " - User replied " + _messages[messNumb].Response);
310  }
311  }
312  }
313 
317  public class MessageInfo
318  {
319  //Members
320  private String _message;
321  private String _originalMess;
322  private Boolean _timeout;
323  private DateTime _timeAdded;
324  private Boolean _waitForResponse;
325  private String _viName;
326  private String _yesText;
327  private String _noText;
328  private int _priority;
329  private int _count = 1;
330  private String _timestamp;
331  private Boolean _response;
332  private Boolean _userReplied;
333 
334  public String Message { get { return _message; } set { _message = value; } }
335  public String OriginalMess { get { return _originalMess; } set { _originalMess = value; } }
336  public Boolean Timeout { get { return _timeout; } set { _timeout = value; } }
337  public Boolean WaitForResponse { get { return _waitForResponse; } set { _waitForResponse = value; } }
338  public String VIName { get { return _viName; } set { _viName = value; } }
339  public DateTime TimeAdded { get { return _timeAdded; } set { _timeAdded = value; } }
340  public String YesText { get { return _yesText; } set { _yesText = value; } }
341  public String NoText { get { return _noText; } set { _noText = value; } }
342  public int Priority { get { return _priority; } set { _priority = value; } }
343  public int Count { get { return _count; } set { _count = value; } }
344  public String Timestamp { get { return _timestamp; } set { _timestamp = value; } }
345  public Boolean Response { get { return _response; } set { _response = value; } }
346  public Boolean UserReplied { get { return _userReplied; } set { _userReplied = value; } }
347 
351  public MessageInfo()
352  {
353  }
354 
355  }
356 }
Boolean _waitForResponse
Set if VI requires a response.
static void InitialiseMessQVI()
This method load the message panel VI and starts it running.
static Boolean getMessageQ()
This method get the latest message information from the messgae panel VI. The method checks for any n...
A simple custom exception used for LabVIEW exceptions
static void SendReply(String questionMessage, String source, Boolean reply)
This method handles any user replies to messages, just updates the SECI copy.
String _timestamp
Timestamp from LV.
String _message
Text to display.
This class is a wrapper for the Message Panel VI. This VI is where sample environment VIs should send...
Boolean _response
Result of the error form.
String _noText
Button 2 text (no)
static void ShowVI()
This method makes the message panel VI visible (only recommended when debugging). ...
Boolean _timeout
Set if error message should timeout.
static void HideVI()
This method hides the message panel VI.
static Boolean UpdateMessages()
This method is called when it is time to check for changes to the message panel VI. It checks to see if any new messages have arrived, if any old messages have timed out, and if the user has dismissed any messages.
This class is used to store the message data that is retrieved from the message panel vi...
static Boolean removeMessages()
This method checks to see if any messages have been responded to by the user or timed out...
DateTime _timeAdded
Time when added to the list.
String _originalMess
Originally received from message panel.
String _yesText
Button 1 text (yes)
String _viName
Name of VI that generated the error.
Boolean _userReplied
Set when result waiting to be sent out.