960 lines
36 KiB
C++
960 lines
36 KiB
C++
|
|
#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;
|
||
|
|
}
|
||
|
|
}
|