package main import ( "context" "fmt" "log" "time" "github.com/0x524a/onvif-go" ) func main() { // Camera connection details endpoint := "http://192.168.1.100/onvif/device_service" username := "admin" password := "password" fmt.Println("Connecting to ONVIF camera...") // Create a new ONVIF 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() // Initialize client if err := client.Initialize(ctx); err != nil { log.Fatalf("Failed to initialize client: %v", err) } // Get profiles profiles, err := client.GetProfiles(ctx) if err != nil { log.Fatalf("Failed to get profiles: %v", err) } if len(profiles) == 0 { log.Fatal("No profiles found") } profileToken := profiles[0].Token fmt.Printf("Using profile: %s\n\n", profiles[0].Name) // Demonstrate PTZ controls demonstratePTZ(ctx, client, profileToken) } func demonstratePTZ(ctx context.Context, client *onvif.Client, profileToken string) { // Get current PTZ status fmt.Println("Getting current PTZ status...") status, err := client.GetStatus(ctx, profileToken) if err != nil { log.Printf("Warning: Failed to get PTZ status: %v\n", err) } else { fmt.Printf("Current Position:\n") if status.Position != nil { if status.Position.PanTilt != nil { fmt.Printf(" Pan/Tilt: X=%.2f, Y=%.2f\n", status.Position.PanTilt.X, status.Position.PanTilt.Y) } if status.Position.Zoom != nil { fmt.Printf(" Zoom: %.2f\n", status.Position.Zoom.X) } } fmt.Println() } // Get presets fmt.Println("Getting PTZ presets...") presets, err := client.GetPresets(ctx, profileToken) if err != nil { log.Printf("Warning: Failed to get presets: %v\n", err) } else { fmt.Printf("Found %d preset(s):\n", len(presets)) for _, preset := range presets { fmt.Printf(" - %s (Token: %s)\n", preset.Name, preset.Token) } fmt.Println() } // Continuous move right for 2 seconds fmt.Println("Moving camera right...") velocity := &onvif.PTZSpeed{ PanTilt: &onvif.Vector2D{ X: 0.5, // Move right Y: 0.0, }, } timeout := "PT2S" // 2 seconds if err := client.ContinuousMove(ctx, profileToken, velocity, &timeout); err != nil { log.Printf("Failed to move: %v\n", err) } else { time.Sleep(2 * time.Second) } // Stop movement fmt.Println("Stopping camera movement...") if err := client.Stop(ctx, profileToken, true, false); err != nil { log.Printf("Failed to stop: %v\n", err) } // Relative move fmt.Println("\nPerforming relative move (up and zoom in)...") translation := &onvif.PTZVector{ PanTilt: &onvif.Vector2D{ X: 0.0, Y: 0.1, // Move up }, Zoom: &onvif.Vector1D{ X: 0.1, // Zoom in }, } if err := client.RelativeMove(ctx, profileToken, translation, nil); err != nil { log.Printf("Failed to relative move: %v\n", err) } else { time.Sleep(2 * time.Second) } // Absolute move to home position fmt.Println("\nMoving to home position...") homePosition := &onvif.PTZVector{ PanTilt: &onvif.Vector2D{ X: 0.0, Y: 0.0, }, Zoom: &onvif.Vector1D{ X: 0.0, }, } if err := client.AbsoluteMove(ctx, profileToken, homePosition, nil); err != nil { log.Printf("Failed to absolute move: %v\n", err) } else { time.Sleep(2 * time.Second) } // Go to preset if available if len(presets) > 0 { fmt.Printf("\nGoing to preset: %s\n", presets[0].Name) if err := client.GotoPreset(ctx, profileToken, presets[0].Token, nil); err != nil { log.Printf("Failed to go to preset: %v\n", err) } else { time.Sleep(2 * time.Second) } } fmt.Println("\nPTZ demonstration complete!") }