Logging, Exceptions, and Errors: Difference between revisions

From Phidgets Support
No edit summary
Line 1: Line 1:
[[Category:Programming]]
[[Category:Programming]]
{|
|style="vertical-align:middle; width: 60%;"|
You've written your code, fixed the compiler errors, and yet, the program still isn't behaving as intended. The tools described on this page will help you further debug your program and figure out where in the code things are going wrong.
You've written your code, fixed the compiler errors, and yet, the program still isn't behaving as intended. The tools described on this page will help you further debug your program and figure out where in the code things are going wrong.
|{{TOC limit|3}}
|}


==Errors and Error Events==


==Logging==
The Phidget library uses errors and error events to communicate information about potential problems in your program. These can happen in-line in the form of an exception or error code (which generally indicate a problem in the code), and as Error Events (which generally indicate a problem with the Phidget's environment).


The {{Phidget22API}} supports a general logging API that supports log levels, named sources of logs, and the writing of logs to a file or to a Phidget Network Server.  The Phidget software library uses this logging system internally, so in addition to being able to log within your own software, information about what the Phidget software is doing is also available.  Refer to the ''Logging API'' in the {{Phidget22API}} for language specific information.
===Errors from Function Calls===


To begin, logging must be enabled
When a call to a Phidgets function fails it will throw an exception (or return an error code, depending on the language). It is important to check each function call for errors, and to catch and handle any errors.


<syntaxhighlight lang=c>
Common causes of this type of errors are the Phidget not being attached, or one of the values provided to the function being outside the valid range.
PhidgetLog_enable(PHIDGET_LOG_INFO, NULL);
</syntaxhighlight>


Or in Java:
You can handle exceptions and return codes as follows:


<syntaxhighlight lang=java>
<tabber>
Log.enable(LogLevel.INFO, null);
Java=<syntaxhighlight lang=java>
try {
    ch.open(5000);
} catch (PhidgetException ex) {
    System.out.println("Failed to open: " + ex.getMessage());
}
</syntaxhighlight>
</syntaxhighlight>
 
|-|
When <code>NULL</code> is passed to <code>enable()</code> in the above examples, the logging system will output to <code>STDERR</code>.
Python=<syntaxhighlight lang=python>
 
try:
There are five different logging levels, ranging from "Give me Everything!" to "Tell me only about critical problems". Note that the DEBUG log level is only active for Debug builds of the library and should not be used.
    ch.openWaitForAttachment(5000);
 
except PhidgetException as e:
'''CRITICAL'''
    print("Failed to open: " + e.details)
:Critical error messages.
:Errors at this level are generally non-recoverable and indicate either hardware problems, library bugs, or other serious issues.
 
'''ERROR'''
:Non-critical error messages.
:Errors at this level are generally automatically recoverable, but may help to track down issues.
 
'''WARNING'''
:Warning messages.
:Warnings are used to log behavior that is not necessarily in error, but is nevertheless odd or unexpected.
 
'''INFO'''
:Informational messages.
:Informational messages communicate useful operations and states changes within the software
 
'''VERBOSE'''
:Verbose messages.
:Verbose messages are informational messages that are expected to happen so frequently that they tend to drown out other log messages.
 
These are available in the '''Enumerations''' section of Logging API in the {{Phidget22API}} documentation.
 
=== Logging in Your Program ===
 
Logging is performed using the <code>log()</code> method from the Logging API.
 
For example, in C:
 
<syntaxhighlight lang=c>
PhidgetLog_log(PHIDGET_LOG_INFO, "Something happened in loop iteration %d!", i);
</syntaxhighlight>
</syntaxhighlight>
 
|-|
Or in Java:
C#=<syntaxhighlight lang=cSharp>
 
try
<syntaxhighlight lang=java>
{
Log.log(LogLevel.INFO, "Something happened in loop iteration " + i + "!");
    ch.Open(5000);
}
catch (PhidgetException ex)
{
    Console.WriteLine("Failed to open: " + ex.Description)
}
</syntaxhighlight>
</syntaxhighlight>
 
|-|
The logging API supports the concept of a ''log source'', were the ''log source'' is a textual identifier of where the log message originated. The ''log source'' is output to log the log file along with the log message to help organize the data.
  C=<syntaxhighlight lang=c>
 
PhidgetDigitalInputHandle ch;
The following examples define and create a log source, and then write a log message using that source.
PhidgetReturnCode res;
 
...   
<syntaxhighlight lang=c>
res = Phidget_openWaitForAttachment((PhidgetHandle)ch, 5000);
#define MYSOURCE "mysource"
if (res != EPHIDGET_OK) {
PhidgetLog_addSource(MYSOURCE, PHIDGET_LOG_INFO);
    char* desc;
PhidgetLog_log(__FILE__, __LINE__, __func__, MYSOURCE, PHIDGET_LOG_INFO, "Something happened");
    Phidget_getErrorDescription(res, &desc);
    printf("Failed to open: (%d) %s\n", res, desc);
}
</syntaxhighlight>
</syntaxhighlight>
</tabber>


Or in Java:
The consequences of not handling errors correctly ranges from improper behavior, to the program crashing due to an unhandled exception.  Programs should check for errors on each function call, and handle any errors.


<syntaxhighlight lang=java>
====Error Codes====
public static final String MYSOURCE = "mysource";
Log.addSource(MYSOURCE, LogLevel.INFO);
Log.log(LogLevel.INFO, MYSOURCE, "Something happened);
</syntaxhighlight>


A list of error codes can be found in the {{Phidget22API}}.


==Exceptions and Errors==
===Error Events===


There are two different types of errors that you can use to determine where a problem exists in your program.
Error events are asynchronously generated by Phidget devices, and by the Phidget library itself.  


===Error Generated By Methods===
These do not necessarily indicate a problem with your program, and often serve as a status update from your device that your program should know. For example, a DistanceSensor might send an OutOfRange error if it does not detect anything in its field of view, or a TemperatureSensor could send a Saturation error indicating its temperature reading is outside the valid range for the sensor.


When an error occurs during a method invocation, either a language specific exception is thrown, or an error is returned.  It is important to check the return value from each method call, and to catch and handle exceptions.
Error events are also fired when network errors occur, or when the library is unable to handle incoming change events quickly enough (event handlers could be too slow).


For example, in C:
We strongly recommend setting up an error event handler for your channels so your program can keep track of these error conditions.


<syntaxhighlight lang=c>
<tabber>
  int
Java=<syntaxhighlight lang=java>
  main(int argc, char **argv) {
//Declare the event listener
     PhidgetReturnCode res;
public static ErrorListener onError = new ErrorListener() {
 
     @Override
    res = PhidgetLog_enable(PHIDGET_LOG_ERROR, NULL);
     public void onError(ErrorEvent e) {
     if (res != EPHIDGET_OK) {
        System.out.println("Code: " + e.getCode());
      fprintf(stderr, "failed to enable Phidget logging: %d\n", res);
        System.out.println("Description: " + e.getDescription());
      exit(1);
     }
     }
     exit(0);
};
  }
...
//Declare your object. Replace "DigitalInput" with the object for your Phidget.
DigitalInput ch;
...
//Assign the event listener that will be called when the event occurs
ch.addErrorListener(onError);
</syntaxhighlight>
|-|
Python=<syntaxhighlight lang=python>
#Declare the event handler
def onErrorHandler(self, code, description):
    print("Code: " + str(code))
    print("Description: " + description)
...
#Declare your object. Replace "DigitalInput" with the object for your Phidget
ch = DigitalInput()
...
#Assign the handler that will be called when the event occurs
ch.setOnErrorHandler(onErrorHandler)
</syntaxhighlight>
|-|
C#=<syntaxhighlight lang=cSharp>
//Declare the event handler
void error(object sender, Phidget22.Events.ErrorEventArgs e) {
     Console.WriteLine("Code: " + e.Code.ToString());
    Console.WriteLine("Description: " + e.Description);
}
...
//Declare your object. Replace "DigitalInput" with the object for your Phidget.
DigitalInput ch;
...
//Assign the handler that will be called when the event occurs
ch.Error += error;
</syntaxhighlight>
</syntaxhighlight>
 
|-|
Or in Java:
C=<syntaxhighlight lang=c>
 
//Declare the event handler
<syntaxhighlight lang=java>
static void CCONV onErrorHandler(PhidgetHandle ph, void *ctx, Phidget_ErrorEventCode code, const char* description) {
  try {
    printf("Code: %d\n", code);
      Log.enable(LogLevel.INFO, null);
    printf("Description: %s\n", description);
  } catch (PhidgetException ex) {
}
      System.out.println("Failed to enable Phidget logging: " + ex.getMessage());
...
  }
//Declare your object. Replace "PhidgetDigitalInputHandle" with the handle for your Phidget object.
PhidgetDigitalInputHandle ch;
...
//Assign the handler that will be called when the event occurs
Phidget_setOnErrorHandler((PhidgetHandle)ch, onErrorHandler, NULL);
</syntaxhighlight>
</syntaxhighlight>
</tabber>


The consequence of not handling errors correctly ranges from the program crashing if an unhandled exception occurs to improper behavior.  Program should check for errors on each method call, and handle any errors.
Full descriptions of all error event codes can be found in the [[Error Event Code List]] page.


====Error Codes====
==Logging==
 
You can enable logging to get more debugging information. This would happen at the very start of your program, before even initializing your software object or opening it. Logging lets you get feedback from the Phidget libraries about things happening behind the scenes.
A list of error codes can be found in the {{Phidget22API}}.  Refer to language specific exceptions in languages that support them.
 
===Error Events===
 
Error events are asynchronously generated by Phidget devices, and the Phidget library itself, during runtime.  A Phidget device might experience an excessive value (temperature, voltage, acceleration etc.), and trigger an error event to inform the program that is attached. This would not necessarily be due to any operation the program performed; instead, the operating environment of the Phidget device would likely be the cause.  Error events are also fired when network errors occur, or the library is unable to handle incoming change events quickly enough (event handlers could be too slow).
 
Error events are handled by setting an error event handler.
 
In C:


<syntaxhighlight lang=c>
<syntaxhighlight lang=c>
  void CCONV
PhidgetLog_enable(PHIDGET_LOG_INFO, NULL);
  errorEventHandler(PhidgetHandle ch, void *ctx, Phidget_ErrorEventCode code,
    const char *errorDescription) {
        Phidget_log(PHIDGET_LOG_ERROR, "Error Event [%d] %s", code, errorDescription);
  }
 
  // set the error event handler before opening the channel
  res = Phidget_setOnErrorHandler((PhidgetHandle) ch, errorEventHandler, NULL);
  if (res != EPHIDGET_OK) {
    Phidget_log(PHIDGET_LOG_ERROR, "Failed to set error handler for %P", ch);
    // XXX handle the error
  }
</syntaxhighlight>
</syntaxhighlight>


In Java:
Or in Java:


<syntaxhighlight lang=java>
<syntaxhighlight lang=java>
  ch.addErrorListener((ErrorEvent ee) -> {
Log.enable(LogLevel.INFO, null);
    System.err.println("Error: " + ee.getDescription());
  });
</syntaxhighlight>
</syntaxhighlight>


====Error Codes====
When <code>NULL</code> is passed to <code>enable()</code> in the above examples, the logging system will output to <code>STDERR</code>.  
 
These codes are passed to an  error event handler. See the {{Phidget22API}} documentation for your device to see which error event codes are supported.  The error event codes are generic, and the error description passed to the error event handler may contain more detailed information about the actual cause of the error event.
 
'''BADVERSION'''
:Version Mismatch Error. Usually means client and server library versions are out of sync. Update to the latest version of the Phidget software.
 
 
'''BUSY'''
:The Phidget device channel has already been locally attached. Only one channel may attach locally to a device channel.
 
 
'''NETWORK'''
:An error occurred with the network communications. See the error description for more details.
 
 
'''DISPATCH'''
:An error occurred when trying to dispatch an event. It's possible that the data rate is too fast for the computer (or network) and the event queue has filled up.
 
 
'''OK'''
: An error state has ended. You can use the <code>getDescription</code> method of the error event to get more information.
 
'''OVERRUN'''
:Sampling overrun. Some samples were lost in firmware because the queue filled up. This error is exclusive to Phidget InterfaceKits.
 
 
'''PACKETLOST'''
:Packet(s) were lost. This error is often an indication that your event handlers are not executing fast enough. Try to remove slow processes like GUI updates or user input from your handlers.
 
 
'''WRAP'''
:A variable has wrapped. For example, the encoder position can wrap from 2,147,483,647 to -2,147,483,648 because of an integer overflow.
 
 
'''OVERTEMP'''
:Over-Temperature condition detected. See error description for more details.
 
 
'''OVERCURRENT'''
:Over-Current condition detected. See error description for more details.
 
 
'''OUTOFRANGE'''
:Out of range condition detected. Usually an input on the board is reporting a value that is outside of the allowed range.
 
 
'''BADPOWER'''
:Power supply problem detected. Either the power supply is being overloaded, or it is under-powered (possibly not plugged in).
 
 
'''SATURATION'''
:A sensor's value has reached the maximum or minimum of its sensing range. For example, a 1000 lux light sensor will throw this error event when a value greater than 1000 lux is detected. The sensor will still be reporting 1000 lux, but this error tells you that you don't know for certain how much higher than 1000 the real reading is.
 
 
'''OVERVOLTAGE'''
:Over-Voltage condition detected. Occurs in power-providing Phidgets when the output voltage exceeds the set value.
 
 
'''VOLTAGEERROR'''
:A voltage error occurs when a Phidget that provides a voltage output has the value drop below what what specified. This can happen if the device being powered draws too much current, which causes a voltage drop. Stay within output current specifications to avoid voltage errors.
 


'''ENERGYDUMP'''
For a more comprehensive look at the logging system in Phidget22, you can check out the [[Logging Details]] page.
:An energy dump occurs when a power-providing Phidget needs to dissipate its extra energy. See the [[:Category:UserGuide|User Guide]] for your device for more information.


== Other Problems ==
== Other Problems ==

Revision as of 19:56, 30 October 2018

You've written your code, fixed the compiler errors, and yet, the program still isn't behaving as intended. The tools described on this page will help you further debug your program and figure out where in the code things are going wrong.

Errors and Error Events

The Phidget library uses errors and error events to communicate information about potential problems in your program. These can happen in-line in the form of an exception or error code (which generally indicate a problem in the code), and as Error Events (which generally indicate a problem with the Phidget's environment).

Errors from Function Calls

When a call to a Phidgets function fails it will throw an exception (or return an error code, depending on the language). It is important to check each function call for errors, and to catch and handle any errors.

Common causes of this type of errors are the Phidget not being attached, or one of the values provided to the function being outside the valid range.

You can handle exceptions and return codes as follows:

try {
    ch.open(5000);
} catch (PhidgetException ex) {
    System.out.println("Failed to open: " + ex.getMessage());
}
try:
    ch.openWaitForAttachment(5000);
except PhidgetException as e:
    print("Failed to open: " + e.details)
try
{
    ch.Open(5000);
}
catch (PhidgetException ex)
{
    Console.WriteLine("Failed to open: " + ex.Description)
}
PhidgetDigitalInputHandle ch;
PhidgetReturnCode res;
...    
res = Phidget_openWaitForAttachment((PhidgetHandle)ch, 5000);
if (res != EPHIDGET_OK) {
    char* desc;
    Phidget_getErrorDescription(res, &desc);
    printf("Failed to open: (%d) %s\n", res, desc);
}

The consequences of not handling errors correctly ranges from improper behavior, to the program crashing due to an unhandled exception. Programs should check for errors on each function call, and handle any errors.

Error Codes

A list of error codes can be found in the Phidget22 API.

Error Events

Error events are asynchronously generated by Phidget devices, and by the Phidget library itself.

These do not necessarily indicate a problem with your program, and often serve as a status update from your device that your program should know. For example, a DistanceSensor might send an OutOfRange error if it does not detect anything in its field of view, or a TemperatureSensor could send a Saturation error indicating its temperature reading is outside the valid range for the sensor.

Error events are also fired when network errors occur, or when the library is unable to handle incoming change events quickly enough (event handlers could be too slow).

We strongly recommend setting up an error event handler for your channels so your program can keep track of these error conditions.

//Declare the event listener
public static ErrorListener onError = new ErrorListener() {
    @Override
    public void onError(ErrorEvent e) {
        System.out.println("Code: " + e.getCode());
        System.out.println("Description: " + e.getDescription());
    }
};
...
//Declare your object. Replace "DigitalInput" with the object for your Phidget.
DigitalInput ch;
...
//Assign the event listener that will be called when the event occurs
ch.addErrorListener(onError);
#Declare the event handler
def onErrorHandler(self, code, description):
    print("Code: " + str(code))
    print("Description: " + description)
...
#Declare your object. Replace "DigitalInput" with the object for your Phidget
ch = DigitalInput()
...
#Assign the handler that will be called when the event occurs
ch.setOnErrorHandler(onErrorHandler)
//Declare the event handler
void error(object sender, Phidget22.Events.ErrorEventArgs e) {
    Console.WriteLine("Code: " + e.Code.ToString());
    Console.WriteLine("Description: " + e.Description);
}
...
//Declare your object. Replace "DigitalInput" with the object for your Phidget.
DigitalInput ch;
...
//Assign the handler that will be called when the event occurs
ch.Error += error;
//Declare the event handler
static void CCONV onErrorHandler(PhidgetHandle ph, void *ctx, Phidget_ErrorEventCode code, const char* description) {
    printf("Code: %d\n", code);
    printf("Description: %s\n", description);
}
...
//Declare your object. Replace "PhidgetDigitalInputHandle" with the handle for your Phidget object.
PhidgetDigitalInputHandle ch;
...
//Assign the handler that will be called when the event occurs
Phidget_setOnErrorHandler((PhidgetHandle)ch, onErrorHandler, NULL);

Full descriptions of all error event codes can be found in the Error Event Code List page.

Logging

You can enable logging to get more debugging information. This would happen at the very start of your program, before even initializing your software object or opening it. Logging lets you get feedback from the Phidget libraries about things happening behind the scenes.

PhidgetLog_enable(PHIDGET_LOG_INFO, NULL);

Or in Java:

Log.enable(LogLevel.INFO, null);

When NULL is passed to enable() in the above examples, the logging system will output to STDERR.

For a more comprehensive look at the logging system in Phidget22, you can check out the Logging Details page.

Other Problems

If your Phidget is still not behaving as expected after handling errors and exceptions, have a look at our General Troubleshooting guide to track down the problem.

Further Reading

Phidget Programming Basics - Here you can find the basic concepts to help you get started with making your own programs that use Phidgets.

Data Interval/Change Trigger - Learn about these two properties that control how much data comes in from your sensors.

Using Multiple Phidgets - It can be difficult to figure out how to use more than one Phidget in your program. This page will guide you through the steps.

Polling vs. Events - Your program can gather data in either a polling-driven or event-driven manner. Learn the difference to determine which is best for your application.

Phidget Network Server - Phidgets can be controlled and communicated with over your network- either wirelessly or over ethernet.

Best Phidgets Practices - Good programming habits that will save you from common problems when writing code for your Phidgets.