# onvif-go - ONVIF Client and Server Library for Go [![Go Reference](https://pkg.go.dev/badge/github.com/0x524a/onvif-go.svg)](https://pkg.go.dev/github.com/0x524a/onvif-go) [![Go Report Card](https://goreportcard.com/badge/github.com/0x524a/onvif-go)](https://goreportcard.com/report/github.com/0x524a/onvif-go) [![License](https://img.shields.io/github/license/0x524a/onvif-go)](LICENSE) [![GitHub stars](https://img.shields.io/github/stars/0x524a/onvif-go)](https://github.com/0x524a/onvif-go/stargazers) [![GitHub issues](https://img.shields.io/github/issues/0x524a/onvif-go)](https://github.com/0x524a/onvif-go/issues) > **Modern, high-performance Go library for ONVIF IP camera integration** - Control surveillance cameras, NVRs, and video devices with comprehensive ONVIF Profile S/T/G support. Includes both client and server implementations for complete ONVIF camera simulation and testing. A production-ready, feature-rich Go (Golang) library for communicating with ONVIF-compliant IP cameras, network video recorders (NVR), and surveillance devices. Perfect for building video management systems (VMS), security camera applications, IoT projects, and camera testing frameworks. ## ๐ŸŽฏ Key Features at a Glance - โœ… **ONVIF Client & Server** - Both client library and virtual camera server - โœ… **Production Ready** - Battle-tested with multiple camera brands - โœ… **Full Protocol Support** - Device, Media, PTZ, Imaging, Discovery services - โœ… **Type Safe** - Comprehensive Go types for all ONVIF operations - โœ… **Well Documented** - Extensive examples and API documentation - โœ… **Camera Tested** - Verified with Hikvision, Axis, Dahua, Bosch cameras - โœ… **Testing Framework** - Built-in mock server and testing utilities ## ๐Ÿ”‘ What is ONVIF? ONVIF (Open Network Video Interface Forum) is an open industry standard for IP-based security products. This library allows you to: - ๐ŸŽฅ Control IP cameras from any manufacturer (Bosch, Hikvision, Axis, Dahua, etc.) - ๐Ÿ“น Get RTSP video streams and snapshots - ๐ŸŽฎ Pan, tilt, and zoom cameras remotely - ๐Ÿ”ง Configure camera settings (exposure, focus, white balance) - ๐Ÿ” Discover cameras on your network automatically - ๐Ÿงช Test ONVIF implementations without physical hardware ## Features ### ๐Ÿ“ก ONVIF Client โœจ **Modern Go Design** - Context support for cancellation and timeouts - Concurrent-safe operations - Type-safe API with comprehensive error handling - Connection pooling for optimal performance ๐ŸŽฅ **Comprehensive ONVIF Support** - **Device Management**: Get device info, capabilities, system date/time, reboot - **Media Services**: Profiles, stream URIs (RTSP/HTTP), snapshot URIs, encoder configuration - **PTZ Control**: Continuous, absolute, and relative movement, presets, status - **Imaging**: Get/set brightness, contrast, exposure, focus, white balance, WDR - **Discovery**: Automatic camera detection via WS-Discovery multicast ### ๐ŸŽฌ ONVIF Server (NEW!) ๐ŸŽฅ **Virtual IP Camera Simulator** - **Multi-Lens Camera Support**: Simulate up to 10 independent camera profiles - **Complete ONVIF Implementation**: Device, Media, PTZ, and Imaging services - **Flexible Configuration**: CLI and library interfaces for easy setup - **PTZ Simulation**: Full pan-tilt-zoom control with preset positions - **Imaging Control**: Brightness, contrast, exposure, focus, and more - **Testing & Development**: Perfect for testing ONVIF clients without physical cameras ๐Ÿ” **Security** - WS-Security with UsernameToken authentication - Password digest (SHA-1) support - Configurable timeout and HTTP client options ๐Ÿ“ฆ **Easy Integration** - Simple, intuitive API - Well-documented with examples - No external dependencies beyond Go standard library and golang.org/x/net ## Installation ```bash go get github.com/0x524a/onvif-go ``` ## Quick Start ### Discover Cameras on Network ```go package main import ( "context" "fmt" "log" "time" "github.com/0x524a/onvif-go/discovery" ) func main() { ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) defer cancel() devices, err := discovery.Discover(ctx, 5*time.Second) if err != nil { log.Fatal(err) } for _, device := range devices { fmt.Printf("Found: %s at %s\n", device.GetName(), device.GetDeviceEndpoint()) } } ``` ### Connect to a Camera ```go package main import ( "context" "fmt" "log" "time" "github.com/0x524a/onvif-go" ) func main() { // Create client - endpoint can be: // - Full URL: "http://192.168.1.100/onvif/device_service" // - IP with port: "192.168.1.100:8080" // - IP only: "192.168.1.100" (automatically adds http:// and path) client, err := onvif.NewClient( "192.168.1.100", // Simple IP address onvif.WithCredentials("admin", "password"), onvif.WithTimeout(30*time.Second), ) if err != nil { log.Fatal(err) } ctx := context.Background() // Get device information info, err := client.GetDeviceInformation(ctx) if err != nil { log.Fatal(err) } fmt.Printf("Camera: %s %s\n", info.Manufacturer, info.Model) fmt.Printf("Firmware: %s\n", info.FirmwareVersion) // Initialize and discover service endpoints if err := client.Initialize(ctx); err != nil { log.Fatal(err) } // Get media profiles profiles, err := client.GetProfiles(ctx) if err != nil { log.Fatal(err) } // Get stream URI if len(profiles) > 0 { streamURI, err := client.GetStreamURI(ctx, profiles[0].Token) if err != nil { log.Fatal(err) } fmt.Printf("Stream URI: %s\n", streamURI.URI) } } ``` ### PTZ Control ```go // Continuous movement velocity := &onvif.PTZSpeed{ PanTilt: &onvif.Vector2D{X: 0.5, Y: 0.0}, // Move right } timeout := "PT2S" // 2 seconds err := client.ContinuousMove(ctx, profileToken, velocity, &timeout) // Stop movement err = client.Stop(ctx, profileToken, true, true) // Absolute positioning position := &onvif.PTZVector{ PanTilt: &onvif.Vector2D{X: 0.0, Y: 0.0}, // Center Zoom: &onvif.Vector1D{X: 0.5}, // 50% zoom } err = client.AbsoluteMove(ctx, profileToken, position, nil) // Go to preset presets, err := client.GetPresets(ctx, profileToken) if len(presets) > 0 { err = client.GotoPreset(ctx, profileToken, presets[0].Token, nil) } ``` ### Imaging Settings ```go // Get current settings settings, err := client.GetImagingSettings(ctx, videoSourceToken) // Modify settings brightness := 60.0 settings.Brightness = &brightness contrast := 55.0 settings.Contrast = &contrast // Apply settings err = client.SetImagingSettings(ctx, videoSourceToken, settings, true) ``` ## API Overview ### Client Creation ```go client, err := onvif.NewClient( endpoint, onvif.WithCredentials(username, password), onvif.WithTimeout(30*time.Second), onvif.WithHTTPClient(customHTTPClient), ) ``` ### Device Service | Method | Description | |--------|-------------| | `GetDeviceInformation()` | Get manufacturer, model, firmware version | | `GetCapabilities()` | Get device capabilities and service endpoints | | `GetSystemDateAndTime()` | Get device system time | | `SystemReboot()` | Reboot the device | | `Initialize()` | Discover and cache service endpoints | | `GetHostname()` | Get device hostname configuration | | `SetHostname()` | Set device hostname | | `GetDNS()` | Get DNS configuration | | `GetNTP()` | Get NTP configuration | | `GetNetworkInterfaces()` | Get network interface configuration | | `GetScopes()` | Get configured discovery scopes | | `GetUsers()` | Get list of user accounts | | `CreateUsers()` | Create new user accounts | | `DeleteUsers()` | Delete user accounts | | `SetUser()` | Modify existing user account | ### Media Service | Method | Description | |--------|-------------| | `GetProfiles()` | Get all media profiles | | `GetStreamURI()` | Get RTSP/HTTP stream URI | | `GetSnapshotURI()` | Get snapshot image URI | | `GetVideoEncoderConfiguration()` | Get video encoder settings | | `GetVideoSources()` | Get all video sources | | `GetAudioSources()` | Get all audio sources | | `GetAudioOutputs()` | Get all audio outputs | | `CreateProfile()` | Create new media profile | | `DeleteProfile()` | Delete media profile | | `SetVideoEncoderConfiguration()` | Set video encoder configuration | ### PTZ Service | Method | Description | |--------|-------------| | `ContinuousMove()` | Start continuous PTZ movement | | `AbsoluteMove()` | Move to absolute position | | `RelativeMove()` | Move relative to current position | | `Stop()` | Stop PTZ movement | | `GetStatus()` | Get current PTZ status and position | | `GetPresets()` | Get list of PTZ presets | | `GotoPreset()` | Move to a preset position | | `SetPreset()` | Save current position as preset | | `RemovePreset()` | Delete a preset | | `GotoHomePosition()` | Move to home position | | `SetHomePosition()` | Set current position as home | | `GetConfiguration()` | Get PTZ configuration | | `GetConfigurations()` | Get all PTZ configurations | ### Imaging Service | Method | Description | |--------|-------------| | `GetImagingSettings()` | Get imaging settings (brightness, contrast, etc.) | | `SetImagingSettings()` | Set imaging settings | | `Move()` | Perform focus move operations | | `GetOptions()` | Get available imaging options and ranges | | `GetMoveOptions()` | Get available focus move options | | `StopFocus()` | Stop focus movement | | `GetImagingStatus()` | Get current imaging/focus status | ### Discovery Service | Method | Description | |--------|-------------| | `Discover()` | Discover ONVIF devices on network | ## ONVIF Server The library now includes a complete ONVIF server implementation that simulates multi-lens IP cameras! ### Quick Start ```bash # Install the server CLI go install ./cmd/onvif-server # Run with default settings (3 camera profiles) onvif-server # Or customize onvif-server -profiles 5 -username admin -password mypass -port 9000 ``` ### Using the Server Library ```go package main import ( "context" "log" "github.com/0x524a/onvif-go/server" ) func main() { // Create server with default multi-lens camera configuration srv, err := server.New(server.DefaultConfig()) if err != nil { log.Fatal(err) } // Start server ctx := context.Background() if err := srv.Start(ctx); err != nil { log.Fatal(err) } } ``` ### Server Features - ๐ŸŽฅ **Multi-Lens Simulation**: Support for up to 10 independent camera profiles - ๐ŸŽฎ **Full PTZ Control**: Pan, tilt, zoom with preset positions - ๐Ÿ“ท **Imaging Settings**: Brightness, contrast, exposure, focus, white balance - ๐ŸŒ **Complete ONVIF Services**: Device, Media, PTZ, and Imaging services - ๐Ÿ” **WS-Security**: Digest authentication support - โš™๏ธ **Flexible Configuration**: CLI and library interfaces ### Use Cases - Testing ONVIF client implementations - Developing video management systems - CI/CD integration testing - Demonstrations without physical cameras - Learning ONVIF protocol For complete documentation, see [server/README.md](server/README.md). ## Examples The [examples](examples/) directory contains complete working examples: ### Client Examples - **[discovery](examples/discovery/)**: Discover cameras on the network - **[device-info](examples/device-info/)**: Get device information and media profiles - **[ptz-control](examples/ptz-control/)**: Control camera PTZ (pan, tilt, zoom) - **[imaging-settings](examples/imaging-settings/)**: Adjust imaging settings ### Server Examples - **[onvif-server](examples/onvif-server/)**: Multi-lens camera server with custom configuration To run an example: ```bash cd examples/discovery go run main.go ``` ## Architecture ``` onvif-go/ โ”œโ”€โ”€ client.go # Main ONVIF client โ”œโ”€โ”€ types.go # ONVIF data types โ”œโ”€โ”€ errors.go # Error definitions โ”œโ”€โ”€ device.go # Device service implementation โ”œโ”€โ”€ media.go # Media service implementation โ”œโ”€โ”€ ptz.go # PTZ service implementation โ”œโ”€โ”€ imaging.go # Imaging service implementation โ”œโ”€โ”€ soap/ # SOAP client with WS-Security โ”‚ โ””โ”€โ”€ soap.go โ”œโ”€โ”€ discovery/ # WS-Discovery implementation โ”‚ โ””โ”€โ”€ discovery.go โ”œโ”€โ”€ server/ # ONVIF server implementation โ”‚ โ”œโ”€โ”€ server.go # Main server โ”‚ โ”œโ”€โ”€ types.go # Server types and configuration โ”‚ โ”œโ”€โ”€ device.go # Device service handlers โ”‚ โ”œโ”€โ”€ media.go # Media service handlers โ”‚ โ”œโ”€โ”€ ptz.go # PTZ service handlers โ”‚ โ”œโ”€โ”€ imaging.go # Imaging service handlers โ”‚ โ””โ”€โ”€ soap/ # SOAP server handler โ”‚ โ””โ”€โ”€ handler.go โ”œโ”€โ”€ cmd/ โ”‚ โ”œโ”€โ”€ onvif-cli/ # Client CLI tool โ”‚ โ””โ”€โ”€ onvif-server/ # Server CLI tool โ””โ”€โ”€ examples/ # Usage examples โ”œโ”€โ”€ discovery/ โ”œโ”€โ”€ device-info/ โ”œโ”€โ”€ ptz-control/ โ”œโ”€โ”€ imaging-settings/ โ””โ”€โ”€ onvif-server/ # Multi-lens camera server example ``` ## Design Principles 1. **Context-Aware**: All network operations accept `context.Context` for cancellation and timeouts 2. **Type Safety**: Strong typing with comprehensive struct definitions 3. **Error Handling**: Typed errors with clear error messages 4. **Concurrency Safe**: Thread-safe operations with proper locking 5. **Performance**: Connection pooling and efficient HTTP client reuse 6. **Standards Compliant**: Follows ONVIF specifications for SOAP/XML messaging ## Compatibility - **Go Version**: 1.21+ - **ONVIF Versions**: Compatible with ONVIF Profile S, Profile T, Profile G - **Tested Cameras**: Works with most ONVIF-compliant IP cameras including: - Axis - Hikvision - Dahua - Bosch - Hanwha (Samsung) - And many others ## Testing ```bash # Run tests go test ./... # Run tests with coverage go test -cover ./... # Run tests with race detection go test -race ./... ``` ## Contributing Contributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change. 1. Fork the repository 2. Create your feature branch (`git checkout -b feature/amazing-feature`) 3. Commit your changes (`git commit -m 'Add some amazing feature'`) 4. Push to the branch (`git push origin feature/amazing-feature`) 5. Open a Pull Request ## Roadmap - [ ] Event service implementation - [ ] Analytics service implementation - [ ] Recording service implementation - [ ] Replay service implementation - [ ] Advanced security features (TLS, X.509 certificates) - [ ] Comprehensive test suite with mock cameras - [ ] Performance benchmarks - [ ] CLI tool for camera management ## Debugging Tools ### ๐Ÿ” Diagnostic Utility Comprehensive camera testing and analysis with optional XML capture: ```bash go build -o onvif-diagnostics ./cmd/onvif-diagnostics/ # Standard diagnostic report ./onvif-diagnostics \ -endpoint "http://camera-ip/onvif/device_service" \ -username "admin" \ -password "pass" \ -verbose # With raw SOAP XML capture for debugging ./onvif-diagnostics \ -endpoint "http://camera-ip/onvif/device_service" \ -username "admin" \ -password "pass" \ -capture-xml \ -verbose ``` **Generates**: - `camera-logs/Manufacturer_Model_Firmware_timestamp.json` - Diagnostic report - `camera-logs/Manufacturer_Model_Firmware_xmlcapture_timestamp.tar.gz` - Raw XML (with `-capture-xml`) **See**: `XML_DEBUGGING_SOLUTION.md` for complete debugging workflow ### ๐Ÿงช Camera Test Framework Automated regression testing using captured camera responses: ```bash # 1. Capture from camera ./onvif-diagnostics -endpoint "http://camera/onvif/device_service" \ -username "user" -password "pass" -capture-xml # 2. Generate test go build -o generate-tests ./cmd/generate-tests/ ./generate-tests -capture camera-logs/*_xmlcapture_*.tar.gz -output testdata/captures/ # 3. Run tests go test -v ./testdata/captures/ ``` **Benefits**: - Test without physical cameras - Prevent regressions across camera models - Fast CI/CD integration - Real camera response validation **See**: `testdata/captures/README.md` for complete testing guide ## ๐Ÿ–ฅ๏ธ CLI Tools ### Interactive CLI Tool Feature-rich command-line interface for camera management and testing: ```bash go build -o onvif-cli ./cmd/onvif-cli/ # Start interactive menu ./onvif-cli ``` **Features**: - ๐Ÿ” Discover cameras on network with interface selection - ๐ŸŒ View all network interfaces and their capabilities - ๐Ÿ”— Connect to cameras with authentication - ๐Ÿ“ฑ Get device info, capabilities, and system settings - ๐Ÿ“น Retrieve media profiles and stream URLs - ๐ŸŽฎ PTZ control (pan, tilt, zoom, presets) - ๐ŸŽจ Imaging settings (brightness, contrast, exposure, etc.) - ๐Ÿ“ž Network interface selection for multi-interface systems **Usage**: ``` ๐Ÿ“‹ Main Menu: 1. Discover Cameras on Network 2. Connect to Camera 3. Device Operations 4. Media Operations 5. PTZ Operations 6. Imaging Operations 0. Exit ``` Note: The discovery function now intelligently detects multiple interfaces and shows options only when needed - no separate "List Network Interfaces" menu required. ### Quick Demo Tool Lightweight tool for quick testing and demonstration: ```bash go build -o onvif-quick ./cmd/onvif-quick/ # Start interactive menu ./onvif-quick ``` **Features**: - โšก Quick camera discovery - ๐ŸŒ List available network interfaces - ๐Ÿ”— Quick connection and camera info - ๐ŸŽฎ PTZ demo with movement examples - ๐Ÿ“ก Stream URL retrieval ### Network Interface Selection The CLI intelligently handles network interface selection automatically: - **Single interface**: Auto-discovery works seamlessly - **Multiple interfaces**: Shows interfaces only if auto-discovery fails - **Multiple active interfaces**: Tries each one and aggregates results For programmatic usage: ```go opts := &discovery.DiscoverOptions{ NetworkInterface: "eth0", // By interface name // or // NetworkInterface: "192.168.1.100", // By IP address } devices, err := discovery.DiscoverWithOptions(ctx, 5*time.Second, opts) ``` **See**: - `docs/CLI_NETWORK_INTERFACE_USAGE.md` - Detailed CLI guide - `discovery/NETWORK_INTERFACE_GUIDE.md` - API usage examples - `DESIGN_REFACTOR.md` - How smart interface detection works ## ๐ŸŒŸ Star History If you find this project useful, please consider giving it a star! โญ [![Star History Chart](https://api.star-history.com/svg?repos=0x524a/onvif-go&type=Date)](https://star-history.com/#0x524a/onvif-go&Date) ## ๐Ÿ“Š Project Stats ![GitHub repo size](https://img.shields.io/github/repo-size/0x524a/onvif-go) ![GitHub code size](https://img.shields.io/github/languages/code-size/0x524a/onvif-go) ![GitHub go.mod Go version](https://img.shields.io/github/go-mod/go-version/0x524a/onvif-go) ![GitHub last commit](https://img.shields.io/github/last-commit/0x524a/onvif-go) ## License This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. ## Acknowledgments - Inspired by the original [use-go/onvif](https://github.com/use-go/onvif) library - ONVIF specifications from [ONVIF.org](https://www.onvif.org) - Thanks to all contributors and the Go community ## Support - ๐Ÿ“– [Documentation](https://pkg.go.dev/github.com/0x524a/onvif-go) - ๐Ÿ› [Issue Tracker](https://github.com/0x524a/onvif-go/issues) - ๐Ÿ’ฌ [Discussions](https://github.com/0x524a/onvif-go/discussions) - ๐Ÿ”’ [Security Policy](.github/SECURITY.md) ## Keywords `onvif` `ip-camera` `surveillance` `golang` `rtsp` `ptz` `camera-control` `video-streaming` `security-camera` `nvr` `vms` `iot` `cctv` `hikvision` `axis` `dahua` `bosch` `camera-sdk` `golang-library` `soap` `ws-discovery` ## Related Projects - [ONVIF Device Manager](https://sourceforge.net/projects/onvifdm/) - GUI tool for testing ONVIF devices - [ONVIF Device Tool](https://www.onvif.org/tools/) - Official ONVIF test tool --- Made with โค๏ธ for the Go and IoT community