IDS Peak comfortSDK, genericSDK, IPL, and AFL developer manuals are external documents. Please contact us if you need them.
Before you can receive an event from the camera, you must activate it in the camera, e.g. the start of the exposure ("ExposureStart").
genericC++
|
nodemapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("EventSelector")->SetCurrentEntry("ExposureStart");
// Enable continuous notification
nodemapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("EventNotification")->SetCurrentEntry("On");
// Enable one time notification
nodemapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("EventNotification")->SetCurrentEntry("Once");
// Disable notification
nodemapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("EventNotification")->SetCurrentEntry("Off");
|
Receiving camera events on the host PC works similarly to waiting for images. It should be done in a separate thread. Here, a thread is used under Qt and first a worker class is defined (see also Receiving images).
Additionally, the camera object (std::shared_ptr<peak::core::Device>) and the EventController are required.
genericC++
|
class EventWorker : public QObject
{
Q_OBJECT
public:
EventWorker(std::shared_ptr<peak::core::Device> device, QObject parent);
~EventWorker();
private:
std::shared_ptr<peak::core::Device> m_device;
std::unique_ptr<peak::core::EventController> m_eventController;
std::shared_ptr<peak::core::NodeMap> m_nodemapRemoteDevice;
bool m_running;
public slots:
void Start();
};
|
Implementing the worker class
genericC++
|
EventWorker::EventWorker(std::shared_ptr<peak::core::Device> device, QObject parent) : QObject(parent)
{
m_device = device;
m_eventController = nullptr;
m_nodemapRemoteDevice = m_device->RemoteDevice()->NodeMaps().at(0);
m_running = false;
}
EventWorker::~EventWorker()
{
}
void EventWorker::Start()
{
try
{
// Enable events from the camera (remote device)
m_eventController = m_device->EnableEvents(EventType::RemoteDevice);
if (!m_eventController)
{
// ...
return;
}
}
catch (std::exception& e)
{
// ...
return;
}
m_running = true;
while (m_running)
{
try
{
// Wait an infinite time for events
auto event = m_eventController->WaitForEvent(peak::core::Timeout::INFINITE_TIMEOUT);
// Insert event into tree
m_nodemapRemoteDevice->UpdateEventNodes(event);
auto type = peak::core::ToString(event->Type());
if (peak::core::EventType::RemoteDevice == event->Type())
{
// Get unique identifier of the exposure start event and check if the received event has the same id
uint64_t exposureStartID = static_cast<uint64_t>(m_camera->GetNodemapRemoteDevice()->FindNode<peak::core::nodes::IntegerNode>("EventExposureStart")->Value());
if (event->ID() == exposureStartID)
{
// ...
}
}
}
catch (std::exception& e)
{
// ...
}
}
}
|
Creating and starting the worker thread in main program
genericC++
|
void mainProgram()
{
// ...
// Create worker thread
EventWorker* m_eventWorker = new EventWorker();
QThread m_eventThread;
// Move the worker to a new thread
m_eventWorker ->moveToThread(&m_eventThread);
// Call Start() slot of the worker when QThread starts
connect(&m_eventThread, SIGNAL(started()), m_eventWorker , SLOT(Start()));
// Start QThread
m_eventThread.start();
}
|
Alternative solution in C++ with a standard thread
genericC++
|
class EventWorker
{
public:
EventWorker(const std::shared_ptr<peak::core::Device>& device);
~EventWorker();
EventWorker(const EventWorker& o) = delete;
EventWorker& operator=(const EventWorker& o) = delete;
EventWorker(EventWorker&& o) = default;
EventWorker& operator=(EventWorker&& o) = default;
private:
void run();
std::shared_ptr<peak::core::Device> m_device;
std::unique_ptr<peak::core::EventController> m_eventController;
std::shared_ptr<peak::core::NodeMap> m_nodemapRemoteDevice;
std::atomic_bool m_running{ false };
std::thread m_listenerThread;
};
|
genericC++
|
EventWorker::EventWorker(const std::shared_ptr<peak::core::Device>& device)
: m_device(device)
{
// Enable events from the camera (remote device)
m_eventController = std::move(m_device->EnableEvents(peak::core::EventType::RemoteDevice));
m_nodemapRemoteDevice = m_device->RemoteDevice()->NodeMaps().at(0);
// Enable "ExposureStart" event on the camera
m_nodemapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("EventSelector")
->SetCurrentEntry("ExposureStart");
m_nodemapRemoteDevice->FindNode<peak::core::nodes::EnumerationNode>("EventNotification")
->SetCurrentEntry("On");
// Enable additional events
// ...
// Start the event listener thread
m_listenerThread = std::thread([this]() {
run();
});
}
EventWorker::~EventWorker()
{
// Stop the event listener thread
m_running = false;
if (m_listenerThread.joinable()) {
try {
// Stop the current WaitForEvent()
m_eventController->KillWait();
}
catch (const peak::core::Exception&) {
// ignore
}
m_listenerThread.join();
}
}
void EventWorker::run()
{
m_running = true;
while (m_running) {
try {
auto event = m_eventController->WaitForEvent(
peak::core::Timeout::INFINITE_TIMEOUT);
if (event->Type() != peak::core::EventType::RemoteDevice)
{
// error ...
}
m_nodemapRemoteDevice->UpdateEventNodes(event);
// Get unique identifier of the exposure start event and check if the received event has the same id
uint64_t exposureStartID = static_cast<uint64_t>(m_nodemapRemoteDevice->FindNode<peak::core::nodes::IntegerNode>("EventExposureStart")->Value());
if (event->ID() == exposureStartID)
{
// Handle event ...
}
// Handle additional events
// ...
}
catch (const peak::core::Exception& e) {
// ...
}
}
}
|
genericC++
|
void mainProgram() {
// ...
// Create worker thread
EventWorker eventWorker(device);
}
|