Initial setup for CLion
This commit is contained in:
960
ANSONVIF/ANSONVIF.cpp
Normal file
960
ANSONVIF/ANSONVIF.cpp
Normal file
@@ -0,0 +1,960 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
93
ANSONVIF/ANSONVIF.h
Normal file
93
ANSONVIF/ANSONVIF.h
Normal file
@@ -0,0 +1,93 @@
|
||||
#ifndef ANSONVIF_H
|
||||
#define ANSONVIF_H
|
||||
#define ANSONVIF_API __declspec(dllexport)
|
||||
#include "onvif/onvif.h"
|
||||
#include <iostream>
|
||||
#include "ANSLicense.h"
|
||||
#include "LabVIEWHeader/extcode.h"
|
||||
#include <vector>
|
||||
#include <mutex>
|
||||
#include <cstdint>
|
||||
namespace ANSCENTER
|
||||
{
|
||||
typedef struct
|
||||
{
|
||||
std::string deviceIP;
|
||||
std::string deviceProfileName;
|
||||
std::string deviceProfileURI;
|
||||
} OnvifDeviceProfile;
|
||||
typedef struct
|
||||
{
|
||||
ONVIF_DEVICE onvif_device;
|
||||
int flags; // FLAG_MANUAL mean added manual, other auto discovery device
|
||||
int state; // 0 -- offline; 1 -- online
|
||||
void* p_user; // user data
|
||||
pthread_t thread_handler; // get information thread handler
|
||||
BOOL need_update; // if update device information
|
||||
int snapshot_len; // devcie snapshot buffer length
|
||||
uint8* snapshot; // device snapshot buffer
|
||||
} ONVIF_DEVICE_EX;
|
||||
typedef struct
|
||||
{
|
||||
std::string deviceIP;
|
||||
int devicePort;
|
||||
} OnvifDevice;
|
||||
|
||||
void StateDetectThread(void* argv);
|
||||
|
||||
PPSN_CTX* m_dev_fl = nullptr; // device free list
|
||||
PPSN_CTX* m_dev_ul = nullptr; // device used list
|
||||
BOOL m_bStateDetect = FALSE; // device state detect flag
|
||||
pthread_t m_hStateDetect = 0; // device state detect threand handler
|
||||
|
||||
static std::vector<OnvifDevice> _deviceList;
|
||||
class ANSONVIF_API ANSOnvifClient
|
||||
{
|
||||
private:
|
||||
bool _licenseValid{ false };
|
||||
std::string _licenseKey;
|
||||
std::mutex _mutex;
|
||||
|
||||
private:
|
||||
[[nodiscard]] ONVIF_DEVICE_EX* FindDevice(ONVIF_DEVICE_EX* pdevice);
|
||||
[[nodiscard]] ONVIF_DEVICE_EX* FindDeviceByEndpointReference(char* p_EndpointReference);
|
||||
[[nodiscard]] ONVIF_DEVICE_EX* AddDevice(ONVIF_DEVICE_EX* pdevice);
|
||||
void FreeDevice(ONVIF_DEVICE_EX* p_dev);
|
||||
void GetDevInfo(ONVIF_DEVICE_EX* p_device);
|
||||
//void StartDetectTask();
|
||||
//void StopDetectTask();
|
||||
void ClearDevices();
|
||||
protected:
|
||||
static void ProbeCallback(DEVICE_BINFO* p_res, int msgtype, void* p_data);
|
||||
void CheckLicense();
|
||||
void ErrorHandler(ONVIF_DEVICE* p_device);
|
||||
|
||||
public:
|
||||
[[nodiscard]] bool Init(const std::string& licenseKey);
|
||||
~ANSOnvifClient();
|
||||
ANSOnvifClient();
|
||||
void ClearDeviceList();
|
||||
void Destroy();
|
||||
[[nodiscard]] std::vector<OnvifDevice> SearchForDevices(int sleepDuration);
|
||||
[[nodiscard]] std::vector<OnvifDeviceProfile> SearchForDeviceProfiles(const std::string& username, const std::string& password);
|
||||
[[nodiscard]] std::vector<OnvifDeviceProfile> SearchForDeviceProfiles(const std::vector<std::string>& usernameList, const std::vector<std::string>& passwordList);
|
||||
[[nodiscard]] std::vector<OnvifDeviceProfile> SearchForDeviceProfile(const std::string& ip, int port, const std::string& username, const std::string& password);
|
||||
[[nodiscard]] std::string DeviceListToJsonString(const std::vector<OnvifDevice>& deviceList);
|
||||
[[nodiscard]] std::string DeviceProfileToJsonString(const std::vector<OnvifDeviceProfile>& deviceProfileList);
|
||||
void UpdateDevice(ONVIF_DEVICE_EX* p_device);
|
||||
};
|
||||
}
|
||||
extern "C" __declspec(dllexport) int CreateANSOnvifHandle(ANSCENTER::ANSOnvifClient * *Handle, const char* licenseKey);
|
||||
extern "C" __declspec(dllexport) int SearchANSOnvifDevices(ANSCENTER::ANSOnvifClient * *Handle, int sleepDuration, std::vector<std::string> &deviceList);
|
||||
extern "C" __declspec(dllexport) int SearchANSOnvifProfiles(ANSCENTER::ANSOnvifClient * *Handle, const char* username, const char* password, std::vector<std::string> &profileList);
|
||||
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);
|
||||
extern "C" __declspec(dllexport) int SearchANSOnvifDevices_LV(ANSCENTER::ANSOnvifClient * *Handle, int sleepDuration, LStrHandle deviceList);
|
||||
extern "C" __declspec(dllexport) int SearchANSOnvifProfiles_LV(ANSCENTER::ANSOnvifClient * *Handle, const char* username, const char* password, LStrHandle profileList);
|
||||
extern "C" __declspec(dllexport) int SearchANSOnvifSpecificProfiles_LV(ANSCENTER::ANSOnvifClient * *Handle, const char* ip, int port, const char* username, const char* password, LStrHandle profileList);
|
||||
extern "C" __declspec(dllexport) int ReleaseANSOnvifHandle(ANSCENTER::ANSOnvifClient * *Handle);
|
||||
|
||||
// V2 entry points — accept handle by value (uint64_t) to fix LabVIEW buffer-reuse bug
|
||||
extern "C" __declspec(dllexport) int SearchANSOnvifDevices_LV_V2(uint64_t handleVal, int sleepDuration, LStrHandle deviceList);
|
||||
extern "C" __declspec(dllexport) int SearchANSOnvifProfiles_LV_V2(uint64_t handleVal, const char* username, const char* password, LStrHandle profileList);
|
||||
extern "C" __declspec(dllexport) int SearchANSOnvifSpecificProfiles_LV_V2(uint64_t handleVal, const char* ip, int port, const char* username, const char* password, LStrHandle profileList);
|
||||
#endif
|
||||
31
ANSONVIF/CMakeLists.txt
Normal file
31
ANSONVIF/CMakeLists.txt
Normal file
@@ -0,0 +1,31 @@
|
||||
# ANSONVIF — ONVIF Camera Protocol DLL
|
||||
add_library(ANSONVIF SHARED
|
||||
ANSONVIF.cpp
|
||||
ANSONVIF.h
|
||||
dllmain.cpp
|
||||
pch.cpp
|
||||
pch.h
|
||||
framework.h
|
||||
)
|
||||
|
||||
target_include_directories(ANSONVIF PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}
|
||||
${SHARED_INCLUDE_DIR}
|
||||
)
|
||||
|
||||
target_include_directories(ANSONVIF PRIVATE
|
||||
${ANLS_ROOT}/ONVIF/include
|
||||
${ANLS_ROOT}/ONVIF/include/bm
|
||||
)
|
||||
|
||||
target_link_directories(ANSONVIF PRIVATE ${ANLS_ROOT}/ONVIF/lib)
|
||||
|
||||
target_link_libraries(ANSONVIF
|
||||
PRIVATE ANSLicensingSystem
|
||||
PRIVATE anslicensing
|
||||
PRIVATE labview
|
||||
PRIVATE OnvifClientLibrary.lib
|
||||
)
|
||||
|
||||
target_compile_definitions(ANSONVIF PRIVATE UNICODE _UNICODE ANSONVIF_EXPORTS _USRDLL)
|
||||
target_precompile_headers(ANSONVIF PRIVATE pch.h)
|
||||
19
ANSONVIF/dllmain.cpp
Normal file
19
ANSONVIF/dllmain.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
// dllmain.cpp : Defines the entry point for the DLL application.
|
||||
#include "pch.h"
|
||||
|
||||
BOOL APIENTRY DllMain( HMODULE hModule,
|
||||
DWORD ul_reason_for_call,
|
||||
LPVOID lpReserved
|
||||
)
|
||||
{
|
||||
switch (ul_reason_for_call)
|
||||
{
|
||||
case DLL_PROCESS_ATTACH:
|
||||
case DLL_THREAD_ATTACH:
|
||||
case DLL_THREAD_DETACH:
|
||||
case DLL_PROCESS_DETACH:
|
||||
break;
|
||||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
5
ANSONVIF/framework.h
Normal file
5
ANSONVIF/framework.h
Normal file
@@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
#define NOMINMAX // Prevent windows.h from defining min/max macros
|
||||
// which break std::min / std::max (C2589)
|
||||
#include <windows.h>
|
||||
5
ANSONVIF/pch.cpp
Normal file
5
ANSONVIF/pch.cpp
Normal file
@@ -0,0 +1,5 @@
|
||||
// pch.cpp: source file corresponding to the pre-compiled header
|
||||
|
||||
#include "pch.h"
|
||||
|
||||
// When you are using pre-compiled headers, this source file is necessary for compilation to succeed.
|
||||
13
ANSONVIF/pch.h
Normal file
13
ANSONVIF/pch.h
Normal file
@@ -0,0 +1,13 @@
|
||||
// pch.h: This is a precompiled header file.
|
||||
// Files listed below are compiled only once, improving build performance for future builds.
|
||||
// This also affects IntelliSense performance, including code completion and many code browsing features.
|
||||
// However, files listed here are ALL re-compiled if any one of them is updated between builds.
|
||||
// Do not add files here that you will be updating frequently as this negates the performance advantage.
|
||||
|
||||
#ifndef PCH_H
|
||||
#define PCH_H
|
||||
|
||||
// add headers that you want to pre-compile here
|
||||
#include "framework.h"
|
||||
|
||||
#endif //PCH_H
|
||||
Reference in New Issue
Block a user