Handling Events

Our lives never get be static. As long as we live in own life, everything is lead by events as stimulation. As people who are trying to model dynamic systems, handling events is one of the important features and the GenTL Standard actually covers it. A basic usage of the event feature that GenTL defines goes like this:

  1. Start monitoring an event of interest.
  2. Get noticed every time when the event happens.
  3. Acquire newly updated event data if needed.
  4. Stop monitoring the event.

To handle events, API consumers manipulate unique classes those derive from BaseEventManager class. The following class diagram shows the relationship between relevant classes. The image is stretched following the browser size, or you could see it in the original size opening the image in another tab/window.

As we were hinted in the beginning, we interact with events using classes which derive from BaseEventManager class. Every event class corresponds to a unique event type that is defined in EVENT_TYPE_LIST (and technically speaking it possible to design your own custom class, too) and every event class provides event data such as a buffer filled up with an image, feature name, or feature value, as its properties for its consumer.

If we interact with EVENT_ERROR, we manipulate an EventManagerError class object to access its event data. If we interact with EVENT_FEATURE_CHANGE, we manipulate an EventManagerFeatureChange object for the same purpose. Yes, the class names follow a convention such that EventManager + EventName. It’s not necessary but it should be helpful anyway.

Every class that derives from BaseEventManager class should have properties to provide a way to access its event data. For example, EventManagerNewBuffer class provides buffer property to allow consumers to access the delivered image data and its user data tagged on the raw buffer; EventManagerError class provides gc_error property and description property to report the error code and the description.

So let’s try to walk through the following steps to see how we can interact with the event data of EVENT_ERROR event:

The following import statement is required for this tutorial.

from genicam.gentl import EventManagerError, GenTLProducer
from genicam.gentl import DEVICE_ACCESS_FLAGS_LIST, EVENT_TYPE_LIST
from genicam.gentl import NotImplementedException, TimeoutException

First, accessing a Device object of TLSimu, instantiate a DataStream object calling open_data_stream() method of the Device object. In the following example, it opens the first DataStream object.

data_stream = device.create_data_stream()
data_stream.open(device.data_stream_ids[0])

Next, register EVENT_ERROR event on the DataStream object. Then you’ll get an EventToken object as its return. You have nothing to do with it. Everything will be fine if you just pass it to the constructor of EventManagerError class later.

event_token = data_stream.register_event(EVENT_TYPE_LIST.EVENT_ERROR)

Then instantiate an EventManagerError object with EventToken object. Once you instantiated an event manager object, there’s nothing to do with the event source module about the event. In this case, the source of the event is a Device object. Like Device class, classes those realize IEventCapableModule, they are used to just register event types to start monitoring them. Checking status of the event queue, fetching event data, stopping monitoring the event, or the other event related manipulations all close in the event manager class objects those derive from BaseEventManager class.

event_manager = EventManagerError(event_token)

Good, you’ve got an EventManagerError object. As long as you hold it, you can monitor the target event. So now we need to intentionally cause an error event to let the DataStream object to raise an exception (the actual GenTL function must be returning an error code at the time). As an example, we try to register an unsupported event on the object. It will raise NotImplementedException and we try to get the error over EventManagerError class object.

assert event_manager.num_in_queue == 0
try:
    data_stream.register_event(EVENT_TYPE_LIST.EVENT_CUSTOM_ID - 1)
except NotImplementedException as e:
    # Caught an expected NotImplementedException so we are okay.
    print(e)

Now we can explicitly notice the error accessing the event data over gc_error and description properties of the EventManagerError object. First, you should be able to confirm num_in_queue is greater than 0 because we have already caused an error. Then to update the event data that is being held by EventManagerError object, we call update_event_data() method of it. Having called that method, its properties, gc_error and description are now up to date. The update_event_data() method waits the duration that is specified by its parameter, then it raises TimeoutException exception if nothing happened during the period.

assert event_manager.num_in_queue > 0
try:
    timeout = 1000  # [ms]
    event_manager.update_event_data(timeout)
    print(
        event_manager.gc_error,
        ':',
        event_manager.description
    )
except TimeoutException as e:
    # Nothing happened during the period specified by timeout.
    print(e)

After that, here we have reached to a place where we tear it down. To tear it down, flush the event queue and unregister the event. As we were mentioned earlier, everything is closed in the event manager class object.

event_manager.flush_event_queue()
event_manager.unregister_event()

Having that procedures you have stopped monitoring the event and you have been free from the duty. That’s all about the basic knowledge about handling events with the GenTL-Python Binding. You may learn about other events in the following chapters.