Files
onvif-go/testdata/captures/enhanced_device_features_test.go
T
ProtoTess 9cf30e2c41 cleanup
2026-01-16 04:58:24 +00:00

393 lines
10 KiB
Go

//go:build real_camera
package onvif
import (
"context"
"os"
"testing"
"time"
"github.com/0x524a/onvif-go"
)
// getTestCredentials returns ONVIF credentials from environment variables.
// Required environment variables:
// - ONVIF_ENDPOINT: Camera endpoint URL (e.g., http://192.168.1.201/onvif/device_service)
// - ONVIF_USERNAME: ONVIF username
// - ONVIF_PASSWORD: ONVIF password
func getTestCredentials(t *testing.T) (endpoint, username, password string) {
endpoint = os.Getenv("ONVIF_ENDPOINT")
username = os.Getenv("ONVIF_USERNAME")
password = os.Getenv("ONVIF_PASSWORD")
if endpoint == "" || username == "" || password == "" {
t.Skip("ONVIF credentials not configured. Set ONVIF_ENDPOINT, ONVIF_USERNAME, and ONVIF_PASSWORD environment variables.")
}
return endpoint, username, password
}
// TestEnhancedDeviceFeatures tests new Device service methods with real camera data
// Based on test results from Bosch FLEXIDOME indoor 5100i IR (8.71.0066)
func TestEnhancedDeviceFeatures(t *testing.T) {
endpoint, username, password := getTestCredentials(t)
// Create client with test credentials
client, err := onvif.NewClient(
endpoint,
onvif.WithCredentials(username, password),
onvif.WithTimeout(30*time.Second),
)
if err != nil {
t.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
t.Run("GetHostname", func(t *testing.T) {
hostname, err := client.GetHostname(ctx)
if err != nil {
t.Fatalf("GetHostname failed: %v", err)
}
// Bosch camera has hostname configuration
if hostname == nil {
t.Fatal("Expected hostname information, got nil")
}
t.Logf("Hostname: FromDHCP=%v, Name=%q", hostname.FromDHCP, hostname.Name)
})
t.Run("GetDNS", func(t *testing.T) {
dns, err := client.GetDNS(ctx)
if err != nil {
t.Fatalf("GetDNS failed: %v", err)
}
if dns == nil {
t.Fatal("Expected DNS information, got nil")
}
// Bosch camera uses DHCP for DNS
if !dns.FromDHCP {
t.Logf("Note: Camera not using DHCP for DNS")
}
// Should have at least one DNS server
if len(dns.DNSFromDHCP) == 0 && len(dns.DNSManual) == 0 {
t.Error("Expected at least one DNS server")
}
t.Logf("DNS: FromDHCP=%v, Servers=%d (DHCP) + %d (Manual)",
dns.FromDHCP, len(dns.DNSFromDHCP), len(dns.DNSManual))
})
t.Run("GetNTP", func(t *testing.T) {
ntp, err := client.GetNTP(ctx)
if err != nil {
t.Fatalf("GetNTP failed: %v", err)
}
if ntp == nil {
t.Fatal("Expected NTP information, got nil")
}
// Bosch camera uses DHCP for NTP
if !ntp.FromDHCP {
t.Logf("Note: Camera not using DHCP for NTP")
}
t.Logf("NTP: FromDHCP=%v, Servers=%d (DHCP) + %d (Manual)",
ntp.FromDHCP, len(ntp.NTPFromDHCP), len(ntp.NTPManual))
})
t.Run("GetNetworkInterfaces", func(t *testing.T) {
interfaces, err := client.GetNetworkInterfaces(ctx)
if err != nil {
t.Fatalf("GetNetworkInterfaces failed: %v", err)
}
// Bosch camera has 1 network interface
if len(interfaces) == 0 {
t.Fatal("Expected at least one network interface")
}
iface := interfaces[0]
if iface.Token == "" {
t.Error("Expected interface to have token")
}
if iface.Info.Name == "" {
t.Error("Expected interface to have name")
}
if iface.Info.HwAddress == "" {
t.Error("Expected interface to have hardware address")
}
// Bosch camera has MTU of 1514
if iface.Info.MTU == 0 {
t.Error("Expected interface to have MTU")
}
t.Logf("Interface: Token=%s, Name=%s, HwAddr=%s, MTU=%d",
iface.Token, iface.Info.Name, iface.Info.HwAddress, iface.Info.MTU)
if iface.IPv4 != nil {
t.Logf(" IPv4: Enabled=%v, DHCP=%v",
iface.IPv4.Enabled, iface.IPv4.Config.DHCP)
}
})
t.Run("GetScopes", func(t *testing.T) {
scopes, err := client.GetScopes(ctx)
if err != nil {
t.Fatalf("GetScopes failed: %v", err)
}
// Bosch camera has 8 scopes
if len(scopes) == 0 {
t.Fatal("Expected at least one scope")
}
// Check for expected scopes
foundManufacturer := false
foundType := false
foundProfiles := 0
for _, scope := range scopes {
if scope.ScopeItem == "onvif://www.onvif.org/name/Bosch" {
foundManufacturer = true
}
if scope.ScopeItem == "onvif://www.onvif.org/type/Network_Video_Transmitter" {
foundType = true
}
// Count ONVIF profiles
if len(scope.ScopeItem) > 30 && scope.ScopeItem[:30] == "onvif://www.onvif.org/Profile/" {
foundProfiles++
}
}
if !foundManufacturer {
t.Error("Expected to find manufacturer scope")
}
if !foundType {
t.Error("Expected to find device type scope")
}
t.Logf("Scopes: Total=%d, Manufacturer=%v, Type=%v, Profiles=%d",
len(scopes), foundManufacturer, foundType, foundProfiles)
})
t.Run("GetUsers", func(t *testing.T) {
users, err := client.GetUsers(ctx)
if err != nil {
t.Fatalf("GetUsers failed: %v", err)
}
// Bosch camera has 3 users
if len(users) == 0 {
t.Fatal("Expected at least one user")
}
// Verify user levels
userLevels := make(map[string]int)
for _, user := range users {
if user.Username == "" {
t.Error("Expected user to have username")
}
if user.UserLevel == "" {
t.Error("Expected user to have level")
}
userLevels[user.UserLevel]++
}
t.Logf("Users: Total=%d, Administrator=%d, Operator=%d, User=%d",
len(users),
userLevels["Administrator"],
userLevels["Operator"],
userLevels["User"])
})
}
// TestEnhancedMediaFeatures tests new Media service methods
func TestEnhancedMediaFeatures(t *testing.T) {
endpoint, username, password := getTestCredentials(t)
client, err := onvif.NewClient(
endpoint,
onvif.WithCredentials(username, password),
onvif.WithTimeout(30*time.Second),
)
if err != nil {
t.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
// Initialize to get media endpoint
if err := client.Initialize(ctx); err != nil {
t.Logf("Warning: Initialize failed: %v", err)
}
t.Run("GetVideoSources", func(t *testing.T) {
sources, err := client.GetVideoSources(ctx)
if err != nil {
t.Fatalf("GetVideoSources failed: %v", err)
}
// Bosch camera has 1 video source
if len(sources) == 0 {
t.Fatal("Expected at least one video source")
}
source := sources[0]
if source.Token == "" {
t.Error("Expected source to have token")
}
// Bosch camera supports 30fps
if source.Framerate == 0 {
t.Error("Expected source to have framerate")
}
// Bosch camera has 1920x1080 resolution
if source.Resolution == nil {
t.Error("Expected source to have resolution")
} else {
if source.Resolution.Width == 0 || source.Resolution.Height == 0 {
t.Error("Expected valid resolution dimensions")
}
t.Logf("Video Source: Token=%s, Framerate=%.1ffps, Resolution=%dx%d",
source.Token, source.Framerate,
source.Resolution.Width, source.Resolution.Height)
}
})
t.Run("GetAudioSources", func(t *testing.T) {
sources, err := client.GetAudioSources(ctx)
if err != nil {
t.Fatalf("GetAudioSources failed: %v", err)
}
// Bosch camera has 1 audio source with 2 channels
if len(sources) == 0 {
t.Fatal("Expected at least one audio source")
}
source := sources[0]
if source.Token == "" {
t.Error("Expected source to have token")
}
t.Logf("Audio Source: Token=%s, Channels=%d",
source.Token, source.Channels)
})
t.Run("GetAudioOutputs", func(t *testing.T) {
outputs, err := client.GetAudioOutputs(ctx)
if err != nil {
t.Fatalf("GetAudioOutputs failed: %v", err)
}
// Bosch camera has 1 audio output
if len(outputs) == 0 {
t.Fatal("Expected at least one audio output")
}
output := outputs[0]
if output.Token == "" {
t.Error("Expected output to have token")
}
t.Logf("Audio Output: Token=%s", output.Token)
})
}
// TestEnhancedImagingFeatures tests new Imaging service methods
func TestEnhancedImagingFeatures(t *testing.T) {
endpoint, username, password := getTestCredentials(t)
client, err := onvif.NewClient(
endpoint,
onvif.WithCredentials(username, password),
onvif.WithTimeout(30*time.Second),
)
if err != nil {
t.Fatalf("Failed to create client: %v", err)
}
ctx := context.Background()
// Initialize to get imaging endpoint
if err := client.Initialize(ctx); err != nil {
t.Logf("Warning: Initialize failed: %v", err)
}
// Get video source token
sources, err := client.GetVideoSources(ctx)
if err != nil || len(sources) == 0 {
t.Skip("No video sources available for imaging tests")
}
videoSourceToken := sources[0].Token
t.Run("GetOptions", func(t *testing.T) {
options, err := client.GetOptions(ctx, videoSourceToken)
if err != nil {
t.Fatalf("GetOptions failed: %v", err)
}
if options == nil {
t.Fatal("Expected imaging options, got nil")
}
// Bosch camera supports brightness (0-255)
if options.Brightness != nil {
if options.Brightness.Min > options.Brightness.Max {
t.Error("Expected Min <= Max for brightness")
}
t.Logf("Brightness range: %.0f - %.0f",
options.Brightness.Min, options.Brightness.Max)
}
// Bosch camera supports color saturation (0-255)
if options.ColorSaturation != nil {
if options.ColorSaturation.Min > options.ColorSaturation.Max {
t.Error("Expected Min <= Max for color saturation")
}
t.Logf("ColorSaturation range: %.0f - %.0f",
options.ColorSaturation.Min, options.ColorSaturation.Max)
}
// Bosch camera supports contrast (0-255)
if options.Contrast != nil {
if options.Contrast.Min > options.Contrast.Max {
t.Error("Expected Min <= Max for contrast")
}
t.Logf("Contrast range: %.0f - %.0f",
options.Contrast.Min, options.Contrast.Max)
}
})
t.Run("GetMoveOptions", func(t *testing.T) {
moveOptions, err := client.GetMoveOptions(ctx, videoSourceToken)
if err != nil {
t.Fatalf("GetMoveOptions failed: %v", err)
}
if moveOptions == nil {
t.Fatal("Expected move options, got nil")
}
// Log available move options
hasAbsolute := moveOptions.Absolute != nil
hasRelative := moveOptions.Relative != nil
hasContinuous := moveOptions.Continuous != nil
t.Logf("Move Options: Absolute=%v, Relative=%v, Continuous=%v",
hasAbsolute, hasRelative, hasContinuous)
})
}