OnvifClient Plugin¶
Description¶
OnvifClient is a network camera integration plugin that provides ONVIF (Open Network Video Interface Forum) protocol support for CVEDIA-RT. It enables discovery, configuration, and control of ONVIF-compliant IP cameras and network video devices.
This plugin implements the complete ONVIF specification for professional camera integration, providing automatic device discovery, secure authentication, camera control, stream management, and event handling for enterprise-grade surveillance and video management systems.
Key Features¶
- ONVIF Protocol Compliance: Full implementation of ONVIF specification for standardized camera integration
- Automatic Device Discovery: WS-Discovery protocol for automatic detection of ONVIF devices on the network
- Camera Control: Pan, tilt, zoom (PTZ) and other camera control operations
- Stream Management: Video stream configuration, profile management, and URI generation
- Secure Authentication: WS-Security authentication with digest and basic authentication support
- Profile Management: Camera profile configuration, switching, and media stream setup
- Event Handling: ONVIF event subscription, notification processing, and real-time event streams
- REST API Integration: RESTful API interface for external ONVIF operations and management
- Device Information: Comprehensive device information retrieval and management
- Capabilities Discovery: Automatic discovery and reporting of device capabilities
- Network Configuration: Network interface configuration and management
- Time Synchronization: NTP and manual time synchronization with ONVIF devices
Requirements¶
Hardware Requirements¶
- Network Interface: Ethernet or Wi-Fi network connectivity
- ONVIF Devices: ONVIF-compliant IP cameras and network video devices
- Network Infrastructure: Proper network configuration with multicast support for discovery
- Bandwidth: Sufficient network bandwidth for video streams (varies by resolution/bitrate)
Software Dependencies¶
- GSOAP: SOAP protocol implementation library for ONVIF communication
- OpenSSL: Cryptographic library for secure communication and authentication
- libxml2: XML parsing library for SOAP message processing
- Network Libraries: TCP/UDP networking support and socket operations
- JSON Library: JSON processing for REST API and configuration
- UUID Library: UUID generation for device identification
- Threading Library: Multi-threading support for concurrent operations
Network Requirements¶
- Multicast Support: UDP multicast for WS-Discovery (239.255.255.250:3702)
- Port Access: Access to ONVIF device HTTP/HTTPS ports (typically 80, 443, 8080)
- Firewall Configuration: Proper firewall rules for ONVIF communication
- DNS Resolution: DNS resolution for device hostname lookup
Configuration¶
Basic Configuration¶
{
"onvif": {
"discovery": {
"enabled": true,
"timeout": 5000,
"multicast_address": "239.255.255.250",
"multicast_port": 3702
},
"authentication": {
"username": "admin",
"password": "password",
"auth_method": "digest"
},
"connection": {
"timeout": 30000,
"retry_attempts": 3,
"keep_alive": true
}
}
}
Advanced Configuration¶
{
"onvif": {
"discovery": {
"enabled": true,
"timeout": 10000,
"multicast_address": "239.255.255.250",
"multicast_port": 3702,
"probe_interval": 60000,
"device_filters": ["NetworkVideoTransmitter"],
"scope_filters": ["onvif://www.onvif.org/Profile/Streaming"]
},
"authentication": {
"username": "admin",
"password": "secure_password",
"auth_method": "digest",
"token_lifetime": 3600,
"nonce_generation": true
},
"connection": {
"timeout": 30000,
"retry_attempts": 5,
"retry_delay": 1000,
"keep_alive": true,
"ssl_verify": false,
"user_agent": "CVEDIA-RT ONVIF Client"
},
"capabilities": {
"ptz_support": true,
"imaging_support": true,
"events_support": true,
"media_support": true
},
"streaming": {
"preferred_transport": "RTP-Unicast",
"stream_setup_timeout": 10000,
"profile_selection": "auto"
}
}
}
Configuration Schema¶
Parameter | Type | Default | Description |
---|---|---|---|
discovery.enabled |
bool | true | Enable automatic device discovery |
discovery.timeout |
int | 5000 | Discovery timeout in milliseconds |
discovery.multicast_address |
string | "239.255.255.250" | WS-Discovery multicast address |
discovery.multicast_port |
int | 3702 | WS-Discovery multicast port |
discovery.probe_interval |
int | 60000 | Periodic discovery probe interval |
discovery.device_filters |
array | [] | Device type filters for discovery |
discovery.scope_filters |
array | [] | Scope filters for device matching |
authentication.username |
string | "admin" | ONVIF device username |
authentication.password |
string | "" | ONVIF device password |
authentication.auth_method |
string | "digest" | Authentication method ("basic", "digest") |
authentication.token_lifetime |
int | 3600 | Authentication token lifetime (seconds) |
connection.timeout |
int | 30000 | Connection timeout in milliseconds |
connection.retry_attempts |
int | 3 | Number of retry attempts for failed operations |
connection.retry_delay |
int | 1000 | Delay between retry attempts (ms) |
connection.keep_alive |
bool | true | Enable HTTP keep-alive connections |
connection.ssl_verify |
bool | false | Enable SSL certificate verification |
streaming.preferred_transport |
string | "RTP-Unicast" | Preferred transport protocol |
streaming.stream_setup_timeout |
int | 10000 | Stream setup timeout (ms) |
streaming.profile_selection |
string | "auto" | Profile selection mode |
API Reference¶
C++ API (OnvifDeviceImpl)¶
Device Information and Properties¶
class OnvifDeviceImpl : public iface::OnvifDevice {
public:
// Device identification
std::string const& getName() const override;
std::string const& getXaddr() const override;
std::string const& getManufacturer() const override;
std::string const& getModel() const override;
std::string const& getFirmwareVersion() const override;
std::string const& getSerialNumber() const override;
std::string const& getHardwareId() const override;
// Network and scope information
std::string const& getScopes() const override;
std::string const& getTypes() const override;
std::string const& getMetadataVersion() const override;
// UUID and identification
Uuid getUuid() const override;
// Device state
iface::OnvifDeviceState getState() const override;
};
enum class OnvifDeviceState {
Unknown,
Discovered,
Connected,
Authenticated,
Configured,
Error
};
Authentication and Security¶
class OnvifDeviceImpl {
public:
// Credential management
std::string const& getUsername() const override;
std::string const& getPassword() const override;
void setUsername(std::string const& username) override;
void setPassword(std::string const& password) override;
// Device population and initialization
expected<void> populate() override;
expected<void> authenticate();
expected<void> updateCapabilities();
};
Stream Management¶
struct OnvifStream {
std::string token; // Profile token
std::string name; // Profile name
std::string uri; // Stream URI
std::string transport; // Transport protocol
int width; // Video width
int height; // Video height
float framerate; // Frame rate
std::string encoding; // Video encoding
int bitrate; // Bitrate (bps)
};
class OnvifDeviceImpl {
public:
// Stream access
std::map<std::string, iface::OnvifStream> const& getStreams() const override;
expected<std::string> getStreamUri(const std::string& profileToken);
expected<void> configureStream(const std::string& profileToken, const StreamConfig& config);
};
Device Control¶
class OnvifDeviceImpl {
public:
// PTZ control
expected<void> moveAbsolute(float pan, float tilt, float zoom);
expected<void> moveRelative(float pan, float tilt, float zoom);
expected<void> moveContinuous(float panVelocity, float tiltVelocity, float zoomVelocity);
expected<void> stopMovement();
// Preset management
expected<void> setPreset(const std::string& name);
expected<void> gotoPreset(const std::string& token);
expected<std::vector<PresetInfo>> getPresets();
// Imaging control
expected<void> setImagingSettings(const ImagingSettings& settings);
expected<ImagingSettings> getImagingSettings();
};
struct ImagingSettings {
float brightness = 50.0f;
float contrast = 50.0f;
float saturation = 50.0f;
float sharpness = 50.0f;
bool auto_focus = true;
float focus_value = 0.0f;
};
REST API Interface¶
Device Discovery and Management¶
class ONVIFApi {
public:
// Device discovery
expected<std::vector<OnvifDevice>> discoverDevices();
expected<OnvifDevice> getDevice(const std::string& deviceId);
// Camera management
expected<std::vector<OnvifCamera>> getCameras();
expected<OnvifCamera> getCamera(const std::string& cameraId);
expected<void> setCredentials(const std::string& cameraId,
const CredentialRequest& credentials);
// Stream management
expected<std::vector<OnvifStream>> getStreams(const std::string& cameraId);
expected<std::string> getStreamUri(const std::string& cameraId,
const std::string& profileToken);
};
struct OnvifCamera {
std::string id;
std::string name;
std::string manufacturer;
std::string model;
std::string ipAddress;
std::string macAddress;
OnvifDeviceState state;
std::vector<std::string> capabilities;
};
Lua API¶
Device Discovery¶
-- Create ONVIF client
local onvif = api.factory.onvif.create(instance, "onvif_client")
-- Discover ONVIF devices
local devices = onvif:discoverDevices({
timeout = 10000,
device_types = {"NetworkVideoTransmitter"},
scope_match = "onvif://www.onvif.org/Profile/Streaming"
})
for _, device in ipairs(devices) do
print("Discovered device:")
print(" Name:", device.name)
print(" Manufacturer:", device.manufacturer)
print(" Model:", device.model)
print(" IP Address:", device.ip_address)
print(" Capabilities:", table.concat(device.capabilities, ", "))
end
Device Connection and Authentication¶
-- Connect to specific device
local deviceId = "uuid:12345678-1234-1234-1234-123456789012"
local device = onvif:getDevice(deviceId)
if device then
-- Set credentials
device:setCredentials("admin", "password")
-- Populate device information
local success = device:populate()
if success then
print("Device connected successfully")
print("Firmware:", device:getFirmwareVersion())
print("Serial:", device:getSerialNumber())
else
print("Failed to connect to device")
end
end
Stream Management¶
-- Get available streams
local streams = device:getStreams()
for profileToken, stream in pairs(streams) do
print("Stream Profile:", stream.name)
print(" Token:", stream.token)
print(" Resolution:", stream.width .. "x" .. stream.height)
print(" Frame Rate:", stream.framerate .. " fps")
print(" Encoding:", stream.encoding)
print(" URI:", stream.uri)
end
-- Select and configure stream
local mainStream = streams["Profile_1"]
if mainStream then
local streamUri = device:getStreamUri(mainStream.token)
print("Stream URI:", streamUri)
end
Examples¶
Basic ONVIF Device Discovery and Connection¶
#include "onvif_device_impl.h"
#include "ws_discovery_impl.h"
// ONVIF client for device discovery and management
class ONVIFClientManager {
public:
void discoverAndConnect() {
// Initialize WS-Discovery for device discovery
wsDiscovery_ = std::make_unique<WSDiscoveryImpl>();
// Configure discovery parameters
DiscoveryConfig config;
config.timeout = 10000; // 10 second timeout
config.multicastAddress = "239.255.255.250";
config.multicastPort = 3702;
// Discover ONVIF devices
auto devices = wsDiscovery_->discoverDevices(config);
if (!devices) {
LOGE << "Device discovery failed: " << devices.error().message();
return;
}
LOGI << "Discovered " << devices->size() << " ONVIF devices";
// Connect to discovered devices
for (const auto& deviceInfo : devices.value()) {
connectToDevice(deviceInfo);
}
}
void connectToDevice(const WsDiscoveryDevice& deviceInfo) {
// Create ONVIF device instance
auto device = std::make_unique<OnvifDeviceImpl>(deviceInfo);
// Set authentication credentials
device->setUsername("admin");
device->setPassword("password");
// Populate device information and capabilities
auto populateResult = device->populate();
if (!populateResult) {
LOGE << "Failed to populate device " << device->getName()
<< ": " << populateResult.error().message();
return;
}
// Log device information
LOGI << "Connected to device: " << device->getName();
LOGI << " Manufacturer: " << device->getManufacturer();
LOGI << " Model: " << device->getModel();
LOGI << " Firmware: " << device->getFirmwareVersion();
LOGI << " Serial: " << device->getSerialNumber();
// Get and configure streams
configureDeviceStreams(device.get());
// Store device for later use
connectedDevices_[device->getUuid().toString()] = std::move(device);
}
void configureDeviceStreams(OnvifDeviceImpl* device) {
auto streams = device->getStreams();
LOGI << "Available streams for " << device->getName() << ":";
for (const auto& [token, stream] : streams) {
LOGI << " Profile: " << stream.name;
LOGI << " Token: " << stream.token;
LOGI << " Resolution: " << stream.width << "x" << stream.height;
LOGI << " Frame Rate: " << stream.framerate << " fps";
LOGI << " Encoding: " << stream.encoding;
LOGI << " URI: " << stream.uri;
// Configure preferred stream
if (stream.width >= 1920 && stream.height >= 1080) {
// Use high resolution stream
configureHighResolutionStream(device, stream);
}
}
}
private:
std::unique_ptr<WSDiscoveryImpl> wsDiscovery_;
std::map<std::string, std::unique_ptr<OnvifDeviceImpl>> connectedDevices_;
void configureHighResolutionStream(OnvifDeviceImpl* device,
const iface::OnvifStream& stream) {
// Configure stream for optimal quality
StreamConfig config;
config.width = 1920;
config.height = 1080;
config.framerate = 30.0f;
config.bitrate = 4000000; // 4 Mbps
config.encoding = "H264";
auto result = device->configureStream(stream.token, config);
if (result) {
LOGI << "Configured high-resolution stream for " << device->getName();
}
}
};
PTZ Camera Control¶
// PTZ camera control and management
class ONVIFPTZController {
public:
void initializePTZControl(OnvifDeviceImpl* device) {
device_ = device;
// Verify PTZ capabilities
auto caps = device_->getCapabilities();
if (!caps || !caps->get("ptz_support").getBool()) {
LOGE << "Device does not support PTZ control";
return;
}
// Get PTZ presets
loadPresets();
LOGI << "PTZ control initialized for " << device_->getName();
}
void performPTZOperations() {
// Absolute positioning
moveToPosition(0.5f, 0.0f, 0.3f); // Pan=50%, Tilt=0%, Zoom=30%
std::this_thread::sleep_for(std::chrono::seconds(2));
// Relative movement
moveRelative(0.1f, 0.1f, 0.0f); // Small pan and tilt adjustment
std::this_thread::sleep_for(std::chrono::seconds(2));
// Continuous movement
startContinuousMovement(0.2f, 0.0f, 0.0f); // Slow pan right
std::this_thread::sleep_for(std::chrono::seconds(5));
// Stop movement
stopMovement();
// Go to preset position
gotoPreset("Home");
}
void moveToPosition(float pan, float tilt, float zoom) {
auto result = device_->moveAbsolute(pan, tilt, zoom);
if (result) {
LOGI << "PTZ moved to position - Pan: " << pan
<< ", Tilt: " << tilt << ", Zoom: " << zoom;
} else {
LOGE << "PTZ absolute move failed: " << result.error().message();
}
}
void moveRelative(float panDelta, float tiltDelta, float zoomDelta) {
auto result = device_->moveRelative(panDelta, tiltDelta, zoomDelta);
if (result) {
LOGI << "PTZ relative move completed";
}
}
void startContinuousMovement(float panVel, float tiltVel, float zoomVel) {
auto result = device_->moveContinuous(panVel, tiltVel, zoomVel);
if (result) {
LOGI << "PTZ continuous movement started";
}
}
void stopMovement() {
auto result = device_->stopMovement();
if (result) {
LOGI << "PTZ movement stopped";
}
}
void createPreset(const std::string& name) {
auto result = device_->setPreset(name);
if (result) {
LOGI << "Created PTZ preset: " << name;
loadPresets(); // Refresh preset list
}
}
void gotoPreset(const std::string& name) {
// Find preset by name
auto it = std::find_if(presets_.begin(), presets_.end(),
[&name](const PresetInfo& preset) {
return preset.name == name;
});
if (it != presets_.end()) {
auto result = device_->gotoPreset(it->token);
if (result) {
LOGI << "Moved to preset: " << name;
}
} else {
LOGE << "Preset not found: " << name;
}
}
private:
OnvifDeviceImpl* device_ = nullptr;
std::vector<PresetInfo> presets_;
void loadPresets() {
auto presets = device_->getPresets();
if (presets) {
presets_ = presets.value();
LOGI << "Loaded " << presets_.size() << " PTZ presets";
for (const auto& preset : presets_) {
LOGI << " Preset: " << preset.name << " (" << preset.token << ")";
}
}
}
};
Complete ONVIF Integration with Lua Scripting¶
-- Complete ONVIF integration for surveillance system
local onvif = api.factory.onvif.create(instance, "surveillance_onvif")
local video = api.factory.videoreader.create(instance, "onvif_video")
-- ONVIF device management
local devices = {}
local activeStreams = {}
-- Discover and initialize ONVIF devices
function initializeONVIFSystem()
print("Initializing ONVIF surveillance system")
-- Configure discovery parameters
local discoveryConfig = {
timeout = 15000,
probe_interval = 60000,
device_filters = {"NetworkVideoTransmitter"},
scope_filters = {"onvif://www.onvif.org/Profile/Streaming"}
}
-- Discover devices
local discoveredDevices = onvif:discoverDevices(discoveryConfig)
if discoveredDevices and #discoveredDevices > 0 then
print("Discovered " .. #discoveredDevices .. " ONVIF devices")
for _, deviceInfo in ipairs(discoveredDevices) do
connectToONVIFDevice(deviceInfo)
end
else
print("No ONVIF devices discovered")
end
end
-- Connect to individual ONVIF device
function connectToONVIFDevice(deviceInfo)
local device = onvif:createDevice(deviceInfo)
-- Set credentials (could be from configuration)
device:setCredentials("admin", "admin123")
-- Populate device information
local success = device:populate()
if success then
local deviceId = device:getUuid()
devices[deviceId] = device
print("Connected to ONVIF device:", device:getName())
print(" Manufacturer:", device:getManufacturer())
print(" Model:", device:getModel())
print(" IP:", deviceInfo.ip_address)
-- Configure device streams
configureDeviceStreams(device)
-- Setup PTZ control if available
if device:hasPTZSupport() then
setupPTZControl(device)
end
-- Setup event subscription
setupEventSubscription(device)
else
print("Failed to connect to device:", deviceInfo.name or deviceInfo.ip_address)
end
end
-- Configure video streams for device
function configureDeviceStreams(device)
local streams = device:getStreams()
local deviceId = device:getUuid()
print("Configuring streams for device:", device:getName())
-- Find best quality stream
local bestStream = nil
local maxResolution = 0
for profileToken, stream in pairs(streams) do
local resolution = stream.width * stream.height
print(" Stream: " .. stream.name .. " (" .. stream.width .. "x" .. stream.height .. " @ " .. stream.framerate .. "fps, " .. stream.encoding .. ")")
if resolution > maxResolution then
maxResolution = resolution
bestStream = stream
end
end
-- Configure video reader for best stream
if bestStream then
local streamUri = device:getStreamUri(bestStream.token)
if streamUri then
-- Configure video reader
local videoConfig = {
uri = streamUri,
transport = "tcp",
timeout = 30000,
reconnect = true,
buffer_size = "1MB"
}
local videoReader = api.factory.videoreader.create(
instance, "onvif_stream_" .. deviceId
)
videoReader:configure(videoConfig)
videoReader:openUri(streamUri)
activeStreams[deviceId] = {
device = device,
stream = bestStream,
reader = videoReader,
uri = streamUri
}
print("Configured video stream:", streamUri)
end
end
end
-- Setup PTZ control for camera
function setupPTZControl(device)
local deviceId = device:getUuid()
-- Load presets
local presets = device:getPresets()
if presets and #presets > 0 then
print("PTZ presets for", device:getName() .. ":")
for _, preset in ipairs(presets) do
print(" Preset:", preset.name, "(", preset.token, ")")
end
end
-- Create PTZ control interface
-- Implement PTZ patrol in your main processing loop
-- Use frame counters or time checks for periodic patrol
-- Example: Store last patrol time and check elapsed
end
-- Perform PTZ patrol sequence
function performPTZPatrol(device)
local presets = device:getPresets()
if presets and #presets > 1 then
-- Cycle through presets
local currentTime = api.system.getCurrentTime()
local presetIndex = (math.floor(currentTime / 30) % #presets) + 1
local preset = presets[presetIndex]
device:gotoPreset(preset.token)
print("PTZ patrol - moved to preset:", preset.name)
end
end
-- Setup event subscription
function setupEventSubscription(device)
local deviceId = device:getUuid()
-- Subscribe to motion detection events
device:subscribeToEvents({
"tns1:VideoSource/MotionAlarm",
"tns1:Device/Trigger/DigitalInput"
}, function(event)
handleONVIFEvent(deviceId, event)
end)
print("Event subscription configured for:", device:getName())
end
-- Handle ONVIF events
function handleONVIFEvent(deviceId, event)
local device = devices[deviceId]
print("ONVIF Event [" .. device:getName() .. "]: " .. event.type .. " at " .. event.timestamp)
-- Process specific event types
if event.type == "MotionAlarm" then
handleMotionDetection(deviceId, event)
elseif event.type == "DigitalInput" then
handleDigitalInput(deviceId, event)
end
end
-- Handle motion detection events
function handleMotionDetection(deviceId, event)
local streamInfo = activeStreams[deviceId]
if streamInfo then
-- Move PTZ to motion area if available
if event.region and streamInfo.device:hasPTZSupport() then
local pan = event.region.center_x - 0.5 -- Convert to PTZ coordinates
local tilt = 0.5 - event.region.center_y
streamInfo.device:moveAbsolute(pan, tilt, 0.0)
print("PTZ moved to motion region")
end
-- Trigger recording or alerting
triggerMotionAlert(deviceId, event)
end
end
-- System monitoring and health check
function monitorONVIFSystem()
-- Implement periodic health checks in main loop
-- Use os.time() to track last check time
local function performHealthCheck()
for deviceId, streamInfo in pairs(activeStreams) do
local device = streamInfo.device
-- Check device connectivity
local state = device:getState()
if state ~= "Connected" then
print("Device disconnected:", device:getName())
-- Attempt reconnection
reconnectDevice(deviceId)
end
-- Check stream health
local reader = streamInfo.reader
if reader and not reader:isConnected() then
print("Stream disconnected for:", device:getName())
-- Attempt stream reconnection
reader:openUri(streamInfo.uri)
end
end
end)
end
-- Initialize the system
initializeONVIFSystem()
monitorONVIFSystem()
print("ONVIF surveillance system initialized")
Best Practices¶
Network Configuration¶
- Multicast Support: Ensure network infrastructure supports UDP multicast for device discovery
- Firewall Rules: Configure appropriate firewall rules for ONVIF communication ports
- Network Segmentation: Use dedicated VLAN for IP cameras when possible
- Bandwidth Management: Monitor and manage network bandwidth for video streams
Security Considerations¶
- Authentication: Always use strong passwords and digest authentication
- SSL/TLS: Enable HTTPS when supported by devices
- Network Security: Secure camera network with appropriate access controls
- Credential Management: Store credentials securely and rotate regularly
Performance Optimization¶
- Connection Pooling: Reuse SOAP connections when possible
- Timeout Configuration: Set appropriate timeouts for network operations
- Stream Selection: Choose optimal stream profiles based on requirements
- Event Filtering: Filter events to reduce processing overhead
Integration Guidelines¶
- Device Compatibility: Test with specific camera models for compatibility
- Profile Support: Verify ONVIF profile support (Profile S, Profile T, etc.)
- Capability Discovery: Use capability discovery to determine available features
- Error Handling: Implement robust error handling for network failures
Troubleshooting¶
Common Issues¶
Discovery Problems¶
// Check multicast connectivity
if (!checkMulticastSupport()) {
LOGE << "Multicast not supported. Check network configuration.";
// Try unicast discovery as fallback
performUnicastDiscovery();
}
// Verify network interface
if (!checkNetworkInterface()) {
LOGE << "Network interface not available for discovery.";
return;
}
Authentication Failures¶
- Wrong Credentials: Verify username and password
- Authentication Method: Try different authentication methods (basic vs. digest)
- Time Synchronization: Ensure device and client clocks are synchronized
- Nonce Issues: Check nonce generation and validation
Stream Connection Issues¶
- Network Connectivity: Verify network path to device
- Stream URI: Validate stream URI format and accessibility
- Transport Protocol: Try different transport protocols (TCP, UDP, HTTP)
- Codec Support: Ensure codec compatibility
PTZ Control Problems¶
- Capability Check: Verify PTZ capabilities are supported
- Coordinate System: Check PTZ coordinate system and ranges
- Speed Limits: Respect device-specific speed and position limits
Debugging Tools¶
// ONVIF diagnostics
void diagnoseONVIFConnectivity(OnvifDeviceImpl* device) {
// Test basic connectivity
if (!testHTTPConnectivity(device->getXaddr())) {
LOGE << "HTTP connectivity failed to " << device->getXaddr();
}
// Test SOAP communication
if (!testSOAPCommunication(device)) {
LOGE << "SOAP communication failed";
}
// Verify capabilities
auto caps = device->getCapabilities();
if (caps) {
LOGI << "Device Capabilities:";
for (const auto& [key, value] : caps->getMap()) {
LOGI << " " << key << ": " << value.toString();
}
}
}
Integration Examples¶
Enterprise Video Management System¶
// Complete ONVIF-based video management system
class ONVIFVideoManagementSystem {
public:
void initialize() {
// Initialize discovery and device management
initializeDiscovery();
// Setup device monitoring
startDeviceMonitoring();
// Initialize stream management
initializeStreamManager();
// Setup event processing
initializeEventProcessor();
}
void processVideoFeeds() {
for (auto& [deviceId, deviceInfo] : managedDevices_) {
if (deviceInfo.streamReader && deviceInfo.streamReader->isConnected()) {
auto frame = deviceInfo.streamReader->readFrame();
if (frame) {
processFrameWithAI(deviceId, frame.value());
}
}
}
}
private:
struct ManagedDevice {
std::unique_ptr<OnvifDeviceImpl> device;
std::unique_ptr<VideoReader> streamReader;
std::string streamUri;
OnvifDeviceState lastState;
std::chrono::steady_clock::time_point lastHealthCheck;
};
std::map<std::string, ManagedDevice> managedDevices_;
std::unique_ptr<WSDiscoveryImpl> discovery_;
void initializeDiscovery() {
discovery_ = std::make_unique<WSDiscoveryImpl>();
// Periodic discovery
discoveryTimer_ = std::make_unique<Timer>([this]() {
performPeriodicDiscovery();
}, std::chrono::minutes(5));
}
void processFrameWithAI(const std::string& deviceId, const VideoFrame& frame) {
// AI processing integration
auto detections = aiProcessor_->processFrame(frame);
// Event generation based on detections
if (!detections.empty()) {
generateSmartEvents(deviceId, detections);
}
}
};
See Also¶
- VideoReader Plugin - Video input integration with ONVIF streams
- Platform Plugins Overview - All platform-specific plugins
- Plugin Overview - Complete plugin ecosystem
- Input Plugins - Video input plugin alternatives
- Network Integration Guide - Network camera integration patterns