Add ONVIF types and structures for device capabilities and configurations
- Introduced comprehensive data structures for ONVIF device information, capabilities, media profiles, and configurations. - Added types for device services, network settings, imaging options, audio/video configurations, and user management. - Implemented structures for handling various ONVIF features including PTZ control, event subscriptions, and analytics configurations. - Enhanced support for network protocols, security settings, and system logging.
This commit is contained in:
@@ -0,0 +1,235 @@
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user