335 lines
10 KiB
Markdown
335 lines
10 KiB
Markdown
# go-onvif Architecture & Design
|
|
|
|
## Overview
|
|
|
|
go-onvif 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
|
|
|
|
### 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 (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
|
|
|
|
```go
|
|
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:
|
|
|
|
```go
|
|
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 `ONVIFError` for SOAP faults
|
|
- Wrapped errors with context
|
|
|
|
```go
|
|
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:
|
|
|
|
1. Generate random nonce (16 bytes)
|
|
2. Get current UTC timestamp
|
|
3. Calculate digest: `Base64(SHA1(nonce + created + password))`
|
|
4. Include in SOAP header
|
|
|
|
```xml
|
|
<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:
|
|
|
|
1. Send multicast probe to `239.255.255.250:3702`
|
|
2. Listen for probe matches
|
|
3. Parse device information from responses
|
|
4. Extract service endpoints (XAddrs)
|
|
5. 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
|
|
```go
|
|
// 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
|
|
```go
|
|
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
|
|
```go
|
|
// 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 IDNA
|
|
- `golang.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
|
|
|
|
go-onvif 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)
|