Click or drag to resize
Exceptions Monitor
Print this page

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:

Creating the project

Open Visual Studio and create a new C# or VB.NET Windows Forms application. Name the project 'ExceptionsMonitor'.

Building the form

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.

Adding the web service

In Visual Studio, ensure that your project has a reference to the Fleet Web Service API:

  1. In Solution Explorer, right-click your project and select Add Service Reference... (.NET 2: then click Advanced (at lower left), and click Add Web Reference).
  2. For the Address (.NET 2: API URL), enter https://<customer>.api.telogis.com/V2/<customer>/wsdl, where <customer> is your account name.
  3. Click Go.
  4. Change the Namespace (.NET 2: Web reference name) to Fleet, then click OK.
    tutorial-createproject-selectservice 4
Connecting to the 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.

.NET 4

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 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:

  • Some proxy servers will cause an exception to be raised. To work around this you should set System.Net.ServicePointManager.Expect100Continue to false.
  • The login method takes a customer name, a username and a password and returns an authentication token. The Authentication header, in turn, is either passed as an argument to API calls (.NET 4) or assigned to the LegacyTelogisService object.
  • We use the ListDrivers and ListConditions methods to fetch our Condition and Driver objects. A maximum of 100 drivers and conditions are returned to prevent time-consuming queries.

.NET 4

// 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();
}
Retrieving exceptions

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.

.NET 4

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!");
}
}
Showing exception information
Tip 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 note 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);
}
}
Reloading the exception list

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.

private void buttonReload_Click(object sender, EventArgs e) {
Reload();
}

private void timerReload_Tick(object sender, EventArgs e) {
Reload();
}
Conclusion

That completes the Exceptions Monitor sample project.