Handling changes#

The interaction with a device isn’t always unidirectional. In certain cases, the client code may be interested in reacting to changes or events occurring in the camera. During an acquisition, for instance, the temperature of the device may increase and the user could be interested in monitoring that variation by looking at the value changes of the DeviceTemperature node. He can also be interested in being notified when the camera completes some tasks, such an exposure end event. This kind of functionality is exposed on the device nodemap and can be configured via GenApi, which provides callback functionality to detect and react to node changes. A callback can be registered the in following way:

Node changes may occur for different reasons. Here’s a quick brief.

Invalidation#

Some features are linked to others. A typical example is the PayloadSize feature. If the pixel format of the camera changes, e.g. from Mono8 to Mono12p, the size of the image payload changes accordingly. That means the PayloadSize feature is invalidated by the pixel format change and should be read again by the client code. The client code can react to the value change of the PayloadSize node by registering a custom callback to it.

Polling#

The change in value of some read only nodes like DeviceTemperature isn’t related to other features. If the device temperature is actually changed inside the camera, to see the change of the corresponding feature’s value the user needs to manually perform a polling on the nodemap via the dedicated GenApi function. Every “pollable” feature has a specific polling time defined by the manufacturer. When the itala.itala.INodeMap.poll() function is called on the nodemap by the client code, the time elapsed since the last poll must be specified. Every feature with a polling time shorter than the elapsed time is automatically read and updated by GenApi. At this point the callback registered to it is called (if any).

Events#

Events allow signaling from the device to the client code. Every event is represented by a dedicated feature on the device nodemap. Additional features related to that event may be available. For instance, the EventExposureEnd feature represent the exposure end event of the camera and the EventExposureEndTimestamp feature is related to it: it can be read to get the exact time in which the exposure has ended. When the EventExposureEnd event occurs, its related features are automatically updated by ItalaApi’s internal event listening thread.

Note

Event feature names and types are also standardized by SFNC (Standard Feature Naming Convention), which is part of the GenICam standard. Please refer to the official SFNC document to gather information about a particular chunk. Refer to the official GenICam document to find a more in-depth description of the standard. All the material is freely accessible from the GenICam Introduction page.

The event functionality for a device must be enabled manually from its itala.itala.IDevice interface so that ItalaApiPython can start listening for events coming from that device. For the device side, each event the client code is interested in, must be enabled via the device nodemap.

# Select the ExposureEnd event and enable the notification for it.
# The device is now configured to send events to the host.
event_selector = device.node_map.EventSelector
event_selector.from_string("ExposureEnd")
event_notification = device.node_map.EventNotification
event_notification.from_string("On")

# Enable the event listening functionality on the host.
device.enable_events();

From now on, the event releated features are automatically updated by ItalaApi and their callbacks are executed. When the event functionality is no longer required, it must be disabled on both host and device side.

# Select the ExposureEnd event and disable the notification for it.
event_selector.from_string("ExposureEnd")
pEventNotification.from_string("Off")

# Disable the event listening functionality on the host.
pDevice.disable_events()

Alternatively to the callback, the client code can be notified of events by implementing the dedicated itala.itala.DeviceEventHandler class. In the present version only events raised from the device are supported. The configuration process via GenApi and itala.itala.IDevice.enable_events()/itala.itala.IDevice.disable_events() is still needed.

# Implement a custom handler
class ExposureEndEventHandler(itala.DeviceEventHandler):
   def __init__(self, device):
      itala.DeviceEventHandler.__init__(self)
      self.device = device
   def on_device_event(self, eventId):
      nodemap = self.device.node_map
      event_exposure_end_node = nodemap.EventExposureEnd
      if(eventId == event_exposure_end_node.value):
          event_exposure_end_timestamp_node = nodemap.EventExposureEndTimestamp
          print("ExposureEndEvent detected by the Handler, timestamp is " + str(event_exposure_end_timestamp_node.value))

# Instantiate and register the user-defined handler
exposure_end_handler = ExposureEndEventHandler(device)
device.register_handler(exposure_end_handler)

# Acquire and enjoy events..

# Deregister the handler
device.deregister_handler()

The itala.itala.DeviceEventHandler.on_device_event() function is called by ItalaApi when the device event occurs. The eventId parameter allows the client code to identify which particular event triggered the call.