Files
onvif-go/examples/test-new-features/main.go
T

445 lines
15 KiB
Go

package main
import (
"context"
"encoding/json"
"flag"
"fmt"
"log"
"os"
"time"
"github.com/0x524a/onvif-go"
)
var (
endpoint = flag.String("endpoint", "http://192.168.1.201/onvif/device_service", "ONVIF device endpoint")
username = flag.String("username", "admin", "Username for authentication")
password = flag.String("password", "", "Password for authentication")
verbose = flag.Bool("verbose", true, "Enable verbose output")
output = flag.String("output", "test-results.json", "Output file for results")
)
type TestResults struct {
Timestamp time.Time `json:"timestamp"`
CameraInfo *CameraInfo `json:"camera_info"`
DeviceTests map[string]interface{} `json:"device_tests"`
MediaTests map[string]interface{} `json:"media_tests"`
PTZTests map[string]interface{} `json:"ptz_tests"`
ImagingTests map[string]interface{} `json:"imaging_tests"`
Errors []string `json:"errors"`
}
type CameraInfo struct {
Manufacturer string `json:"manufacturer"`
Model string `json:"model"`
FirmwareVersion string `json:"firmware_version"`
SerialNumber string `json:"serial_number"`
HardwareID string `json:"hardware_id"`
}
func main() {
flag.Parse()
if *password == "" {
log.Fatal("Password is required. Use -password flag")
}
log.Printf("Testing ONVIF camera at: %s", *endpoint)
log.Printf("Username: %s", *username)
// Create client
client, err := onvif.NewClient(
*endpoint,
onvif.WithCredentials(*username, *password),
onvif.WithTimeout(30*time.Second),
)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
results := &TestResults{
Timestamp: time.Now(),
DeviceTests: make(map[string]interface{}),
MediaTests: make(map[string]interface{}),
PTZTests: make(map[string]interface{}),
ImagingTests: make(map[string]interface{}),
Errors: []string{},
}
// Initialize client
log.Println("\n=== Initializing Client ===")
if err := client.Initialize(ctx); err != nil {
log.Printf("Warning: Initialize failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("Initialize: %v", err))
}
// Get basic device information
log.Println("\n=== Getting Device Information ===")
info, err := client.GetDeviceInformation(ctx)
if err != nil {
log.Fatalf("Failed to get device information: %v", err)
}
log.Printf("Camera: %s %s", info.Manufacturer, info.Model)
log.Printf("Firmware: %s", info.FirmwareVersion)
log.Printf("Serial: %s", info.SerialNumber)
results.CameraInfo = &CameraInfo{
Manufacturer: info.Manufacturer,
Model: info.Model,
FirmwareVersion: info.FirmwareVersion,
SerialNumber: info.SerialNumber,
HardwareID: info.HardwareID,
}
// Test NEW Device Service Methods
testDeviceService(ctx, client, results)
// Test NEW Media Service Methods
testMediaService(ctx, client, results)
// Test NEW PTZ Service Methods
testPTZService(ctx, client, results)
// Test NEW Imaging Service Methods
testImagingService(ctx, client, results)
// Save results
saveResults(results)
log.Printf("\n=== Test Complete ===")
log.Printf("Results saved to: %s", *output)
log.Printf("Total errors: %d", len(results.Errors))
}
func testDeviceService(ctx context.Context, client *onvif.Client, results *TestResults) {
log.Println("\n=== Testing Device Service (NEW Methods) ===")
// Test GetHostname
log.Println("\n--- GetHostname ---")
if hostname, err := client.GetHostname(ctx); err != nil {
log.Printf("❌ GetHostname failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetHostname: %v", err))
} else {
log.Printf("✅ Hostname: %+v", hostname)
results.DeviceTests["hostname"] = hostname
}
// Test GetDNS
log.Println("\n--- GetDNS ---")
if dns, err := client.GetDNS(ctx); err != nil {
log.Printf("❌ GetDNS failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetDNS: %v", err))
} else {
log.Printf("✅ DNS: FromDHCP=%v, SearchDomain=%v", dns.FromDHCP, dns.SearchDomain)
log.Printf(" DNSFromDHCP: %+v", dns.DNSFromDHCP)
log.Printf(" DNSManual: %+v", dns.DNSManual)
results.DeviceTests["dns"] = dns
}
// Test GetNTP
log.Println("\n--- GetNTP ---")
if ntp, err := client.GetNTP(ctx); err != nil {
log.Printf("❌ GetNTP failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetNTP: %v", err))
} else {
log.Printf("✅ NTP: FromDHCP=%v", ntp.FromDHCP)
log.Printf(" NTPFromDHCP: %+v", ntp.NTPFromDHCP)
log.Printf(" NTPManual: %+v", ntp.NTPManual)
results.DeviceTests["ntp"] = ntp
}
// Test GetNetworkInterfaces
log.Println("\n--- GetNetworkInterfaces ---")
if interfaces, err := client.GetNetworkInterfaces(ctx); err != nil {
log.Printf("❌ GetNetworkInterfaces failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetNetworkInterfaces: %v", err))
} else {
log.Printf("✅ Found %d network interface(s)", len(interfaces))
for i, iface := range interfaces {
log.Printf(" Interface %d: Token=%s, Name=%s, Enabled=%v",
i+1, iface.Token, iface.Info.Name, iface.Enabled)
log.Printf(" HwAddress=%s, MTU=%d", iface.Info.HwAddress, iface.Info.MTU)
if iface.IPv4 != nil {
log.Printf(" IPv4: Enabled=%v, DHCP=%v", iface.IPv4.Enabled, iface.IPv4.Config.DHCP)
for _, addr := range iface.IPv4.Config.Manual {
log.Printf(" Manual: %s/%d", addr.Address, addr.PrefixLength)
}
}
}
results.DeviceTests["network_interfaces"] = interfaces
}
// Test GetScopes
log.Println("\n--- GetScopes ---")
if scopes, err := client.GetScopes(ctx); err != nil {
log.Printf("❌ GetScopes failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetScopes: %v", err))
} else {
log.Printf("✅ Found %d scope(s)", len(scopes))
for i, scope := range scopes {
log.Printf(" Scope %d: Def=%s, Item=%s", i+1, scope.ScopeDef, scope.ScopeItem)
}
results.DeviceTests["scopes"] = scopes
}
// Test GetUsers
log.Println("\n--- GetUsers ---")
if users, err := client.GetUsers(ctx); err != nil {
log.Printf("❌ GetUsers failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetUsers: %v", err))
} else {
log.Printf("✅ Found %d user(s)", len(users))
for i, user := range users {
log.Printf(" User %d: Username=%s, Level=%s", i+1, user.Username, user.UserLevel)
}
results.DeviceTests["users"] = users
}
}
func testMediaService(ctx context.Context, client *onvif.Client, results *TestResults) {
log.Println("\n=== Testing Media Service (NEW Methods) ===")
// Test GetVideoSources
log.Println("\n--- GetVideoSources ---")
if sources, err := client.GetVideoSources(ctx); err != nil {
log.Printf("❌ GetVideoSources failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetVideoSources: %v", err))
} else {
log.Printf("✅ Found %d video source(s)", len(sources))
for i, source := range sources {
log.Printf(" Source %d: Token=%s, Framerate=%.1f",
i+1, source.Token, source.Framerate)
if source.Resolution != nil {
log.Printf(" Resolution: %dx%d", source.Resolution.Width, source.Resolution.Height)
}
}
results.MediaTests["video_sources"] = sources
}
// Test GetAudioSources
log.Println("\n--- GetAudioSources ---")
if sources, err := client.GetAudioSources(ctx); err != nil {
log.Printf("❌ GetAudioSources failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetAudioSources: %v", err))
} else {
log.Printf("✅ Found %d audio source(s)", len(sources))
for i, source := range sources {
log.Printf(" Source %d: Token=%s, Channels=%d",
i+1, source.Token, source.Channels)
}
results.MediaTests["audio_sources"] = sources
}
// Test GetAudioOutputs
log.Println("\n--- GetAudioOutputs ---")
if outputs, err := client.GetAudioOutputs(ctx); err != nil {
log.Printf("❌ GetAudioOutputs failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetAudioOutputs: %v", err))
} else {
log.Printf("✅ Found %d audio output(s)", len(outputs))
for i, output := range outputs {
log.Printf(" Output %d: Token=%s", i+1, output.Token)
}
results.MediaTests["audio_outputs"] = outputs
}
// Get profiles for further testing
profiles, err := client.GetProfiles(ctx)
if err != nil {
log.Printf("⚠️ Could not get profiles: %v", err)
return
}
if len(profiles) > 0 {
log.Printf("\nUsing profile: %s (%s)", profiles[0].Name, profiles[0].Token)
results.MediaTests["test_profile_token"] = profiles[0].Token
}
}
func testPTZService(ctx context.Context, client *onvif.Client, results *TestResults) {
log.Println("\n=== Testing PTZ Service (NEW Methods) ===")
// Get profiles to find one with PTZ
profiles, err := client.GetProfiles(ctx)
if err != nil {
log.Printf("⚠️ Could not get profiles for PTZ tests: %v", err)
return
}
var ptzProfile *onvif.Profile
for _, p := range profiles {
if p.PTZConfiguration != nil {
ptzProfile = p
break
}
}
if ptzProfile == nil {
log.Println("⚠️ No PTZ-enabled profile found, skipping PTZ tests")
results.PTZTests["skipped"] = "No PTZ profile found"
return
}
log.Printf("Using PTZ profile: %s (%s)", ptzProfile.Name, ptzProfile.Token)
results.PTZTests["test_profile_token"] = ptzProfile.Token
// Test GetConfigurations
log.Println("\n--- GetConfigurations ---")
if configs, err := client.GetConfigurations(ctx); err != nil {
log.Printf("❌ GetConfigurations failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetConfigurations: %v", err))
} else {
log.Printf("✅ Found %d PTZ configuration(s)", len(configs))
for i, cfg := range configs {
log.Printf(" Config %d: Token=%s, Name=%s, NodeToken=%s",
i+1, cfg.Token, cfg.Name, cfg.NodeToken)
}
results.PTZTests["configurations"] = configs
}
// Test GetConfiguration
if ptzProfile.PTZConfiguration != nil {
log.Println("\n--- GetConfiguration ---")
if cfg, err := client.GetConfiguration(ctx, ptzProfile.PTZConfiguration.Token); err != nil {
log.Printf("❌ GetConfiguration failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetConfiguration: %v", err))
} else {
log.Printf("✅ Configuration: Token=%s, Name=%s", cfg.Token, cfg.Name)
results.PTZTests["configuration"] = cfg
}
}
// Test GetPresets
log.Println("\n--- GetPresets ---")
if presets, err := client.GetPresets(ctx, ptzProfile.Token); err != nil {
log.Printf("❌ GetPresets failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetPresets: %v", err))
} else {
log.Printf("✅ Found %d preset(s)", len(presets))
for i, preset := range presets {
log.Printf(" Preset %d: Token=%s, Name=%s", i+1, preset.Token, preset.Name)
if preset.PTZPosition != nil {
if preset.PTZPosition.PanTilt != nil {
log.Printf(" PanTilt: X=%.2f, Y=%.2f",
preset.PTZPosition.PanTilt.X, preset.PTZPosition.PanTilt.Y)
}
if preset.PTZPosition.Zoom != nil {
log.Printf(" Zoom: X=%.2f", preset.PTZPosition.Zoom.X)
}
}
}
results.PTZTests["presets"] = presets
}
// Test GetStatus
log.Println("\n--- GetStatus ---")
if status, err := client.GetStatus(ctx, ptzProfile.Token); err != nil {
log.Printf("❌ GetStatus failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("PTZ GetStatus: %v", err))
} else {
log.Printf("✅ PTZ Status:")
if status.Position != nil {
if status.Position.PanTilt != nil {
log.Printf(" Position PanTilt: X=%.2f, Y=%.2f",
status.Position.PanTilt.X, status.Position.PanTilt.Y)
}
if status.Position.Zoom != nil {
log.Printf(" Position Zoom: X=%.2f", status.Position.Zoom.X)
}
}
if status.MoveStatus != nil {
log.Printf(" MoveStatus: PanTilt=%s, Zoom=%s",
status.MoveStatus.PanTilt, status.MoveStatus.Zoom)
}
results.PTZTests["status"] = status
}
}
func testImagingService(ctx context.Context, client *onvif.Client, results *TestResults) {
log.Println("\n=== Testing Imaging Service (NEW Methods) ===")
// Get video sources first
sources, err := client.GetVideoSources(ctx)
if err != nil || len(sources) == 0 {
log.Printf("⚠️ Could not get video sources for imaging tests: %v", err)
return
}
videoSourceToken := sources[0].Token
log.Printf("Using video source: %s", videoSourceToken)
results.ImagingTests["test_video_source_token"] = videoSourceToken
// Test GetOptions
log.Println("\n--- GetOptions ---")
if options, err := client.GetOptions(ctx, videoSourceToken); err != nil {
log.Printf("❌ GetOptions failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetOptions: %v", err))
} else {
log.Printf("✅ Imaging Options:")
if options.Brightness != nil {
log.Printf(" Brightness: Min=%.1f, Max=%.1f", options.Brightness.Min, options.Brightness.Max)
}
if options.ColorSaturation != nil {
log.Printf(" ColorSaturation: Min=%.1f, Max=%.1f", options.ColorSaturation.Min, options.ColorSaturation.Max)
}
if options.Contrast != nil {
log.Printf(" Contrast: Min=%.1f, Max=%.1f", options.Contrast.Min, options.Contrast.Max)
}
results.ImagingTests["options"] = options
}
// Test GetMoveOptions
log.Println("\n--- GetMoveOptions ---")
if moveOptions, err := client.GetMoveOptions(ctx, videoSourceToken); err != nil {
log.Printf("❌ GetMoveOptions failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("GetMoveOptions: %v", err))
} else {
log.Printf("✅ Move Options:")
if moveOptions.Absolute != nil {
log.Printf(" Absolute Position: Min=%.1f, Max=%.1f",
moveOptions.Absolute.Position.Min, moveOptions.Absolute.Position.Max)
log.Printf(" Absolute Speed: Min=%.1f, Max=%.1f",
moveOptions.Absolute.Speed.Min, moveOptions.Absolute.Speed.Max)
}
if moveOptions.Relative != nil {
log.Printf(" Relative Distance: Min=%.1f, Max=%.1f",
moveOptions.Relative.Distance.Min, moveOptions.Relative.Distance.Max)
}
if moveOptions.Continuous != nil {
log.Printf(" Continuous Speed: Min=%.1f, Max=%.1f",
moveOptions.Continuous.Speed.Min, moveOptions.Continuous.Speed.Max)
}
results.ImagingTests["move_options"] = moveOptions
}
// Test GetImagingStatus
log.Println("\n--- GetImagingStatus ---")
if status, err := client.GetImagingStatus(ctx, videoSourceToken); err != nil {
log.Printf("❌ GetImagingStatus failed: %v", err)
results.Errors = append(results.Errors, fmt.Sprintf("Imaging GetImagingStatus: %v", err))
} else {
log.Printf("✅ Imaging Status:")
if status.FocusStatus != nil {
log.Printf(" Focus Position: %.2f", status.FocusStatus.Position)
log.Printf(" Focus MoveStatus: %s", status.FocusStatus.MoveStatus)
if status.FocusStatus.Error != "" {
log.Printf(" Focus Error: %s", status.FocusStatus.Error)
}
}
results.ImagingTests["status"] = status
}
}
func saveResults(results *TestResults) {
data, err := json.MarshalIndent(results, "", " ")
if err != nil {
log.Fatalf("Failed to marshal results: %v", err)
}
if err := os.WriteFile(*output, data, 0644); err != nil {
log.Fatalf("Failed to write results: %v", err)
}
}