Notifications

Overview of Camera- and Property-Events

Through the CameraSDK, notifications can be received on the Host computer. These can be on various levels: The SDK, the camera, or the properties (of the camera). The levels correspond to a notification type each: SdkEvents, CameraEvents or PropertyEvents.

All notifications, regardless of type, have to be enabled for the events to generate notifications. These notifications can be enabled or disabled at any time.

To listen for notifications, construct an instance of the Listener class:

P1::CameraSdk::Listener listener;
Listener listener = new Listener();

The Listener class acts as a notification-central, where the notifications from enabled events arrive. You receive the incoming notifications by calling the blocking method: WaitForNotification. Since it is blocking it should be called from a separate thread (see Begin Listening for Notifications).

The thread listening for notifications should be offloaded by using other threads to handle “reactions” to the notifications (see A Thread-model for the CameraSDK). In case the listening thread is blocked, notifications are queued, and the next call to WaitForNotification will return the waiting notifications, in order. This way, notifications are not lost.

Multiple notifications can be enabled per Listener. Furthermore, multiple Listener instances can be created, as needed. Each instance of Listener acts independently of other Listener instances.

SDK Events

An SdkEvent is an event describing a change at the CameraSDK-level. For instance, if the CameraSDK finds a camera, a notification of the type “SdkEvent” is generated.

An example of listening for the event of a camera being found (CameraFound) is shown below:

listener.EnableNotification(P1::CameraSdk::SdkEventId::kSdkEventCameraFound);
listener.EnableNotification(SdkEventId.CameraFound);

SDK Events will tell you when USB cameras are discovered and when they disappear. The CameraFound notification and its counter type CameraRemoved, informs you about the visible USB cameras. It does not matter whether you are connected (camera is opened), or not.

Caution

TCP/IP cameras are not discovered. You will not receive any found or removed notifications from TCP/IP cameras.

Camera Events

The CameraEvent class of events, signifies changes originating in camera. For example, if the CameraSDK receives an image. This can be seen in the example below:

listener.EnableNotification(camera, P1::CameraSdk::CameraEventId::kCameraEventImageReady);
listener.EnableNotification(camera, CameraEventId.ImageReady);

Camera events belong to 4 categories: image receiving, connection, LiveView & property lifetime. The next few sections will examine these in more detail.

Image Receiving

These are camera events that provide progress reporting on the image transfer between camera and host. When the camera starts transferring an image, the ImageTransferBegin event is received. At rate-limited intervals the SDK will provide the TransferProgress event, until the entire image is present in SDK memory. Then ImageReady is received, and the image can be fetched from the camera’s WaitForImage method, without any blocking delay.

Connection

The Disconnected camera event indicates that the connection (USB / TCP) is lost. This is either by intention or as a result of a link error. You will receive the Disconnect event after you call Close on the camera. Similarly, you will receive the same event if the USB or network cable has suddenly been unplugged. The Disconnect event itself cannot tell you with scenario it comes from!

LiveView

The LiveView related camera events will indicate when LiveView is started or stopped. Also, the NewLiveViewImage tells you that a new LiveView image is pending, and can be obtained from the camera’s WaitForLiveView method.

Property Lifetime

These are camera events that advertises about camera properties that appear or disappear. The camera can change mode, which might trigger new properties to become available.

Property Events

A PropertyEvent-type notification is triggered upon the changing of a value in a property, such as the “aperture” being set to “5.6”.

To receive notifications about property events, notifications have to be enabled for the desired property (e.g. “aperture” or “ISO”).

When enabling notifications for a property, a notification arrives when the property changes value.

An example of how to listen for a change in the “aperture”-property can be seen below:

listener.EnableNotification(camera, 1003); // Aperture
listener.EnableNotification(camera, 1003); // Aperture

Note

An attempt to set the value to its current value (e.g. “5.6” –> “5.6”) will not generate a notification.

Specification Change Events

By default a property event denote a change in the property’s value. However, the property’s specification (PropertySpec) might also change. These changes could be the read only state or a change in the list of valid values (the value Map).

Just as you can listen for value changes, you can likewise listen for specification changes - that does not change the property’s value.

Arriving specification change notifications, are of the SpecificationChange type, where as property value change notification are of type Property.

To enable notifications for specification changes, you use the same EnableNotification method, but provide a 3rd argument:

listener.EnableNotification(camera, 1003, true); // 1003 is Aperture
listener.EnableNotification(camera, 1003, isSpecificationChange: true); // 1003 is Aperture

This 3rd and optional argument defaults to false. If you explicitly set it to true you will receive only specification state changes for the given property id and camera.

You can enable both property value and specification change notifications, with two calls the method - one for each type. They can exist independently from each other.

Similarly, you disable specification changes by calling DisableNotification and providing a 3rd argument set to true:

listener.DisableNotification(camera, 1003, true); // 1003 is Aperture
listener.DisableNotification(camera, 1003, isSpecificationChange: true); // 1003 is Aperture

Begin Listening for Notifications

When notifications have been enabled for the desired events, the listening for notifications can begin. A thread will have to continuously listen for the events, regardless of event type. This thread executes the WaitForNotification method, as can be seen below:

void listenRoutine(P1::CameraSdk::Listener listener)
{
	P1::CameraSdk::NotificationEvent arrivednotification;
	while (true)
	{
		bool success = listener.WaitForNotification(arrivednotification);

		if (success == false)
		{
			std::cout << "Signalled wake-up!\n";
			break;
		}
		else
		{
			std::cout << "Notification received\n";
		}

		if (arrivednotification.mSdkEventId == P1::CameraSdk::SdkEventId::kSdkEventCameraFound)
		{
			std::cout << "Camera found\n";
			break;
		}
		// Handle other notification types here...
		else
		{
			std::cout << "Got unknown:" << arrivednotification.mNotificationType << std::endl;
		}
	}

}
var listenThread = new Thread(() => {
    while (true)
    {
        NotificationEvent? notification = listener.WaitForNotification();
        if (notification.HasValue == false)
        {
            Console.WriteLine("Signalled wake-up!");
            break;
        }
        if (notification.Value.SdkEventId == SdkEventId.CameraFound)
        {
            Console.WriteLine("Camera Found");
            break;
        }
        // Handle other notification types here...
        else if (notification.Value.PropertyId == apertureId)
    {
            Console.WriteLine("Aperture changed");
            break;
    }
        else
        {
            Console.WriteLine("Got unexpected: {0}", notification);
            break;
        }
    }
});
listenThread.Start();

Output: (if the notification was not otherwise handled):

Got unexpected: NotificationEvent (SdkEvent): CameraRemoved

Stop Listening for Notifications

Upon terminating the application, the listening for notifications should terminate as well. To accomplish this, the CameraSDK has a function to release the thread listening for notifications in the specific Listener, as follows:

// Force the pending thread in WaitForNotification() to be released
listener.WakeUpWaitingThread();
// Wait here until listen thread has terminated gracefully
listenThread.join();
// Force the pending thread in WaitForNotification() to be released
listener.WakeUpWaitingThread();
// Wait here until listen thread has terminated gracefully
listenThread.Join();

Notification Payloads

Each notification type can deliver optional payloads or context data. The NotificationEvent object defines members that are populated only for specific notification and event types. These members provide contextual information about the notification.

The table below list the available payload members of NotificationEvent and the conditions that must be met, for them to be populated with meaningful values:

Member Field

Description

Condition

PropertyId

The Id of the property that is changed

All Property typed notifications

CameraInfo

A small struct describing the cameras connection type, IP, serial, etc.

SdkEvent typed notifications, where SdkEvent is either CameraFound or CameraRemoved

TransferProgressPercent

A progress status for image transfers, in percent.

CameraEvent typed notifications, where CameraEvent is ImageTransfer

Catch All Listeners

The Listener class has a special catch all state, that enables receiving every single notification posted by the SDK, without the need for calling EnableNotification for every notification first.

Notifications are received for all notification types, for every event, across all opened cameras. Also, notifications will be enabled for properties that are not yet visible, (due to the cameras state).

If you enable the catch all state on a Listener before you open the first camera, you will receive the (CameraEvent type) notification CameraEventPropertyAdded, when you open any cameras.

To enable catch all on a Listener instance:

listener.EnableCatchAllNotifications();
listener.EnableCatchAllNotifications();

Disable Catch All State

The catch all state can be disabled at any time, by calling:

listener.DisableCatchAllNotifications();
listener.DisableCatchAllNotifications();

This effectively deactivates the delivery of all notification types to the Listener instance. The instance’s state is returned to normal, where only enabled notifications will be delivered. (The ones enabled by calling EnableNotification.)

If Listener already has any explicitly enabled notifications, these will be preserved. Thus, these are not affected by disabling the catch all state.

Warning

Be aware that disabling the catch all state, does not clear the listeners queue of incoming notifications. Calls to WaitForNotification might return notifications queued up before the call to DisableCatchAllNotifications.