Files
onvif-go/examples/test-event-deviceio/main.go
T
0x524a df3cdfb5ab feat: add missing Device IO operations and fix formatting
- Add GetVideoOutputConfiguration operation
- Add GetVideoOutputConfigurationOptions operation
- Add SetVideoOutputConfiguration operation
- Add GetRelayOutputOptions operation
- Add comprehensive tests for new operations
- Add CLI support for new Device IO operations
- Fix gofmt formatting issues in all files
2025-12-03 01:03:11 -05:00

236 lines
7.1 KiB
Go

// Package main tests Event and Device IO services against a real camera.
package main
import (
"context"
"flag"
"fmt"
"os"
"time"
onvif "github.com/0x524a/onvif-go"
)
const notAvailable = "N/A"
func main() {
// Command line flags.
cameraIP := flag.String("ip", "192.168.1.201", "Camera IP address")
username := flag.String("user", "service", "Camera username")
password := flag.String("pass", "Service.1234", "Camera password")
flag.Parse()
endpoint := fmt.Sprintf("http://%s/onvif/device_service", *cameraIP)
fmt.Printf("Testing Event and Device IO services on camera: %s\n", *cameraIP)
fmt.Printf("Endpoint: %s\n", endpoint)
fmt.Printf("Username: %s\n\n", *username)
// Create client.
client, err := onvif.NewClient(endpoint,
onvif.WithCredentials(*username, *password),
onvif.WithTimeout(30*time.Second),
)
if err != nil {
fmt.Printf("Failed to create client: %v\n", err)
os.Exit(1)
}
ctx := context.Background()
// Test device information first to verify connectivity.
fmt.Println("=== Testing Device Connectivity ===")
info, err := client.GetDeviceInformation(ctx)
if err != nil {
fmt.Printf("Failed to get device information: %v\n", err)
os.Exit(1)
}
fmt.Printf("Device: %s %s\n", info.Manufacturer, info.Model)
fmt.Printf("Firmware: %s\n", info.FirmwareVersion)
fmt.Printf("Serial: %s\n\n", info.SerialNumber)
// Test Event Service.
testEventService(ctx, client)
// Test Device IO Service.
testDeviceIOService(ctx, client)
fmt.Println("\n=== All Tests Completed ===")
}
func testEventService(ctx context.Context, client *onvif.Client) {
fmt.Println("=== Testing Event Service ===")
// 1. Get Event Service Capabilities.
fmt.Println("\n1. GetEventServiceCapabilities")
caps, err := client.GetEventServiceCapabilities(ctx)
if err != nil {
fmt.Printf(" ERROR: %v\n", err)
} else {
fmt.Printf(" WSSubscriptionPolicySupport: %v\n", caps.WSSubscriptionPolicySupport)
fmt.Printf(" MaxPullPoints: %d\n", caps.MaxPullPoints)
fmt.Printf(" PersistentNotificationStorage: %v\n", caps.PersistentNotificationStorage)
fmt.Printf(" EventBrokerProtocols: %v\n", caps.EventBrokerProtocols)
fmt.Printf(" MaxEventBrokers: %d\n", caps.MaxEventBrokers)
}
// 2. Get Event Properties.
fmt.Println("\n2. GetEventProperties")
props, err := client.GetEventProperties(ctx)
if err != nil {
fmt.Printf(" ERROR: %v\n", err)
} else {
fmt.Printf(" FixedTopicSet: %v\n", props.FixedTopicSet)
fmt.Printf(" TopicNamespaceLocations: %d\n", len(props.TopicNamespaceLocation))
fmt.Printf(" TopicExpressionDialects: %d\n", len(props.TopicExpressionDialects))
}
// 3. Create Pull Point Subscription.
fmt.Println("\n3. CreatePullPointSubscription")
termTime := 60 * time.Second
sub, err := client.CreatePullPointSubscription(ctx, "", &termTime, "")
if err != nil {
fmt.Printf(" ERROR: %v\n", err)
} else {
fmt.Printf(" SubscriptionReference: %s\n", sub.SubscriptionReference)
fmt.Printf(" CurrentTime: %v\n", sub.CurrentTime)
fmt.Printf(" TerminationTime: %v\n", sub.TerminationTime)
// 4. Pull Messages.
if sub.SubscriptionReference != "" {
fmt.Println("\n4. PullMessages")
messages, err := client.PullMessages(ctx, sub.SubscriptionReference, 5*time.Second, 10)
if err != nil {
fmt.Printf(" ERROR: %v\n", err)
} else {
fmt.Printf(" Received %d messages\n", len(messages))
for i, msg := range messages {
if i >= 3 {
fmt.Printf(" ... and %d more\n", len(messages)-3)
break
}
fmt.Printf(" Message %d: Topic=%s, Operation=%s\n",
i+1, msg.Topic, msg.Message.PropertyOperation)
}
}
// 5. Renew Subscription.
fmt.Println("\n5. RenewSubscription")
curTime, newTermTime, err := client.RenewSubscription(ctx, sub.SubscriptionReference, 120*time.Second)
if err != nil {
fmt.Printf(" ERROR: %v\n", err)
} else {
fmt.Printf(" CurrentTime: %v\n", curTime)
fmt.Printf(" NewTerminationTime: %v\n", newTermTime)
}
// 6. Unsubscribe.
fmt.Println("\n6. Unsubscribe")
err = client.Unsubscribe(ctx, sub.SubscriptionReference)
if err != nil {
fmt.Printf(" ERROR: %v\n", err)
} else {
fmt.Println(" Successfully unsubscribed")
}
}
}
// 7. Get Event Brokers (optional, may not be supported).
fmt.Println("\n7. GetEventBrokers")
brokers, err := client.GetEventBrokers(ctx)
if err != nil {
fmt.Printf(" ERROR (may not be supported): %v\n", err)
} else {
fmt.Printf(" Found %d event brokers\n", len(brokers))
for i, broker := range brokers {
fmt.Printf(" Broker %d: %s (Status: %s)\n", i+1, broker.Address, broker.Status)
}
}
}
func testDeviceIOService(ctx context.Context, client *onvif.Client) {
fmt.Println("\n=== Testing Device IO Service ===")
// 1. Get Device IO Service Capabilities.
fmt.Println("\n1. GetDeviceIOServiceCapabilities")
caps, err := client.GetDeviceIOServiceCapabilities(ctx)
if err != nil {
fmt.Printf(" ERROR: %v\n", err)
} else {
fmt.Printf(" VideoSources: %d\n", caps.VideoSources)
fmt.Printf(" VideoOutputs: %d\n", caps.VideoOutputs)
fmt.Printf(" AudioSources: %d\n", caps.AudioSources)
fmt.Printf(" AudioOutputs: %d\n", caps.AudioOutputs)
fmt.Printf(" RelayOutputs: %d\n", caps.RelayOutputs)
fmt.Printf(" DigitalInputs: %d\n", caps.DigitalInputs)
fmt.Printf(" SerialPorts: %d\n", caps.SerialPorts)
}
// 2. Get Digital Inputs.
fmt.Println("\n2. GetDigitalInputs")
inputs, err := client.GetDigitalInputs(ctx)
if err != nil {
fmt.Printf(" ERROR: %v\n", err)
} else {
fmt.Printf(" Found %d digital inputs\n", len(inputs))
for i, input := range inputs {
fmt.Printf(" Input %d: Token=%s, IdleState=%s\n", i+1, input.Token, input.IdleState)
}
}
// 3. Get Video Outputs.
fmt.Println("\n3. GetVideoOutputs")
outputs, err := client.GetVideoOutputs(ctx)
if err != nil {
fmt.Printf(" ERROR: %v\n", err)
} else {
fmt.Printf(" Found %d video outputs\n", len(outputs))
for i, output := range outputs {
res := notAvailable
if output.Resolution != nil {
res = fmt.Sprintf("%dx%d", output.Resolution.Width, output.Resolution.Height)
}
fmt.Printf(" Output %d: Token=%s, Resolution=%s, RefreshRate=%.1f\n",
i+1, output.Token, res, output.RefreshRate)
}
}
// 4. Get Serial Ports.
fmt.Println("\n4. GetSerialPorts")
ports, err := client.GetSerialPorts(ctx)
if err != nil {
fmt.Printf(" ERROR: %v\n", err)
} else {
fmt.Printf(" Found %d serial ports\n", len(ports))
for i, port := range ports {
fmt.Printf(" Port %d: Token=%s, Type=%s\n", i+1, port.Token, port.Type)
}
}
// 5. Get Relay Outputs (using existing method).
fmt.Println("\n5. GetRelayOutputs")
relays, err := client.GetRelayOutputs(ctx)
if err != nil {
fmt.Printf(" ERROR: %v\n", err)
} else {
fmt.Printf(" Found %d relay outputs\n", len(relays))
for i, relay := range relays {
mode := notAvailable
idleState := notAvailable
if relay.Properties.Mode != "" {
mode = string(relay.Properties.Mode)
}
if relay.Properties.IdleState != "" {
idleState = string(relay.Properties.IdleState)
}
fmt.Printf(" Relay %d: Token=%s, Mode=%s, IdleState=%s\n",
i+1, relay.Token, mode, idleState)
}
}
}