DeviceAgent variables pertaining only to the attached device
AnsweredHaving an issue with a threaded event in a test plugin in that a variable holding the deviceInfo->name does not appear differently for each camera attached.
Taking stub diagnostic_events as template I've ignored the engine thread and just want a DeviceAgent timed event that displays a notice with the camera name and the number of seconds delay.
My eventThreadLoop
void DeviceAgent::eventThreadLoop()
{
while (!m_terminated)
{
std::string caption = "Info message from camera " + cameraName;
std::string description = "Timed at " + std::to_string(amountOfSeconds) + " seconds.";
pushPluginDiagnosticEvent(
IPluginDiagnosticEvent::Level::info,
caption,
description);
// Sleep until the next event needs to be generated, or the thread is ordered to
// terminate (hence condition variable instead of sleep()). Return value (whether
// the timeout has occurred) and spurious wake-ups are ignored.
std::unique_lock<std::mutex> lock(m_eventThreadMutex);
if (m_terminated)
break;
{
static const std::chrono::seconds kEventGenerationPeriod{amountOfSeconds};
m_eventThreadCondition.wait_for(lock, kEventGenerationPeriod);
}
}
}
amountOfSeconds is a long that is set in the constructor as is cameraName
amountOfSeconds = 25;
cameraName = deviceInfo->name();
However, when I attach the plugin to two cameras I get two lots of PluginDiagnosticEvent notices as expected, and theym are 25 seconds apart for each device, but they all have the same camera name in the message.
How can I ensure variables set in the DeviceAgent retain their individuality to that device and are not seemingly shared among all attached devices? This will become a bigger issue when the number of seconds is passed in from settings and needs to be different for each device.
Thanks
Graham
-
Hello Graham Parry,
Could you, please, provide OS version, VMS build number, Metadata SDK version?
Could you share the entire plugin code, please?
0 -
Hi Andrey
So this is Windows, Nx Witness 5.0.0.35745 and MetadataSDK 5.0.
I seem to have solved one problem in that if I create my variables in device_agent.h protected: they will only pertain to the device attached.
However, threading is proving tricky. If I take the Stub Diagnostics sample as a template I can get notices appearing, but as I start to add other elements I end up with the key thread method only firing once or not at all.
The code is:
device_agent.h
protected:
virtual void doSetNeededMetadataTypes(
nx::sdk::Result<void>* outValue,
const nx::sdk::analytics::IMetadataTypes* neededMetadataTypes) override;virtual std::string manifestString() const override;
virtual nx::sdk::Result<const nx::sdk::ISettingsResponse*> settingsReceived() override;
virtual bool pushUncompressedVideoFrame(
const nx::sdk::analytics::IUncompressedVideoFrame* videoFrame) override;std::string selectedCameraName;
long selectedDelayInSeconds;device_agent.cpp
DeviceAgent::DeviceAgent(const nx::sdk::IDeviceInfo* deviceInfo) :
// Call the DeviceAgent helper class constructor telling it to verbosely report to stderr.
ConsumingDeviceAgent(deviceInfo, /*enableOutput*/ true)
{
selectedCameraName = deviceInfo->name();
startEventThread();
}DeviceAgent::~DeviceAgent()
{
stopEventThread();
}void DeviceAgent::startEventThread()
{
m_eventThread = std::make_unique<std::thread>([this]() { eventThreadLoop(); });
}void DeviceAgent::stopEventThread()
{
{
std::unique_lock<std::mutex> lock(m_eventThreadMutex);
m_terminated = true;
m_eventThreadCondition.notify_all();
}m_eventThread->join();
}void DeviceAgent::eventThreadLoop()
{
while (!m_terminated)
{
doSomethingHere();
// Sleep until the next event needs to be generated, or the thread is ordered
// to terminate (hence condition variable instead of sleep()). Return value
// (whether the timeout has occurred) and spurious wake-ups are ignored.
{
std::unique_lock<std::mutex> lock(m_eventThreadMutex);
if (m_terminated)
break;
static const seconds kEventGenerationPeriod{ selectedDelayInSeconds };
m_eventThreadCondition.wait_for(lock, kEventGenerationPeriod);
}
}
}void DeviceAgent::doSomethingHere()
{
std::string caption = "This is a notice from camera " + selectedCameraName;
std::string description = "At an interval of " + std::to_string(selectedDelayInSeconds) + " seconds";pushPluginDiagnosticEvent(
IPluginDiagnosticEvent::Level::info,
caption,
description);
}The delay in seconds is created by a spin box in the settings model
settings_model.h
{
"type": "SpinBox",
"name": ")json" + kSettingsModelSecondsIntervalSpin + R"json(",
"caption": "Interval (seconds) before event",
"defaultValue": 20,
"minValue": 1,
"maxValue": 1000000
},and is picked up here
device_agent.cpp
Result<const ISettingsResponse*> DeviceAgent::settingsReceived()
{
const auto settingsResponse = new sdk::SettingsResponse();settingsResponse->setModel(kSettingsModel);
selectedDelayInSeconds = std::stol(settingValue(kSettingsModelSecondsIntervalSpin));
// The manifest depends on some of the above parsed settings, so sending the new manifest.
pushManifest(manifestString());return settingsResponse;
}My project involves multiple cameras attached to the plugin performing a function at an interval set for each device, so I need to get these threading issues sorted before I move on to the more complex procedures.
0 -
Hello Graham,
Could you, please, provide OS version, VMS build number, Metadata SDK version?
So this is Windows, Nx Witness 5.0.0.35745 and MetadataSDK 5.0.
Which of Windows do you use: 11/10/8/7 ? Could you specify the build number of the Metadata SDK, please?
Could you share the entire plugin code, please?
Could you please just archive the folder containing your plugin code, place the archive on any cloud storage you like and share the link here?
I seem to have solved one problem in that if I create my variables in device_agent.h protected: they will only pertain to the device attached.
Congratulations!
Would you mind elaborating the current issue? What are you doing step-by-step? What is expected result? What is actual result?
0 -
Hi Andrey
Developing on Windows 10, deploying to Nx Server on Windows 11
Metadata SDK 5.0.0.35745
Just one setting for now in the settings model, a spin box.
The object of this test plugin, for the end user to set a delay in seconds between events.
Each instance of the DeviceAgent can have separate timings.
PluginDiagnosticEvent is displayed every x seconds for first camera and y seconds for second camera.
The event notice displayed shows the name of the camera displaying the event.
Cannot get the plugin to display the notice.
Archive files here
https://www.dropbox.com/scl/fo/bje3iiqcopyrw0p8oaqcd/h?dl=0&rlkey=eqpxj65cjvplmqdgv8lp0u692
0 -
Hello Graham,
I got you code. Will get back later on.
0 -
Many thanks for your help, Andrey. It's frustrating that what should be a very simple test plugin is proving so tricky. Clearly a trick is being missed.
0 -
Hello Graham,
The plugin built right away from the code you've shared without modification makes the Nx Desktop to hang.
The trick is, that the code of DeviceAgent::eventThreadLoop()
static const seconds kEventGenerationPeriod{ selectedDelayInSeconds };
m_eventThreadCondition.wait_for(lock, kEventGenerationPeriod);does not initialize the kEventGenerationPeriod varibale with the value stored in selectedDelayInSeconds, just because the variable is declared static. The correct code would be
const seconds kEventGenerationPeriod{ selectedDelayInSeconds };That worked for me.

0 -
In order to display Events in the notification tab in the right-hand panel, you need to define a camera rule.
0 -
Doh. Schoolboy error on my part.
Thanks Andrey. Case closed.
0
Please sign in to leave a comment.
Comments
9 comments