Exceptions Monitor |
At the end of this tutorial you will have a simple Windows forms application that shows all the exceptions generated in the specified time window. The application refreshes the list of exceptions every five minutes, and it beeps when a new exception occurs.
This topic contains the following sections:
Open Visual Studio and create a new C# or VB.NET Windows Forms application. Name the project 'ExceptionsMonitor'.
Open Designer View and modify the form to match the screenshot below. The dateTimePickers are named dateTimePickerStart and dateTimePickerEnd. The button is named buttonRefresh. The listboxes are named as shown in the screenshot.
Also, add a timer named timerReload to your form. This will be used to automatically update the list of exceptions.
In Visual Studio, ensure that your project has a reference to the Fleet Web Service API:
Begin by adding the following members to the Form1 class. These will be used to hold a local copy of your Fleet drivers, conditions, and currently loaded exceptions. To access the Fleet Web Service, use the LegacyTelogisServiceClient (.NET 4) or the LegacyTelogisService (.NET 2) object.
Fleet.LegacyTelogisServiceClient service; Fleet.AuthenticationHeader header; // allows us to easily map condition IDs to Conditions Dictionary<long, Fleet.Condition> conditionsDict = new Dictionary<long, Fleet.Condition>(); // allows us to easily map driver IDs to Drivers Dictionary<long, Fleet.Driver> driversDict = new Dictionary<long, Fleet.Driver>(); // all the exceptions currently loaded from OnTrack List<Fleet.Exception> allExceptions = new List<Fleet.Exception>();
Tip |
---|
Alternatively, we could have used the GetDriver and GetCondition methods of LegacyTelogisServiceClient or LegacyTelogisService to obtain Driver and Condition objects on-the-fly, but by caching all the drivers and conditions locally we can make a significant time saving. |
Add a load event to your form. Modify the load event to match the code snippet below. Important points to note are:
// When the form loads we configure the Fleet Web Service and login // to the web service private void Form1_Load(object sender, EventArgs e) { // avoid HTTP417 errors caused by some proxies System.Net.ServicePointManager.Expect100Continue = false; // Create a TelogisServiceClient for logging in Fleet.TelogisServiceClient tsclient = new Fleet.TelogisServiceClient(); // Log in and obtain an authentication token string authToken=tsclient.Login(String.Format("{0}:{1}", customer, user), pword); // Now create the LegacyTelogisServiceClient for accessing the API service = new Fleet.LegacyTelogisServiceClient(); header = new Fleet.AuthenticationHeader(); header.SessionID = authToken; // Create a key-value (ID-Condition) mapping for each Condition // in your Fleet account Fleet.Condition[] conditions = service.ListConditions(header, 0, 100); foreach (Fleet.Condition c in conditions) { conditionsDict.Add(c.ID, c); } // Create a key-value (ID-Driver) mapping for each Driver Fleet.Driver[] drivers = service.ListDrivers(header, 0, 100); foreach (Fleet.Driver d in drivers) { driversDict.Add(d.ID, d); } // By default, show only the previous 1 day of exception events dateTimePickerStart.Value = dateTimePickerEnd.Value.AddDays(-1); // Configure the timer to reload the Exceptions every 5 minutes timerReload.Interval = 5 * 60 * 1000; timerReload.Start(); Reload(); }
The following method uses the Web Service to retrieve and store exceptions.
Each exception contains three ID values: the ID of the condition (that the exception triggered), the ID of the driver responsible for the exception and the ID of the vehicle that caused the exception. Each exception also contains a Point object, which represents the instant in time that the exception was triggered. This Point object encapsulates positional and travel information - such as the street address, direction of travel, time of day and vehicle status.
private void Reload() { listBoxDetails.Items.Clear(); listBoxExceptions.Items.Clear(); int oldCount = allExceptions.Count; allExceptions.Clear(); DateTime start = dateTimePickerStart.Value; DateTime end = dateTimePickerEnd.Value; // The ListExceptions method returns the most recent Exception // last, so we reverse our array. This places the most recent // exception at the top of the list. Fleet.Exception[] exceptions = service.ListExceptions(header, start, end); Array.Reverse(exceptions); foreach (Fleet.Exception e in exceptions) { allExceptions.Add(e); String driverDescription = "(Unknown Driver)"; if (driversDict.ContainsKey(e.DriverID)) { driverDescription = driversDict[e.DriverID].Name; } String conditionDescription = "(Unknown Condition)"; if (conditionsDict.ContainsKey(e.ConditionID)) { conditionDescription = conditionsDict[e.ConditionID].Tag; } String row = driverDescription + " was " + conditionDescription; listBoxExceptions.Items.Add(row); } // See if the number of Exceptions in our list has increased. If the // number of Exceptions has decreased we have probably just moved to // the next calendar day, which we ignore. // int delta = allExceptions.Count - oldCount; if (delta > 0) { System.Media.SystemSounds.Beep.Play(); MessageBox.Show("There are " + delta + " new exceptions!"); } }
Tip |
---|
Most Fleet objects have an array of Property objects as a member. A Property object is a key-value pair. Fleet will look for and display certain key-value pairs. When searching for objects you can typically filter the search results on these Property objects. In this tutorial we'll use the FirstName and LastName properties to identify drivers. Both of these properties are recognized by Fleet. |
Wire the method below to the large listbox's SelectedIndexChanged event. This method will load selected details describing the exception into the smaller details listbox.
Because the exceptions listbox is a straight visual representation of the allExceptions list, we can use the selected index of the exceptions listbox to map straight to the Exception object that we would like to interrogate.
Caution |
---|
Some fields and properties - such as the Point.Marker field - may be null (Nothing). Your code needs to check for, and gracefully handle, occasions where these values are not assigned. |
private void listBoxExceptions_SelectedIndexChanged(object sender, EventArgs e) { if (listBoxExceptions.SelectedIndex != -1) { listBoxDetails.Items.Clear(); Fleet.Exception exception = allExceptions[listBoxExceptions.SelectedIndex]; Point p = exception.Point; // // Get the unit ID, speed, status and time of the event. // The Exception object's Point may also have a Marker, // in which case we'll show the Marker object's tag. // listBoxDetails.Items.Add("Unit = " + exception.UnitID); listBoxDetails.Items.Add("Speed = " + p.Speed); if (p.Marker != null) { listBoxDetails.Items.Add("Marker = " + p.Marker.Tag); } listBoxDetails.Items.Add("Status = " + p.Status); listBoxDetails.Items.Add("Time = " + p.Timestamp); } }
Wire the following to the reload button's click event and the timer's tick event, as appropriate. This will cause the timer to automatically update the list of exceptions, and let the user update the list by clicking the reload button.
That completes the Exceptions Monitor sample project.