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:
- Start monitoring an event of interest.
- Get noticed every time when the event happens.
- Acquire newly updated event data if needed.
- 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.