- CONTRIBUTING.md: Updated title and git clone URL - .github/CONTRIBUTING.md: Updated title, paths, and references - QUICKSTART.md: Updated intro - BUILDING.md: Updated title - docs/ARCHITECTURE.md: Updated title and descriptions - docs/PROJECT_SUMMARY.md: Updated title, description, and structure - docs/IMPLEMENTATION_SUMMARY.md: Updated docker example - server/README.md: Updated cd command and link text - cmd/onvif-diagnostics/README.md: Updated cd command Note: Kept 'go-onvif' as manufacturer identifier in code (server/types.go, cmd/onvif-server/main.go) and in code comments (examples/) for descriptive purposes.
11 KiB
onvif-go Architecture & Design
Overview
onvif-go is a modern, performant Go library for communicating with ONVIF-compliant IP cameras and devices. It provides a clean, type-safe API with comprehensive support for device management, media streaming, PTZ control, and imaging settings.
Architecture
Project Structure
The project follows the Standard Go Project Layout for libraries:
onvif-go/
├── *.go # Public API (client.go, device.go, media.go, ptz.go, imaging.go)
├── internal/ # Private implementation details
│ └── soap/ # SOAP client (not exported)
├── discovery/ # Device discovery (public subpackage)
├── server/ # ONVIF server implementation (public subpackage)
├── cmd/ # Command-line tools
├── examples/ # Usage examples
├── docs/ # Documentation
├── testing/ # Testing helpers
└── testdata/ # Test fixtures
Design Rationale:
- Root-level API: Main package at root for clean imports (
github.com/0x524a/onvif-go) - internal/: Private packages not intended for external use (SOAP implementation)
- Subpackages: Additional features like
discovery/andserver/ - cmd/: Executable applications and tools
- examples/: Demonstrate library usage
Core Components
┌─────────────────────────────────────────────────────────────┐
│ Client Layer │
│ - onvif.Client: Main entry point │
│ - Context-aware operations │
│ - Connection pooling │
│ - Credential management │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Service Layer │
│ - Device Service (device.go) │
│ - Media Service (media.go) │
│ - PTZ Service (ptz.go) │
│ - Imaging Service (imaging.go) │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Transport Layer │
│ - SOAP Client (internal/soap/soap.go) │
│ - WS-Security Authentication │
│ - XML Marshaling/Unmarshaling │
└─────────────────────────────────────────────────────────────┘
↓
┌─────────────────────────────────────────────────────────────┐
│ Network Layer │
│ - HTTP Client with connection pooling │
│ - TLS support │
│ - Timeout management │
└─────────────────────────────────────────────────────────────┘
Discovery Component
┌─────────────────────────────────────────────────────────────┐
│ WS-Discovery Service │
│ - Multicast UDP probe │
│ - Device enumeration │
│ - Service endpoint discovery │
└─────────────────────────────────────────────────────────────┘
Key Design Decisions
1. Context-First Design
All network operations accept context.Context as the first parameter, enabling:
- Request cancellation
- Timeout control
- Request tracing
- Graceful shutdown
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
info, err := client.GetDeviceInformation(ctx)
2. Functional Options Pattern
Client configuration uses functional options for flexibility:
client, err := onvif.NewClient(
endpoint,
onvif.WithCredentials(username, password),
onvif.WithTimeout(30*time.Second),
onvif.WithHTTPClient(customClient),
)
3. Type Safety
Strong typing throughout the API with comprehensive struct definitions:
- Clear data structures for all ONVIF types
- Type-safe service methods
- Compile-time error detection
4. Error Handling
Multiple error handling strategies:
- Sentinel errors for common cases (
ErrServiceNotSupported,ErrAuthenticationFailed) - Typed
ONVIFErrorfor SOAP faults - Wrapped errors with context
if err := client.ContinuousMove(ctx, profileToken, velocity, nil); err != nil {
if errors.Is(err, onvif.ErrServiceNotSupported) {
// Handle missing PTZ support
} else if onvif.IsONVIFError(err) {
// Handle SOAP fault
}
}
5. Concurrency Safety
Thread-safe operations with proper locking:
- Mutex-protected credential management
- Safe concurrent API calls
- Connection pool management
6. Performance Optimization
Multiple performance optimizations:
- HTTP connection pooling
- Reusable HTTP client
- Efficient XML marshaling
- Minimal allocations in hot paths
Service Implementations
Device Service
Provides device management functionality:
- Device information retrieval
- Capability discovery
- System operations (reboot, date/time)
- Service endpoint enumeration
Media Service
Handles media profiles and streaming:
- Profile management
- Stream URI generation (RTSP/HTTP)
- Snapshot URI retrieval
- Encoder configuration
PTZ Service
Controls pan-tilt-zoom operations:
- Continuous movement
- Absolute positioning
- Relative positioning
- Preset management
- Status monitoring
Imaging Service
Manages image settings:
- Brightness, contrast, saturation
- Exposure control
- Focus management
- White balance
- Wide dynamic range (WDR)
Security
WS-Security Implementation
Authentication uses WS-Security UsernameToken with password digest:
- Generate random nonce (16 bytes)
- Get current UTC timestamp
- Calculate digest:
Base64(SHA1(nonce + created + password)) - Include in SOAP header
<Security>
<UsernameToken>
<Username>admin</Username>
<Password Type="...#PasswordDigest">digest</Password>
<Nonce EncodingType="...#Base64Binary">nonce</Nonce>
<Created>2024-01-01T12:00:00Z</Created>
</UsernameToken>
</Security>
Transport Security
- Supports HTTP and HTTPS
- Configurable TLS settings via custom HTTP client
- Certificate validation control
Discovery Protocol
WS-Discovery implementation:
- Send multicast probe to
239.255.255.250:3702 - Listen for probe matches
- Parse device information from responses
- Extract service endpoints (XAddrs)
- Deduplicate devices by endpoint reference
SOAP Message Flow
Client Request
↓
Build SOAP Envelope
↓
Add WS-Security Header (if authenticated)
↓
Marshal to XML
↓
HTTP POST
↓
Receive Response
↓
Parse SOAP Envelope
↓
Check for Fault
↓
Unmarshal Response Data
↓
Return to Caller
Testing Strategy
Unit Tests
- Client initialization and configuration
- Error handling
- Type validation
- Option application
Integration Tests (with mock servers)
- SOAP message formatting
- Response parsing
- Error handling
Real Device Tests
- Full service workflows
- PTZ operations
- Media streaming
- Discovery
Performance Characteristics
Benchmarks (typical)
- Client creation: ~100 µs
- SOAP call: ~10-50 ms (network dependent)
- Discovery: ~1-5 seconds
- Memory usage: ~1-5 MB per client
Scalability
- Supports hundreds of concurrent clients
- Connection pooling reduces overhead
- Minimal memory footprint per device
Future Enhancements
Planned Features
- Event service (event subscription, pull-point)
- Analytics service (rule engine, motion detection)
- Recording service (recording management)
- Replay service (playback control)
- Advanced security (X.509 certificates)
Optimizations
- Response caching for static data
- Batch operations support
- Streaming data handling
- WebSocket support for events
Best Practices
Client Lifecycle
// Create client once
client, err := onvif.NewClient(endpoint, options...)
if err != nil {
return err
}
// Initialize to discover services
if err := client.Initialize(ctx); err != nil {
return err
}
// Reuse client for multiple operations
// ...
// No explicit cleanup needed (HTTP client manages connections)
Error Handling
info, err := client.GetDeviceInformation(ctx)
if err != nil {
// Check for specific errors
if errors.Is(err, context.DeadlineExceeded) {
// Handle timeout
}
return fmt.Errorf("failed to get device info: %w", err)
}
Resource Management
// Use contexts with timeouts
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
// Operations automatically respect context cancellation
result, err := client.Operation(ctx, ...)
Dependencies
Minimal external dependencies:
golang.org/x/net: HTTP/2 support and IDNAgolang.org/x/text: Character encoding- Go standard library: Everything else
Compliance
- ONVIF Core Specification: ✓
- ONVIF Profile S (Streaming): ✓
- ONVIF Profile T (Advanced Streaming): Partial
- ONVIF Profile G (Recording): Planned
- WS-Security: ✓ (UsernameToken)
- WS-Discovery: ✓
Conclusion
onvif-go provides a modern, performant, and easy-to-use Go library for ONVIF camera integration. Its architecture prioritizes:
- Developer experience (simple, intuitive API)
- Type safety (compile-time error detection)
- Performance (connection pooling, efficient operations)
- Reliability (comprehensive error handling)
- Standards compliance (ONVIF specifications)