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);
}
|