Files
ANSCORE/integrations/ANSONVIF/ANSONVIF.cpp

960 lines
36 KiB
C++
Raw Normal View History

2026-03-28 16:54:11 +11:00
#include "ANSONVIF.h"
#include <cstdint>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>
#include "bm\sys_inc.h"
#include "bm\linked_list.h"
#include "http\http.h"
#include "http\http_parse.h"
#include "onvif\onvif_probe.h"
#include "onvif\onvif_event.h"
#include "onvif\onvif_api.h"
#include <unordered_map>
#include <condition_variable>
#include <mutex>
// Handle registry with refcount — prevents use-after-free when
// ReleaseANSOnvifHandle is called while an operation is still running.
static std::unordered_map<ANSCENTER::ANSOnvifClient*, int>& OnvifHandleRegistry() {
static std::unordered_map<ANSCENTER::ANSOnvifClient*, int> s;
return s;
}
static std::mutex& OnvifHandleRegistryMutex() {
static std::mutex m;
return m;
}
static std::condition_variable& OnvifHandleRegistryCV() {
static std::condition_variable cv;
return cv;
}
static void RegisterOnvifHandle(ANSCENTER::ANSOnvifClient* h) {
std::lock_guard<std::mutex> lk(OnvifHandleRegistryMutex());
OnvifHandleRegistry()[h] = 1;
}
static ANSCENTER::ANSOnvifClient* AcquireOnvifHandle(ANSCENTER::ANSOnvifClient* h) {
std::lock_guard<std::mutex> lk(OnvifHandleRegistryMutex());
auto it = OnvifHandleRegistry().find(h);
if (it == OnvifHandleRegistry().end()) return nullptr;
it->second++;
return h;
}
static bool ReleaseOnvifHandleRef(ANSCENTER::ANSOnvifClient* h) {
std::lock_guard<std::mutex> lk(OnvifHandleRegistryMutex());
auto it = OnvifHandleRegistry().find(h);
if (it == OnvifHandleRegistry().end()) return false;
it->second--;
if (it->second <= 0) {
OnvifHandleRegistry().erase(it);
OnvifHandleRegistryCV().notify_all();
return true;
}
return false;
}
static bool UnregisterOnvifHandle(ANSCENTER::ANSOnvifClient* h) {
std::unique_lock<std::mutex> lk(OnvifHandleRegistryMutex());
auto it = OnvifHandleRegistry().find(h);
if (it == OnvifHandleRegistry().end()) return false;
it->second--;
bool ok = OnvifHandleRegistryCV().wait_for(lk, std::chrono::seconds(30), [&]() {
auto it2 = OnvifHandleRegistry().find(h);
return it2 == OnvifHandleRegistry().end() || it2->second <= 0;
});
if (!ok) {
OutputDebugStringA("WARNING: UnregisterOnvifHandle timed out waiting for in-flight operations\n");
}
OnvifHandleRegistry().erase(h);
return true;
}
// RAII guard — ensures ReleaseOnvifHandleRef is always called
class OnvifHandleGuard {
ANSCENTER::ANSOnvifClient* engine;
public:
explicit OnvifHandleGuard(ANSCENTER::ANSOnvifClient* e) : engine(e) {}
~OnvifHandleGuard() { if (engine) ReleaseOnvifHandleRef(engine); }
ANSCENTER::ANSOnvifClient* get() const { return engine; }
explicit operator bool() const { return engine != nullptr; }
OnvifHandleGuard(const OnvifHandleGuard&) = delete;
OnvifHandleGuard& operator=(const OnvifHandleGuard&) = delete;
};
static bool ansonvifLicenceValid = false;
// Global once_flag to protect license checking
static std::once_flag ansonvifLicenseOnceFlag;
namespace ANSCENTER {
static void VerifyGlobalANSONVIFLicense(const std::string& licenseKey) {
try {
std::cout << "ANSOnvifClient::CheckLicense.", "Checking ONVIF license. Please wait....";
ansonvifLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1007, "ANSCV");//
if (!ansonvifLicenceValid)ansonvifLicenceValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(licenseKey, 1003, "ANSVIS");//Default productId=1005
if (!ansonvifLicenceValid) std::cerr << "ANSOnvifClient::CheckLicense.", "Invalid ONVIF license. Please activate correct license.";
else std::cout << "ANSOnvifClient::CheckLicense.", "Valid ONVIF license.";
}
catch (std::exception& e) {
std::cerr << "ANSOnvifClient::CheckLicense()" << e.what();
ansonvifLicenceValid = false;
}
}
//Private methods
void ANSOnvifClient::GetDevInfo(ONVIF_DEVICE_EX* p_device) {
char profileToken[ONVIF_TOKEN_LEN];
ONVIF_PROFILE* p_profile = nullptr;
GetSystemDateAndTime(&p_device->onvif_device);
GetCapabilities(&p_device->onvif_device);
GetServices(&p_device->onvif_device);
GetDeviceInformation(&p_device->onvif_device);
GetVideoSources(&p_device->onvif_device);
GetImagingSettings(&p_device->onvif_device);
GetVideoSourceConfigurations(&p_device->onvif_device);
GetVideoEncoderConfigurations(&p_device->onvif_device);
if (GetAudioSources(&p_device->onvif_device))
{
GetAudioSourceConfigurations(&p_device->onvif_device);
GetAudioEncoderConfigurations(&p_device->onvif_device);
}
if (p_device->onvif_device.Capabilities.ptz.support)
{
GetNodes(&p_device->onvif_device);
GetConfigurations(&p_device->onvif_device);
}
if (p_device->onvif_device.curProfile)
{
strcpy(profileToken, p_device->onvif_device.curProfile->token);
}
else
{
memset(profileToken, 0, sizeof(profileToken));
}
if (profileToken[0] != '\0')
{
p_profile = onvif_find_profile(p_device->onvif_device.profiles, profileToken);
}
if (nullptr ==p_profile)
{
p_profile = p_device->onvif_device.profiles;
}
p_device->onvif_device.curProfile = p_profile;
if (p_device->onvif_device.curProfile == nullptr)
{
p_device->thread_handler = 0;
return ;
}
if (p_profile)
{
int len;
uint8* p_buff;
if (GetSnapshot(&p_device->onvif_device, p_profile->token, &p_buff, &len))
{
if (p_device->snapshot)
{
FreeBuff(p_device->snapshot);
p_device->snapshot = nullptr;
p_device->snapshot_len = 0;
}
p_device->snapshot = p_buff;
p_device->snapshot_len = len;
}
}
if (p_device->onvif_device.Capabilities.events.support == 1 &&
p_device->onvif_device.events.subscribe == FALSE)
{
Subscribe(&p_device->onvif_device, pps_get_index(m_dev_ul, p_device));
}
}
ONVIF_DEVICE_EX* ANSOnvifClient::FindDevice(ONVIF_DEVICE_EX* pdevice)
{
ONVIF_DEVICE_EX* p_dev = static_cast<ONVIF_DEVICE_EX*>(pps_lookup_start(m_dev_ul));
while (p_dev)
{
if (strcmp(p_dev->onvif_device.binfo.XAddr.host, pdevice->onvif_device.binfo.XAddr.host) == 0 &&
p_dev->onvif_device.binfo.XAddr.port == pdevice->onvif_device.binfo.XAddr.port)
{
break;
}
p_dev = static_cast<ONVIF_DEVICE_EX*>(pps_lookup_next(m_dev_ul, p_dev));
}
pps_lookup_end(m_dev_ul);
return p_dev;
}
ONVIF_DEVICE_EX* ANSOnvifClient::FindDeviceByEndpointReference(char* p_EndpointReference)
{
ONVIF_DEVICE_EX* p_dev = static_cast<ONVIF_DEVICE_EX*>(pps_lookup_start(m_dev_ul));
while (p_dev)
{
if (strcmp(p_dev->onvif_device.binfo.EndpointReference, p_EndpointReference) == 0)
{
break;
}
p_dev = static_cast<ONVIF_DEVICE_EX*>(pps_lookup_next(m_dev_ul, p_dev));
}
pps_lookup_end(m_dev_ul);
return p_dev;
}
ONVIF_DEVICE_EX* ANSOnvifClient::AddDevice(ONVIF_DEVICE_EX* pdevice)
{
ONVIF_DEVICE_EX* p_dev = static_cast<ONVIF_DEVICE_EX*>(pps_fl_pop(m_dev_fl));
if (p_dev)
{
memcpy(p_dev, pdevice, sizeof(ONVIF_DEVICE_EX));
p_dev->p_user = 0;
p_dev->onvif_device.events.init_term_time = 60;
onvif_SetAuthInfo(&p_dev->onvif_device, "admin", "admin");
onvif_SetAuthMethod(&p_dev->onvif_device, AuthMethod_UsernameToken);
onvif_SetReqTimeout(&p_dev->onvif_device, 10000);
pps_ctx_ul_add(m_dev_ul, p_dev);
}
return p_dev;
}
void ANSOnvifClient::UpdateDevice(ONVIF_DEVICE_EX* p_device)
{
if (nullptr ==p_device)
{
return;
}
if (p_device->thread_handler)
{
return;
}
BOOL need_update = FALSE;
if (p_device->need_update)
{
need_update = TRUE;
}
if (!p_device->onvif_device.authFailed)
{
if (nullptr ==p_device->onvif_device.curProfile)
{
need_update = TRUE;
}
else if (p_device->onvif_device.curProfile->stream_uri[0] == '\0')
{
need_update = TRUE;
}
}
if (need_update)
{
p_device->need_update = 0;
GetDevInfo(p_device);
}
}
void ANSOnvifClient::FreeDevice(ONVIF_DEVICE_EX* p_dev)
{
if (nullptr ==p_dev)
{
return;
}
while (p_dev->thread_handler)
{
usleep(1000);
}
onvif_free_device(&p_dev->onvif_device);
if (p_dev->snapshot)
{
FreeBuff(p_dev->snapshot);
p_dev->snapshot = nullptr;
p_dev->snapshot_len = 0;
}
}
void ANSOnvifClient::ClearDevices()
{
if (m_dev_ul != nullptr) {
ONVIF_DEVICE_EX* next_dev;
ONVIF_DEVICE_EX* dev = static_cast<ONVIF_DEVICE_EX*>(pps_lookup_start(m_dev_ul));
int max_iterations = 100; // Set a reasonable limit for the maximum number of iterations
int iteration_count = 0;
while (dev && iteration_count < max_iterations)
{
next_dev = static_cast<ONVIF_DEVICE_EX*>(pps_lookup_next(m_dev_ul, dev));
try {
FreeDevice(dev);
}
catch (const std::exception& e) {
// Log the exception or handle it as needed
printf("Exception occurred while freeing device: %s\n", e.what());
}
catch (...) {
// Catch any other types of exceptions
printf("Unknown exception occurred while freeing device.\n");
}
dev = next_dev;
iteration_count++;
}
if (iteration_count >= max_iterations) {
printf("Warning: ClearDevices loop exceeded maximum iterations.\n");
}
pps_lookup_end(m_dev_ul);
}
}
void ANSOnvifClient::ProbeCallback(DEVICE_BINFO* p_res, int msgtype, void* p_data)
{
ONVIF_DEVICE_EX device;
memset(&device, 0, sizeof(ONVIF_DEVICE_EX));
if (msgtype == PROBE_MSGTYPE_MATCH || msgtype == PROBE_MSGTYPE_HELLO)
{
memcpy(&device.onvif_device.binfo, p_res, sizeof(DEVICE_BINFO));
device.state = 1;
std::string deviceURL = p_res->XAddr.url;
if (deviceURL.find("/onvif/device_service") != std::string::npos) {
OnvifDevice foundOnvifDevice;
foundOnvifDevice.deviceIP = p_res->XAddr.host;
foundOnvifDevice.devicePort = p_res->XAddr.port;
// Check if the device is already in the list
auto it = std::find_if(_deviceList.begin(), _deviceList.end(), [&foundOnvifDevice](const OnvifDevice& d) {
return d.deviceIP == foundOnvifDevice.deviceIP && d.devicePort == foundOnvifDevice.devicePort;
});
// If the device is not found, add it to the list
if (it == _deviceList.end()) {
printf("Found device. Ip : %s, port : %d\n", p_res->XAddr.host, p_res->XAddr.port);
_deviceList.push_back(foundOnvifDevice);
}
}
}
else if (msgtype == PROBE_MSGTYPE_BYE)
{
printf("Exit onvif probe");
}
}
void ANSOnvifClient::ErrorHandler(ONVIF_DEVICE* p_device)
{
if (p_device->authFailed) // Authentication failed
{
std::cerr<<"ANSOnvifClient::ErrorHandler", "Authentication failed";
}
switch (p_device->errCode)
{
case ONVIF_ERR_ConnFailure: // Connection failed
std::cerr << "ANSOnvifClient::ErrorHandler", "Connect failed";
break;
case ONVIF_ERR_MallocFailure: // Failed to allocate memory
std::cerr << "ANSOnvifClient::ErrorHandler", "Memory malloc failed";
break;
case ONVIF_ERR_NotSupportHttps: // The device requires an HTTPS connection, but the onvif client library does not support it (the HTTPS compilation macro is not enabled)
std::cerr << "ANSOnvifClient::ErrorHandler", "Not support https";
break;
case ONVIF_ERR_RecvTimeout: // Message receiving timeout
std::cerr << "ANSOnvifClient::ErrorHandler", "Message receive timeout";
break;
case ONVIF_ERR_InvalidContentType: // Device response message content is invalid
std::cerr << "ANSOnvifClient::ErrorHandler", "Invalid content type";
break;
case ONVIF_ERR_NullContent: // Device response message has no content
std::cerr << "ANSOnvifClient::ErrorHandler", "Null content";
break;
case ONVIF_ERR_ParseFailed: // Parsing the message failed
std::cerr << "ANSOnvifClient::ErrorHandler", "Message parse failed";
break;
case ONVIF_ERR_HandleFailed: // Message handling failed
std::cerr << "ANSOnvifClient::ErrorHandler", "Message handle failed";
break;
case ONVIF_ERR_HttpResponseError: // The device responded with an error message
std::cerr << "ANSOnvifClient::ErrorHandler. Code="<< p_device->fault.Code;
std::cerr << "ANSOnvifClient::ErrorHandler. Subcode="<< p_device->fault.Subcode;
std::cerr << "ANSOnvifClient::ErrorHandler. Season="<< p_device->fault.Subcode;
break;
default:
break;
}
}
std::string ANSOnvifClient::DeviceListToJsonString(const std::vector<OnvifDevice>& deviceList) {
boost::property_tree::ptree root;
boost::property_tree::ptree detectedObjects;
for (int i = 0; i < deviceList.size(); i++) {
boost::property_tree::ptree detectedNode;
detectedNode.put("ip", deviceList[i].deviceIP);
detectedNode.put("port", deviceList[i].devicePort);
detectedObjects.push_back(std::make_pair("", detectedNode));
}
root.add_child("results", detectedObjects);
std::ostringstream stream;
boost::property_tree::write_json(stream, root, false);
std::string trackingResult = stream.str();
return trackingResult;
}
std::string ANSOnvifClient::DeviceProfileToJsonString(const std::vector<OnvifDeviceProfile>& deviceProfileList) {
boost::property_tree::ptree root;
boost::property_tree::ptree detectedObjects;
for (int i = 0; i < deviceProfileList.size(); i++) {
boost::property_tree::ptree detectedNode;
detectedNode.put("ip", deviceProfileList[i].deviceIP);
detectedNode.put("name", deviceProfileList[i].deviceProfileName);
detectedNode.put("uri", deviceProfileList[i].deviceProfileURI);
detectedObjects.push_back(std::make_pair("", detectedNode));
}
root.add_child("results", detectedObjects);
std::ostringstream stream;
boost::property_tree::write_json(stream, root, false);
std::string trackingResult = stream.str();
return trackingResult;
}
void ANSOnvifClient::CheckLicense() {
//try {
// std::cout << "ANSOnvifClient::CheckLicense.", "Checking ONVIF license. Please wait....";
// _licenseValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(_licenseKey, 1007, "ANSCV");//
// if(!_licenseValid)_licenseValid = ANSCENTER::ANSLicenseHelper::LicenseVerification(_licenseKey, 1003, "ANSVIS");//Default productId=1005
// if(!_licenseValid) std::cerr << "ANSOnvifClient::CheckLicense.", "Invalid ONVIF license. Please activate correct license.";
// else std::cout << "ANSOnvifClient::CheckLicense.", "Valid ONVIF license.";
//}
//catch (std::exception& e) {
// std::cerr << "ANSOnvifClient::CheckLicense()"<< e.what();
//}
try {
// Check once globally
std::call_once(ansonvifLicenseOnceFlag, [this]() {
VerifyGlobalANSONVIFLicense(_licenseKey);
});
// Update this instance's local license flag
_licenseValid = ansonvifLicenceValid;
}
catch (const std::exception& e) {
std::cerr << "ANSOnvifClient::CheckLicense()"<< e.what();
}
}
bool ANSOnvifClient::Init(const std::string& licenseKey) {
CheckLicense();
if (!_licenseValid) {
std::cerr << "ANSOnvifClient::Init", "Invalid license";
return false;
}
try {
_deviceList.clear();
m_dev_fl = pps_ctx_fl_init(200, sizeof(ONVIF_DEVICE_EX), TRUE);
m_dev_ul = pps_ctx_ul_init(m_dev_fl, TRUE);
network_init();
sys_buf_init(200);
http_msg_buf_init(200);
onvif_event_init(nullptr, 30100, 10);
set_probe_cb(ProbeCallback, 0);
//StartDetectTask();
return true;
}
catch (std::exception& e)
{
std::cerr << "ANSOnvifClient::Init. Error"<< e.what();
return false;
}
catch (...) {
std::cerr << "ANSOnvifClient::Init", "Unknown error";
return false;
}
}
void ANSOnvifClient::Destroy() {
ClearDevices();
onvif_event_deinit();
http_msg_buf_deinit();
sys_buf_deinit();
network_deinit();
if (m_dev_ul != nullptr) pps_ul_free(m_dev_ul);
if (m_dev_fl != nullptr)pps_fl_free(m_dev_fl);
_deviceList.clear();
std::cout << "ANSOnvifClient::Destroy.", "Clean-up ONVIF resource";
}
ANSOnvifClient::~ANSOnvifClient() {
Destroy();
}
std::vector<OnvifDevice>ANSOnvifClient::SearchForDevices(int sleepDuration) {
if (sleepDuration <= 0)sleepDuration = 1;
if (_licenseValid) {
std::lock_guard<std::mutex> lock(_mutex);
start_probe(nullptr, 30);
sleep(sleepDuration);//sleep for 15 seconds
stop_probe();
return _deviceList;
}
else {
std::cerr << "ANSOnvifClient::SearchForDevices.", "Invalid ONVIF license. Please activate correct license.";
return _deviceList;
}
}
std::vector<OnvifDeviceProfile> ANSOnvifClient::SearchForDeviceProfile(const std::string& ip, int port, const std::string& username, const std::string& password) {
std::lock_guard<std::mutex> lock(_mutex);
std::vector<OnvifDeviceProfile> _deviceProfileList;
_deviceProfileList.clear();
if (_licenseValid) {
ONVIF_DEVICE g_device;
memset(&g_device, 0, sizeof(g_device));
g_device.binfo.XAddr.https = 0;
g_device.binfo.XAddr.port = port;
strcpy(g_device.binfo.XAddr.host, ip.c_str());
strcpy(g_device.binfo.XAddr.url, "/onvif/device_service");
onvif_SetAuthInfo(&g_device, username.c_str(), password.c_str());
onvif_SetAuthMethod(&g_device, AuthMethod_UsernameToken);
onvif_SetReqTimeout(&g_device, 5000);
if (!GetSystemDateAndTime(&g_device))
{
ErrorHandler(&g_device);
std::cerr << "ANSOnvifClient::SearchForDeviceProfile. GetSystemDateAndTime failed."<< g_device.binfo.XAddr.host;
}
if (!GetCapabilities(&g_device))
{
ErrorHandler(&g_device);
std::cerr << "ANSOnvifClient::SearchForDeviceProfile. GetCapabilities failed."<< g_device.binfo.XAddr.host;
}
if (!GetServices(&g_device))
{
ErrorHandler(&g_device);
std::cerr << "ANSOnvifClient::SearchForDeviceProfile. GetServices failed."<< g_device.binfo.XAddr.host;
}
if (!GetDeviceInformation(&g_device))
{
ErrorHandler(&g_device);
std::cerr << "ANSOnvifClient::SearchForDeviceProfile. GetDeviceInformation failed." << g_device.binfo.XAddr.host;
}
if (!GetProfiles(&g_device))
{
ErrorHandler(&g_device);
std::cerr << "ANSOnvifClient::SearchForDeviceProfile. GetDeviceInformation failed."<< g_device.binfo.XAddr.host;
}
if (!GetStreamUris(&g_device, onvif_TransportProtocol::TransportProtocol_UDP))
{
ErrorHandler(&g_device);
std::cerr << "ANSOnvifClient::SearchForDeviceProfile. GetDeviceInformation failed."<< g_device.binfo.XAddr.host;
}
ONVIF_PROFILE* p_profile = g_device.profiles;
bool foundProfile = false;
while (p_profile)
{
OnvifDeviceProfile foundOnvifProfile;
foundOnvifProfile.deviceIP = ip;
foundOnvifProfile.deviceProfileName = p_profile->name;
foundOnvifProfile.deviceProfileURI = p_profile->stream_uri;
_deviceProfileList.push_back(foundOnvifProfile);
foundProfile = true;
p_profile = p_profile->next;
}
if (!foundProfile) {
OnvifDeviceProfile foundOnvifProfile;
foundOnvifProfile.deviceIP = g_device.binfo.XAddr.host;
foundOnvifProfile.deviceProfileName = "Error";
foundOnvifProfile.deviceProfileURI = g_device.fault.Reason;
_deviceProfileList.push_back(foundOnvifProfile);
}
onvif_free_device(&g_device);
return _deviceProfileList;
}
else {
std::cerr << "ANSOnvifClient::SearchForDeviceProfile.", "Invalid ONVIF license. Please activate correct license.";
return _deviceProfileList;
}
}
std::vector<OnvifDeviceProfile> ANSOnvifClient::SearchForDeviceProfiles(const std::string& username, const std::string& password) {
std::vector<OnvifDeviceProfile> _deviceProfileList;
_deviceProfileList.clear();
if (_licenseValid) {
SearchForDevices(15);
if (_deviceList.size() <= 0) return _deviceProfileList;
for (int i = 0; i < _deviceList.size(); i++)
{
OnvifDevice currentOnvifDevice = _deviceList.at(i);
std::vector<OnvifDeviceProfile> _currentDeviceProfileList = SearchForDeviceProfile(currentOnvifDevice.deviceIP, currentOnvifDevice.devicePort, username, password);
if (_currentDeviceProfileList.size() > 0) {
for (int j = 0; j < _currentDeviceProfileList.size(); j++) {
_deviceProfileList.push_back(_currentDeviceProfileList.at(j));
}
}
}
return _deviceProfileList;
}
else {
std::cerr << "ANSOnvifClient::SearchForDeviceProfiles.", "Invalid ONVIF license. Please activate correct license.";
return _deviceProfileList;
}
}
std::vector<OnvifDeviceProfile> ANSOnvifClient::SearchForDeviceProfiles(const std::vector<std::string>& usernameList, const std::vector<std::string>& passwordList) {
std::vector<OnvifDeviceProfile> _deviceProfileList;
_deviceProfileList.clear();
if (_licenseValid) {
SearchForDevices(15);
if (_deviceList.size() <= 0) return _deviceProfileList;
if (usernameList.size() <= 0) return _deviceProfileList;
if (usernameList.size() != passwordList.size())return _deviceProfileList;
for (int i = 0; i < _deviceList.size(); i++)
{
OnvifDevice currentOnvifDevice = _deviceList.at(i);
for (int j = 0; j < usernameList.size(); j++)
{
std::vector<OnvifDeviceProfile> _currentDeviceProfileList = SearchForDeviceProfile(currentOnvifDevice.deviceIP, currentOnvifDevice.devicePort, usernameList.at(j).c_str(), passwordList.at(j).c_str());
if (_currentDeviceProfileList.size() > 0) {
for (int k = 0; k < _currentDeviceProfileList.size(); k++) {
_deviceProfileList.push_back(_currentDeviceProfileList.at(k));
}
}
}
}
return _deviceProfileList;
}
else {
std::cerr << "ANSOnvifClient::SearchForDeviceProfiles.", "Invalid ONVIF license. Please activate correct license.";
return _deviceProfileList;
}
}
ANSOnvifClient::ANSOnvifClient() {
_licenseValid = false;
}
void ANSOnvifClient::ClearDeviceList() {
_deviceList.clear();
}
}
extern "C" __declspec(dllexport) int CreateANSOnvifHandle(ANSCENTER::ANSOnvifClient * *Handle, const char* licenseKey) {
if (Handle == nullptr || licenseKey == nullptr) return 0;
try {
// Release existing handle if called twice (prevents leak from LabVIEW)
if (*Handle) {
if (UnregisterOnvifHandle(*Handle)) {
delete *Handle;
}
*Handle = nullptr;
}
*Handle = new ANSCENTER::ANSOnvifClient();
if (*Handle == nullptr) return 0;
if ((*Handle)->Init(licenseKey)) {
RegisterOnvifHandle(*Handle);
return 1;
}
delete *Handle;
*Handle = nullptr;
return 0;
}
catch (std::exception& e) {
if (*Handle != nullptr) { delete *Handle; *Handle = nullptr; }
return 0;
}
catch (...) {
if (*Handle != nullptr) { delete *Handle; *Handle = nullptr; }
return 0;
}
}
static int ReleaseANSOnvifHandle_Impl(ANSCENTER::ANSOnvifClient** Handle) {
try {
if (!Handle || !*Handle) return 1;
if (!UnregisterOnvifHandle(*Handle)) {
*Handle = nullptr;
return 1;
}
delete *Handle;
*Handle = nullptr;
return 1;
}
catch (...) {
if (Handle) *Handle = nullptr;
return 0;
}
}
extern "C" __declspec(dllexport) int ReleaseANSOnvifHandle(ANSCENTER::ANSOnvifClient * *Handle) {
__try {
return ReleaseANSOnvifHandle_Impl(Handle);
}
__except (EXCEPTION_EXECUTE_HANDLER) {
if (Handle) *Handle = nullptr;
return 0;
}
}
extern "C" __declspec(dllexport) int SearchANSOnvifDevices(ANSCENTER::ANSOnvifClient * *Handle, int sleepDuration, std::vector<std::string> &deviceList) {
if (Handle == nullptr || *Handle == nullptr) return 0;
OnvifHandleGuard guard(AcquireOnvifHandle(*Handle));
if (!guard) return 0;
try {
deviceList.clear();
std::vector<ANSCENTER::OnvifDevice> onvifDeviceList = guard.get()->SearchForDevices(sleepDuration);
if (onvifDeviceList.size() <= 0)return 0;
for (int i = 0; i < onvifDeviceList.size(); i++) {
ANSCENTER::OnvifDevice currentDevice = onvifDeviceList.at(i);
std::string currentDeviceStr = currentDevice.deviceIP + ":" + std::to_string(currentDevice.devicePort);
deviceList.push_back(currentDeviceStr);
}
return 1;
}
catch (std::exception& e) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" __declspec(dllexport) int SearchANSOnvifProfiles(ANSCENTER::ANSOnvifClient * *Handle, const char* username, const char* password, std::vector<std::string> &profileList) {
if (Handle == nullptr || *Handle == nullptr || username == nullptr || password == nullptr) return 0;
OnvifHandleGuard guard(AcquireOnvifHandle(*Handle));
if (!guard) return 0;
try {
profileList.clear();
std::vector<ANSCENTER::OnvifDeviceProfile> onvifDeviceProfileList = guard.get()->SearchForDeviceProfiles(username, password);
if (onvifDeviceProfileList.size() <= 0)return 0;
for (int i = 0; i < onvifDeviceProfileList.size(); i++) {
ANSCENTER::OnvifDeviceProfile currentDevice = onvifDeviceProfileList.at(i);
std::string currentDeviceStr = currentDevice.deviceProfileURI;
profileList.push_back(currentDeviceStr);
}
return 1;
}
catch (std::exception& e) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" __declspec(dllexport) int SearchANSOnvifSpecificProfiles(ANSCENTER::ANSOnvifClient * *Handle, const char* ip, int port, const char* username, const char* password, std::vector<std::string> &profileList) {
if (Handle == nullptr || *Handle == nullptr || ip == nullptr || username == nullptr || password == nullptr) return 0;
OnvifHandleGuard guard(AcquireOnvifHandle(*Handle));
if (!guard) return 0;
try {
profileList.clear();
std::vector<ANSCENTER::OnvifDeviceProfile> onvifDeviceProfileList = guard.get()->SearchForDeviceProfile(ip, port, username, password);
if (onvifDeviceProfileList.size() <= 0)return 0;
for (int i = 0; i < onvifDeviceProfileList.size(); i++) {
ANSCENTER::OnvifDeviceProfile currentDevice = onvifDeviceProfileList.at(i);
std::string currentDeviceStr = currentDevice.deviceProfileURI;
profileList.push_back(currentDeviceStr);
}
return 1;
}
catch (std::exception& e) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" __declspec(dllexport) int SearchANSOnvifDevices_LV(ANSCENTER::ANSOnvifClient * *Handle, int sleepDuration,LStrHandle deviceList) {
if (Handle == nullptr || *Handle == nullptr || deviceList == nullptr) return 0;
OnvifHandleGuard guard(AcquireOnvifHandle(*Handle));
if (!guard) return 0;
try {
std::vector<ANSCENTER::OnvifDevice> onvifDeviceList = guard.get()->SearchForDevices(sleepDuration);
std::string st = guard.get()->DeviceListToJsonString(onvifDeviceList);
int size = static_cast<int>(st.length());
if (size > 0) {
MgErr error;
error = DSSetHandleSize(deviceList, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*deviceList)->cnt = size;
memcpy((*deviceList)->str, st.c_str(), size);
return 1;
}
else return 0;
}
else return 0;
}
catch (std::exception& e) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" __declspec(dllexport) int SearchANSOnvifProfiles_LV(ANSCENTER::ANSOnvifClient * *Handle, const char* username, const char* password, LStrHandle profileList) {
if (Handle == nullptr || *Handle == nullptr || username == nullptr || password == nullptr || profileList == nullptr) return 0;
OnvifHandleGuard guard(AcquireOnvifHandle(*Handle));
if (!guard) return 0;
try {
std::vector<ANSCENTER::OnvifDeviceProfile> onvifDeviceProfileList = guard.get()->SearchForDeviceProfiles(username, password);
std::string st = guard.get()->DeviceProfileToJsonString(onvifDeviceProfileList);
int size = static_cast<int>(st.length());
if (size > 0) {
MgErr error;
error = DSSetHandleSize(profileList, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*profileList)->cnt = size;
memcpy((*profileList)->str, st.c_str(), size);
return 1;
}
else return 0;
}
else return 0;
}
catch (std::exception& e) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" __declspec(dllexport) int SearchANSOnvifSpecificProfiles_LV(ANSCENTER::ANSOnvifClient * *Handle, const char* ip, int port, const char* username, const char* password, LStrHandle profileList) {
if (Handle == nullptr || *Handle == nullptr || ip == nullptr || username == nullptr || password == nullptr || profileList == nullptr) return 0;
OnvifHandleGuard guard(AcquireOnvifHandle(*Handle));
if (!guard) return 0;
try {
std::vector<ANSCENTER::OnvifDeviceProfile> onvifDeviceProfileList = guard.get()->SearchForDeviceProfile(ip, port, username, password);
std::string st = guard.get()->DeviceProfileToJsonString(onvifDeviceProfileList);
int size = static_cast<int>(st.length());
if (size > 0) {
MgErr error;
error = DSSetHandleSize(profileList, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*profileList)->cnt = size;
memcpy((*profileList)->str, st.c_str(), size);
return 1;
}
else return 0;
}
else return 0;
}
catch (std::exception& e) {
return 0;
}
catch (...) {
return 0;
}
}
// ============================================================================
// V2 entry points — accept uint64_t handleVal by value instead of Handle**
// to eliminate LabVIEW buffer-reuse bug when concurrent calls share the same
// Handle** buffer address.
// ============================================================================
extern "C" __declspec(dllexport) int SearchANSOnvifDevices_LV_V2(uint64_t handleVal, int sleepDuration, LStrHandle deviceList) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSOnvifClient*>(handleVal);
if (!_v2h) return 0;
if (deviceList == nullptr) return 0;
OnvifHandleGuard guard(AcquireOnvifHandle(_v2h));
if (!guard) return 0;
try {
std::vector<ANSCENTER::OnvifDevice> onvifDeviceList = guard.get()->SearchForDevices(sleepDuration);
std::string st = guard.get()->DeviceListToJsonString(onvifDeviceList);
int size = static_cast<int>(st.length());
if (size > 0) {
MgErr error;
error = DSSetHandleSize(deviceList, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*deviceList)->cnt = size;
memcpy((*deviceList)->str, st.c_str(), size);
return 1;
}
else return 0;
}
else return 0;
}
catch (std::exception& e) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" __declspec(dllexport) int SearchANSOnvifProfiles_LV_V2(uint64_t handleVal, const char* username, const char* password, LStrHandle profileList) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSOnvifClient*>(handleVal);
if (!_v2h) return 0;
if (username == nullptr || password == nullptr || profileList == nullptr) return 0;
OnvifHandleGuard guard(AcquireOnvifHandle(_v2h));
if (!guard) return 0;
try {
std::vector<ANSCENTER::OnvifDeviceProfile> onvifDeviceProfileList = guard.get()->SearchForDeviceProfiles(username, password);
std::string st = guard.get()->DeviceProfileToJsonString(onvifDeviceProfileList);
int size = static_cast<int>(st.length());
if (size > 0) {
MgErr error;
error = DSSetHandleSize(profileList, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*profileList)->cnt = size;
memcpy((*profileList)->str, st.c_str(), size);
return 1;
}
else return 0;
}
else return 0;
}
catch (std::exception& e) {
return 0;
}
catch (...) {
return 0;
}
}
extern "C" __declspec(dllexport) int SearchANSOnvifSpecificProfiles_LV_V2(uint64_t handleVal, const char* ip, int port, const char* username, const char* password, LStrHandle profileList) {
auto* _v2h = reinterpret_cast<ANSCENTER::ANSOnvifClient*>(handleVal);
if (!_v2h) return 0;
if (ip == nullptr || username == nullptr || password == nullptr || profileList == nullptr) return 0;
OnvifHandleGuard guard(AcquireOnvifHandle(_v2h));
if (!guard) return 0;
try {
std::vector<ANSCENTER::OnvifDeviceProfile> onvifDeviceProfileList = guard.get()->SearchForDeviceProfile(ip, port, username, password);
std::string st = guard.get()->DeviceProfileToJsonString(onvifDeviceProfileList);
int size = static_cast<int>(st.length());
if (size > 0) {
MgErr error;
error = DSSetHandleSize(profileList, sizeof(int32) + size * sizeof(uChar));
if (error == noErr)
{
(*profileList)->cnt = size;
memcpy((*profileList)->str, st.c_str(), size);
return 1;
}
else return 0;
}
else return 0;
}
catch (std::exception& e) {
return 0;
}
catch (...) {
return 0;
}
}