Error Handling and Logging

Error-handling in both SDKs are done via exceptions. In this section, it is briefly described how to handle exceptions for C# and C++.

Exceptions are thrown e.g. if the CameraSDK cannot connect to the camera (CameraCouldNotConnect), or on an attempt to set a property with a type that it does not support (PropertyTypeInvalid).

When catching exceptions, it is recommended to catch the most specific exceptions first, and end with the most general.

In summary, if anything goes wrong, an exception is thrown.

Caution

Both the CameraSDK and the ImageSDK throws SdkException objects. Note, that they reside in different namespaces, so the exceptions need to be explicitly caught from both SDKs.

Error handling in C#

In C#, all exceptions thrown are of the SdkException type. The exceptions contain an ErrorCode (used to determine which kind of exception occurred) and ErrorMessage (used to describe the error) property.

To filter the exceptions, you use the ErrorCode property upon catching:

// Open camera through USB connection
try
{
    var camera = Camera.OpenUsbCamera();
}
// Catch specific exception, thrown if the camera cannot be found
catch(SdkException e) when (e.ErrorCode == ErrorCode.CameraNotFound)
{
    //Write the errormessage to console
    Console.WriteLine($"Camera not opened, error: {e.Message}");
}

Output (if there was no camera connected via USB):

Camera not opened, error: No such camera found

Note

In C#, a timeout will not throw an exception. Instead, a null-value will be returned. This is due to the expensive nature of C# exceptions.

Error handling in C++

In C++, exceptions inherit from SdkException. The exceptions contain an error code, which can be accessed through the mErrorCode variable. The descriptions of the exception can be accessed through the what() method.

To filter the exceptions, you declare the specific exception-type in the catch-block:

Camera camera;

// Open the camera through the USB connection
try
{
    camera = Camera::OpenUsbCamera();
}

// Catch specific exception is the camera could not be located
catch(SdkCameraNotFoundExc e)
{
    std::cout << "Could not find any connected USB camera\n";
}

// Catch other SdkException exceptions
catch(SdkException e)
{
    std::cout << "An error ocurred while opening the camera: " << e.what() << std::endl;
}

In the above example, the SdkCameraNotFoundExc is more specific than SdkException, and is caught first. This ordering is needed, as SdkCameraNotFoundExc inherit from SdkException.

Logging

Logging can be used to investigate the behavior of the SDKs, e.g. to analyze how they handle certain situations, or to determine the reason for an error.

To enable logging, you use the SetSdkLoggingHandler method. Then, the logging-handlers can be configured to output the log messages. The log-messages has four different levels: ERROR, WARNING, INFO and VERBOSE, in order of severity. The level of each log message is determined by the SDKs.

As with the exception classes, each SDK also defines its own logging. This means separate SetSdkLoggingHandler and separate enums for ERROR, WARNING, etc. ImageSDK logging enums cannot be used with the CameraSDK variant of SetSdkLoggingHandler.

void CameraSdkLoggingHandler(const char* message, P1::CameraSdk::LogMessageLevel level)
{
	using P1::CameraSdk::LogMessageLevel;
	switch (level)
	{
	case LogMessageLevel::ERROR:
		std::cout << "[E] : " << message;
		break;
	case LogMessageLevel::WARNING:
		std::cout << "[W] : " << message;
		break;
	case LogMessageLevel::INFO:
		std::cout << "[I] : " << message;
		break;
	case LogMessageLevel::VERBOSE:
		std::cout << "[V] : " << message;
		break;
	default:
		std::cout << "[?] : " << message;
		break;
	}
}
void ImageSdkLoggingHandler(const char* message, P1::ImageSdk::LogMessageLevel level)
{
	using P1::ImageSdk::LogMessageLevel;
	switch (level)
	{
	case LogMessageLevel::Error:
		std::cout << "[E] : " << message;
		break;
	case LogMessageLevel::Warning:
		std::cout << "[W] : " << message;
		break;
	case LogMessageLevel::Info:
		std::cout << "[I] : " << message;
		break;
	case LogMessageLevel::Verbose:
		std::cout << "[V] : " << message;
		break;
	default:
		std::cout << "[?] : " << message;
		break;
	}
}
public static void CameraSdkLoggingHandler(P1.CameraSdk.Sdk.LogMessageLevel level, string message)
{

    switch (level)
    {
        case P1.CameraSdk.Sdk.LogMessageLevel.ERROR:
            Console.WriteLine("[E] : {0}", message);
            break;
        case P1.CameraSdk.Sdk.LogMessageLevel.WARNING:
            Console.WriteLine("[W] : {0}", message);
            break;
        case P1.CameraSdk.Sdk.LogMessageLevel.INFO:
            Console.WriteLine("[I] : {0}", message);
            break;
        case P1.CameraSdk.Sdk.LogMessageLevel.VERBOSE:
            Console.WriteLine("[V] : {0}", message);
            break;
        default:
            Console.WriteLine("[?] : {0}", message);
            break;
    }
}

private static void ImageSdkLoggingHandler(P1.ImageSdk.Sdk.LogMessageLevel level, string message)
{
    switch (level)
    {
        case P1.ImageSdk.Sdk.LogMessageLevel.ERROR:
            Console.WriteLine("[E] : {0}", message);
            break;
        case P1.ImageSdk.Sdk.LogMessageLevel.WARNING:
            Console.WriteLine("[W] : {0}", message);
            break;
        case P1.ImageSdk.Sdk.LogMessageLevel.INFO:
            Console.WriteLine("[I] : {0}", message);
            break;
        case P1.ImageSdk.Sdk.LogMessageLevel.VERBOSE:
            Console.WriteLine("[V] : {0}", message);
            break;
        default:
            Console.WriteLine("[?] : {0}", message);
            break;
    }
}
P1::CameraSdk::SetSdkLoggingHandler(CameraSdkLoggingHandler);
P1::ImageSdk::SetSdkLoggingHandler(ImageSdkLoggingHandler);
P1.CameraSdk.Sdk.Get.SetLoggingHandler(CameraSdkLoggingHandler);
P1.ImageSdk.Sdk.SetLoggingHandler(ImageSdkLoggingHandler);