Merge pull request #48 from 0x524a/46-feature-add-more-event-operations

46 feature add more event operations
This commit is contained in:
ProtoTess
2026-01-08 14:36:07 -05:00
committed by GitHub
12 changed files with 623 additions and 963 deletions
+1
View File
@@ -302,3 +302,4 @@ The library provides **complete coverage** of all essential ONVIF Media and Devi
*Camera: Bosch FLEXIDOME indoor 5100i IR (FW: 8.71.0066)*
+1
View File
@@ -101,3 +101,4 @@ New types added to `types.go`:
*Total Operations: 79/79 (100%)*
+1
View File
@@ -168,3 +168,4 @@ The library provides **complete coverage** of all essential ONVIF operations req
*Camera: Bosch FLEXIDOME indoor 5100i IR (FW: 8.71.0066)*
+1
View File
@@ -229,3 +229,4 @@ The missing operations are primarily **optional discovery and management operati
*Last Updated: December 1, 2025*
+1
View File
@@ -209,3 +209,4 @@ Implement Video Analytics and Audio Decoder operations if needed for specific us
*Last Updated: December 2, 2025*
+1 -6
View File
@@ -506,15 +506,10 @@ func extractParam(authHeader, param string) string {
}
func md5Hash(s string) string {
return fmt.Sprintf("%x", md5sum(s))
}
func md5sum(s string) interface{} {
// Use crypto/md5 - import it if not already present
h := md5.New() //nolint:gosec // MD5 required for ONVIF digest auth
h.Write([]byte(s))
return h.Sum(nil)
return hex.EncodeToString(h.Sum(nil))
}
// generateNonce generates a cryptographically secure random nonce for digest authentication.
+171 -253
View File
@@ -8,14 +8,73 @@ import (
"github.com/0x524a/onvif-go/internal/soap"
)
// Common XML request/response types for device security operations.
// These are defined at package level to avoid repeated inline struct definitions.
// ipAddressFilterRequest is the common structure for IP address filter SOAP requests.
type ipAddressFilterRequest struct {
Type string `xml:"tds:Type"`
IPv4Address []prefixedIPv4AddressXML `xml:"tds:IPv4Address,omitempty"`
IPv6Address []prefixedIPv6AddressXML `xml:"tds:IPv6Address,omitempty"`
}
// prefixedIPv4AddressXML is the XML representation of a prefixed IPv4 address.
type prefixedIPv4AddressXML struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
}
// prefixedIPv6AddressXML is the XML representation of a prefixed IPv6 address.
type prefixedIPv6AddressXML struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
}
// buildIPAddressFilterRequest converts an IPAddressFilter to the XML request format.
// Pre-allocates slices for efficiency when the source length is known.
func buildIPAddressFilterRequest(filter *IPAddressFilter) ipAddressFilterRequest {
req := ipAddressFilterRequest{
Type: string(filter.Type),
}
// Pre-allocate slices with known capacity
if len(filter.IPv4Address) > 0 {
req.IPv4Address = make([]prefixedIPv4AddressXML, 0, len(filter.IPv4Address))
for _, addr := range filter.IPv4Address {
req.IPv4Address = append(req.IPv4Address, prefixedIPv4AddressXML{
Address: addr.Address,
PrefixLength: addr.PrefixLength,
})
}
}
if len(filter.IPv6Address) > 0 {
req.IPv6Address = make([]prefixedIPv6AddressXML, 0, len(filter.IPv6Address))
for _, addr := range filter.IPv6Address {
req.IPv6Address = append(req.IPv6Address, prefixedIPv6AddressXML{
Address: addr.Address,
PrefixLength: addr.PrefixLength,
})
}
}
return req
}
// newSOAPClient creates a SOAP client with the current client credentials.
func (c *Client) newSOAPClient() *soap.Client {
username, password := c.GetCredentials()
return soap.NewClient(c.httpClient, username, password)
}
// GetRemoteUser returns the configured remote user.
func (c *Client) GetRemoteUser(ctx context.Context) (*RemoteUser, error) {
type GetRemoteUser struct {
type getRemoteUserRequest struct {
XMLName xml.Name `xml:"tds:GetRemoteUser"`
Xmlns string `xml:"xmlns:tds,attr"`
}
type GetRemoteUserResponse struct {
type getRemoteUserResponse struct {
XMLName xml.Name `xml:"GetRemoteUserResponse"`
RemoteUser *struct {
Username string `xml:"Username"`
@@ -24,16 +83,12 @@ func (c *Client) GetRemoteUser(ctx context.Context) (*RemoteUser, error) {
} `xml:"RemoteUser"`
}
req := GetRemoteUser{
req := getRemoteUserRequest{
Xmlns: deviceNamespace,
}
var resp GetRemoteUserResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, &resp); err != nil {
var resp getRemoteUserResponse
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, &resp); err != nil {
return nil, fmt.Errorf("GetRemoteUser failed: %w", err)
}
@@ -50,36 +105,31 @@ func (c *Client) GetRemoteUser(ctx context.Context) (*RemoteUser, error) {
// SetRemoteUser sets the remote user.
func (c *Client) SetRemoteUser(ctx context.Context, remoteUser *RemoteUser) error {
type SetRemoteUser struct {
XMLName xml.Name `xml:"tds:SetRemoteUser"`
Xmlns string `xml:"xmlns:tds,attr"`
RemoteUser *struct {
Username string `xml:"tds:Username"`
Password string `xml:"tds:Password,omitempty"`
UseDerivedPassword bool `xml:"tds:UseDerivedPassword"`
} `xml:"tds:RemoteUser,omitempty"`
type remoteUserXML struct {
Username string `xml:"tds:Username"`
Password string `xml:"tds:Password,omitempty"`
UseDerivedPassword bool `xml:"tds:UseDerivedPassword"`
}
req := SetRemoteUser{
type setRemoteUserRequest struct {
XMLName xml.Name `xml:"tds:SetRemoteUser"`
Xmlns string `xml:"xmlns:tds,attr"`
RemoteUser *remoteUserXML `xml:"tds:RemoteUser,omitempty"`
}
req := setRemoteUserRequest{
Xmlns: deviceNamespace,
}
if remoteUser != nil {
req.RemoteUser = &struct {
Username string `xml:"tds:Username"`
Password string `xml:"tds:Password,omitempty"`
UseDerivedPassword bool `xml:"tds:UseDerivedPassword"`
}{
req.RemoteUser = &remoteUserXML{
Username: remoteUser.Username,
Password: remoteUser.Password,
UseDerivedPassword: remoteUser.UseDerivedPassword,
}
}
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, nil); err != nil {
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, nil); err != nil {
return fmt.Errorf("SetRemoteUser failed: %w", err)
}
@@ -88,36 +138,31 @@ func (c *Client) SetRemoteUser(ctx context.Context, remoteUser *RemoteUser) erro
// GetIPAddressFilter gets the IP address filter settings from a device.
func (c *Client) GetIPAddressFilter(ctx context.Context) (*IPAddressFilter, error) {
type GetIPAddressFilter struct {
type getIPAddressFilterRequest struct {
XMLName xml.Name `xml:"tds:GetIPAddressFilter"`
Xmlns string `xml:"xmlns:tds,attr"`
}
type GetIPAddressFilterResponse struct {
type prefixedAddressXML struct {
Address string `xml:"Address"`
PrefixLength int `xml:"PrefixLength"`
}
type getIPAddressFilterResponse struct {
XMLName xml.Name `xml:"GetIPAddressFilterResponse"`
IPAddressFilter struct {
Type string `xml:"Type"`
IPv4Address []struct {
Address string `xml:"Address"`
PrefixLength int `xml:"PrefixLength"`
} `xml:"IPv4Address"`
IPv6Address []struct {
Address string `xml:"Address"`
PrefixLength int `xml:"PrefixLength"`
} `xml:"IPv6Address"`
Type string `xml:"Type"`
IPv4Address []prefixedAddressXML `xml:"IPv4Address"`
IPv6Address []prefixedAddressXML `xml:"IPv6Address"`
} `xml:"IPAddressFilter"`
}
req := GetIPAddressFilter{
req := getIPAddressFilterRequest{
Xmlns: deviceNamespace,
}
var resp GetIPAddressFilterResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, &resp); err != nil {
var resp getIPAddressFilterResponse
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, &resp); err != nil {
return nil, fmt.Errorf("GetIPAddressFilter failed: %w", err)
}
@@ -125,18 +170,25 @@ func (c *Client) GetIPAddressFilter(ctx context.Context) (*IPAddressFilter, erro
Type: IPAddressFilterType(resp.IPAddressFilter.Type),
}
for _, addr := range resp.IPAddressFilter.IPv4Address {
filter.IPv4Address = append(filter.IPv4Address, PrefixedIPv4Address{
Address: addr.Address,
PrefixLength: addr.PrefixLength,
})
// Pre-allocate slices with known capacity
if len(resp.IPAddressFilter.IPv4Address) > 0 {
filter.IPv4Address = make([]PrefixedIPv4Address, 0, len(resp.IPAddressFilter.IPv4Address))
for _, addr := range resp.IPAddressFilter.IPv4Address {
filter.IPv4Address = append(filter.IPv4Address, PrefixedIPv4Address{
Address: addr.Address,
PrefixLength: addr.PrefixLength,
})
}
}
for _, addr := range resp.IPAddressFilter.IPv6Address {
filter.IPv6Address = append(filter.IPv6Address, PrefixedIPv6Address{
Address: addr.Address,
PrefixLength: addr.PrefixLength,
})
if len(resp.IPAddressFilter.IPv6Address) > 0 {
filter.IPv6Address = make([]PrefixedIPv6Address, 0, len(resp.IPAddressFilter.IPv6Address))
for _, addr := range resp.IPAddressFilter.IPv6Address {
filter.IPv6Address = append(filter.IPv6Address, PrefixedIPv6Address{
Address: addr.Address,
PrefixLength: addr.PrefixLength,
})
}
}
return filter, nil
@@ -144,51 +196,18 @@ func (c *Client) GetIPAddressFilter(ctx context.Context) (*IPAddressFilter, erro
// SetIPAddressFilter sets the IP address filter settings on a device.
func (c *Client) SetIPAddressFilter(ctx context.Context, filter *IPAddressFilter) error {
type SetIPAddressFilter struct {
XMLName xml.Name `xml:"tds:SetIPAddressFilter"`
Xmlns string `xml:"xmlns:tds,attr"`
IPAddressFilter struct {
Type string `xml:"tds:Type"`
IPv4Address []struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
} `xml:"tds:IPv4Address,omitempty"`
IPv6Address []struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
} `xml:"tds:IPv6Address,omitempty"`
} `xml:"tds:IPAddressFilter"`
type setIPAddressFilterRequest struct {
XMLName xml.Name `xml:"tds:SetIPAddressFilter"`
Xmlns string `xml:"xmlns:tds,attr"`
IPAddressFilter ipAddressFilterRequest `xml:"tds:IPAddressFilter"`
}
req := SetIPAddressFilter{
Xmlns: deviceNamespace,
}
req.IPAddressFilter.Type = string(filter.Type)
for _, addr := range filter.IPv4Address {
req.IPAddressFilter.IPv4Address = append(req.IPAddressFilter.IPv4Address, struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
}{
Address: addr.Address,
PrefixLength: addr.PrefixLength,
})
req := setIPAddressFilterRequest{
Xmlns: deviceNamespace,
IPAddressFilter: buildIPAddressFilterRequest(filter),
}
for _, addr := range filter.IPv6Address {
req.IPAddressFilter.IPv6Address = append(req.IPAddressFilter.IPv6Address, struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
}{
Address: addr.Address,
PrefixLength: addr.PrefixLength,
})
}
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, nil); err != nil {
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, nil); err != nil {
return fmt.Errorf("SetIPAddressFilter failed: %w", err)
}
@@ -197,51 +216,18 @@ func (c *Client) SetIPAddressFilter(ctx context.Context, filter *IPAddressFilter
// AddIPAddressFilter adds an IP filter address to a device.
func (c *Client) AddIPAddressFilter(ctx context.Context, filter *IPAddressFilter) error {
type AddIPAddressFilter struct {
XMLName xml.Name `xml:"tds:AddIPAddressFilter"`
Xmlns string `xml:"xmlns:tds,attr"`
IPAddressFilter struct {
Type string `xml:"tds:Type"`
IPv4Address []struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
} `xml:"tds:IPv4Address,omitempty"`
IPv6Address []struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
} `xml:"tds:IPv6Address,omitempty"`
} `xml:"tds:IPAddressFilter"`
type addIPAddressFilterRequest struct {
XMLName xml.Name `xml:"tds:AddIPAddressFilter"`
Xmlns string `xml:"xmlns:tds,attr"`
IPAddressFilter ipAddressFilterRequest `xml:"tds:IPAddressFilter"`
}
req := AddIPAddressFilter{
Xmlns: deviceNamespace,
}
req.IPAddressFilter.Type = string(filter.Type)
for _, addr := range filter.IPv4Address {
req.IPAddressFilter.IPv4Address = append(req.IPAddressFilter.IPv4Address, struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
}{
Address: addr.Address,
PrefixLength: addr.PrefixLength,
})
req := addIPAddressFilterRequest{
Xmlns: deviceNamespace,
IPAddressFilter: buildIPAddressFilterRequest(filter),
}
for _, addr := range filter.IPv6Address {
req.IPAddressFilter.IPv6Address = append(req.IPAddressFilter.IPv6Address, struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
}{
Address: addr.Address,
PrefixLength: addr.PrefixLength,
})
}
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, nil); err != nil {
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, nil); err != nil {
return fmt.Errorf("AddIPAddressFilter failed: %w", err)
}
@@ -250,51 +236,18 @@ func (c *Client) AddIPAddressFilter(ctx context.Context, filter *IPAddressFilter
// RemoveIPAddressFilter deletes an IP filter address from a device.
func (c *Client) RemoveIPAddressFilter(ctx context.Context, filter *IPAddressFilter) error {
type RemoveIPAddressFilter struct {
XMLName xml.Name `xml:"tds:RemoveIPAddressFilter"`
Xmlns string `xml:"xmlns:tds,attr"`
IPAddressFilter struct {
Type string `xml:"tds:Type"`
IPv4Address []struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
} `xml:"tds:IPv4Address,omitempty"`
IPv6Address []struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
} `xml:"tds:IPv6Address,omitempty"`
} `xml:"tds:IPAddressFilter"`
type removeIPAddressFilterRequest struct {
XMLName xml.Name `xml:"tds:RemoveIPAddressFilter"`
Xmlns string `xml:"xmlns:tds,attr"`
IPAddressFilter ipAddressFilterRequest `xml:"tds:IPAddressFilter"`
}
req := RemoveIPAddressFilter{
Xmlns: deviceNamespace,
}
req.IPAddressFilter.Type = string(filter.Type)
for _, addr := range filter.IPv4Address {
req.IPAddressFilter.IPv4Address = append(req.IPAddressFilter.IPv4Address, struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
}{
Address: addr.Address,
PrefixLength: addr.PrefixLength,
})
req := removeIPAddressFilterRequest{
Xmlns: deviceNamespace,
IPAddressFilter: buildIPAddressFilterRequest(filter),
}
for _, addr := range filter.IPv6Address {
req.IPAddressFilter.IPv6Address = append(req.IPAddressFilter.IPv6Address, struct {
Address string `xml:"tds:Address"`
PrefixLength int `xml:"tds:PrefixLength"`
}{
Address: addr.Address,
PrefixLength: addr.PrefixLength,
})
}
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, nil); err != nil {
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, nil); err != nil {
return fmt.Errorf("RemoveIPAddressFilter failed: %w", err)
}
@@ -303,12 +256,12 @@ func (c *Client) RemoveIPAddressFilter(ctx context.Context, filter *IPAddressFil
// GetZeroConfiguration gets the zero-configuration from a device.
func (c *Client) GetZeroConfiguration(ctx context.Context) (*NetworkZeroConfiguration, error) {
type GetZeroConfiguration struct {
type getZeroConfigurationRequest struct {
XMLName xml.Name `xml:"tds:GetZeroConfiguration"`
Xmlns string `xml:"xmlns:tds,attr"`
}
type GetZeroConfigurationResponse struct {
type getZeroConfigurationResponse struct {
XMLName xml.Name `xml:"GetZeroConfigurationResponse"`
ZeroConfiguration struct {
InterfaceToken string `xml:"InterfaceToken"`
@@ -317,16 +270,12 @@ func (c *Client) GetZeroConfiguration(ctx context.Context) (*NetworkZeroConfigur
} `xml:"ZeroConfiguration"`
}
req := GetZeroConfiguration{
req := getZeroConfigurationRequest{
Xmlns: deviceNamespace,
}
var resp GetZeroConfigurationResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, &resp); err != nil {
var resp getZeroConfigurationResponse
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, &resp); err != nil {
return nil, fmt.Errorf("GetZeroConfiguration failed: %w", err)
}
@@ -339,23 +288,20 @@ func (c *Client) GetZeroConfiguration(ctx context.Context) (*NetworkZeroConfigur
// SetZeroConfiguration sets the zero-configuration.
func (c *Client) SetZeroConfiguration(ctx context.Context, interfaceToken string, enabled bool) error {
type SetZeroConfiguration struct {
type setZeroConfigurationRequest struct {
XMLName xml.Name `xml:"tds:SetZeroConfiguration"`
Xmlns string `xml:"xmlns:tds,attr"`
InterfaceToken string `xml:"tds:InterfaceToken"`
Enabled bool `xml:"tds:Enabled"`
}
req := SetZeroConfiguration{
req := setZeroConfigurationRequest{
Xmlns: deviceNamespace,
InterfaceToken: interfaceToken,
Enabled: enabled,
}
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, nil); err != nil {
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, nil); err != nil {
return fmt.Errorf("SetZeroConfiguration failed: %w", err)
}
@@ -364,12 +310,12 @@ func (c *Client) SetZeroConfiguration(ctx context.Context, interfaceToken string
// GetDynamicDNS gets the dynamic DNS settings from a device.
func (c *Client) GetDynamicDNS(ctx context.Context) (*DynamicDNSInformation, error) {
type GetDynamicDNS struct {
type getDynamicDNSRequest struct {
XMLName xml.Name `xml:"tds:GetDynamicDNS"`
Xmlns string `xml:"xmlns:tds,attr"`
}
type GetDynamicDNSResponse struct {
type getDynamicDNSResponse struct {
XMLName xml.Name `xml:"GetDynamicDNSResponse"`
DynamicDNSInformation struct {
Type string `xml:"Type"`
@@ -378,16 +324,12 @@ func (c *Client) GetDynamicDNS(ctx context.Context) (*DynamicDNSInformation, err
} `xml:"DynamicDNSInformation"`
}
req := GetDynamicDNS{
req := getDynamicDNSRequest{
Xmlns: deviceNamespace,
}
var resp GetDynamicDNSResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, &resp); err != nil {
var resp getDynamicDNSResponse
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, &resp); err != nil {
return nil, fmt.Errorf("GetDynamicDNS failed: %w", err)
}
@@ -400,23 +342,20 @@ func (c *Client) GetDynamicDNS(ctx context.Context) (*DynamicDNSInformation, err
// SetDynamicDNS sets the dynamic DNS settings on a device.
func (c *Client) SetDynamicDNS(ctx context.Context, dnsType DynamicDNSType, name string) error {
type SetDynamicDNS struct {
type setDynamicDNSRequest struct {
XMLName xml.Name `xml:"tds:SetDynamicDNS"`
Xmlns string `xml:"xmlns:tds,attr"`
Type DynamicDNSType `xml:"tds:Type"`
Name string `xml:"tds:Name,omitempty"`
}
req := SetDynamicDNS{
req := setDynamicDNSRequest{
Xmlns: deviceNamespace,
Type: dnsType,
Name: name,
}
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, nil); err != nil {
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, nil); err != nil {
return fmt.Errorf("SetDynamicDNS failed: %w", err)
}
@@ -425,12 +364,12 @@ func (c *Client) SetDynamicDNS(ctx context.Context, dnsType DynamicDNSType, name
// GetPasswordComplexityConfiguration retrieves the current password complexity configuration settings.
func (c *Client) GetPasswordComplexityConfiguration(ctx context.Context) (*PasswordComplexityConfiguration, error) {
type GetPasswordComplexityConfiguration struct {
type getPasswordComplexityConfigurationRequest struct {
XMLName xml.Name `xml:"tds:GetPasswordComplexityConfiguration"`
Xmlns string `xml:"xmlns:tds,attr"`
}
type GetPasswordComplexityConfigurationResponse struct {
type getPasswordComplexityConfigurationResponse struct {
XMLName xml.Name `xml:"GetPasswordComplexityConfigurationResponse"`
MinLen int `xml:"MinLen"`
Uppercase int `xml:"Uppercase"`
@@ -440,16 +379,12 @@ func (c *Client) GetPasswordComplexityConfiguration(ctx context.Context) (*Passw
PolicyConfigurationLocked bool `xml:"PolicyConfigurationLocked"`
}
req := GetPasswordComplexityConfiguration{
req := getPasswordComplexityConfigurationRequest{
Xmlns: deviceNamespace,
}
var resp GetPasswordComplexityConfigurationResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, &resp); err != nil {
var resp getPasswordComplexityConfigurationResponse
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, &resp); err != nil {
return nil, fmt.Errorf("GetPasswordComplexityConfiguration failed: %w", err)
}
@@ -468,7 +403,7 @@ func (c *Client) SetPasswordComplexityConfiguration(
ctx context.Context,
config *PasswordComplexityConfiguration,
) error {
type SetPasswordComplexityConfiguration struct {
type setPasswordComplexityConfigurationRequest struct {
XMLName xml.Name `xml:"tds:SetPasswordComplexityConfiguration"`
Xmlns string `xml:"xmlns:tds,attr"`
MinLen int `xml:"tds:MinLen,omitempty"`
@@ -479,7 +414,7 @@ func (c *Client) SetPasswordComplexityConfiguration(
PolicyConfigurationLocked bool `xml:"tds:PolicyConfigurationLocked,omitempty"`
}
req := SetPasswordComplexityConfiguration{
req := setPasswordComplexityConfigurationRequest{
Xmlns: deviceNamespace,
MinLen: config.MinLen,
Uppercase: config.Uppercase,
@@ -489,10 +424,7 @@ func (c *Client) SetPasswordComplexityConfiguration(
PolicyConfigurationLocked: config.PolicyConfigurationLocked,
}
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, nil); err != nil {
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, nil); err != nil {
return fmt.Errorf("SetPasswordComplexityConfiguration failed: %w", err)
}
@@ -501,27 +433,23 @@ func (c *Client) SetPasswordComplexityConfiguration(
// GetPasswordHistoryConfiguration retrieves the current password history configuration settings.
func (c *Client) GetPasswordHistoryConfiguration(ctx context.Context) (*PasswordHistoryConfiguration, error) {
type GetPasswordHistoryConfiguration struct {
type getPasswordHistoryConfigurationRequest struct {
XMLName xml.Name `xml:"tds:GetPasswordHistoryConfiguration"`
Xmlns string `xml:"xmlns:tds,attr"`
}
type GetPasswordHistoryConfigurationResponse struct {
type getPasswordHistoryConfigurationResponse struct {
XMLName xml.Name `xml:"GetPasswordHistoryConfigurationResponse"`
Enabled bool `xml:"Enabled"`
Length int `xml:"Length"`
}
req := GetPasswordHistoryConfiguration{
req := getPasswordHistoryConfigurationRequest{
Xmlns: deviceNamespace,
}
var resp GetPasswordHistoryConfigurationResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, &resp); err != nil {
var resp getPasswordHistoryConfigurationResponse
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, &resp); err != nil {
return nil, fmt.Errorf("GetPasswordHistoryConfiguration failed: %w", err)
}
@@ -533,23 +461,20 @@ func (c *Client) GetPasswordHistoryConfiguration(ctx context.Context) (*Password
// SetPasswordHistoryConfiguration allows setting of the password history configuration.
func (c *Client) SetPasswordHistoryConfiguration(ctx context.Context, config *PasswordHistoryConfiguration) error {
type SetPasswordHistoryConfiguration struct {
type setPasswordHistoryConfigurationRequest struct {
XMLName xml.Name `xml:"tds:SetPasswordHistoryConfiguration"`
Xmlns string `xml:"xmlns:tds,attr"`
Enabled bool `xml:"tds:Enabled"`
Length int `xml:"tds:Length"`
}
req := SetPasswordHistoryConfiguration{
req := setPasswordHistoryConfigurationRequest{
Xmlns: deviceNamespace,
Enabled: config.Enabled,
Length: config.Length,
}
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, nil); err != nil {
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, nil); err != nil {
return fmt.Errorf("SetPasswordHistoryConfiguration failed: %w", err)
}
@@ -558,28 +483,24 @@ func (c *Client) SetPasswordHistoryConfiguration(ctx context.Context, config *Pa
// GetAuthFailureWarningConfiguration retrieves the current authentication failure warning configuration.
func (c *Client) GetAuthFailureWarningConfiguration(ctx context.Context) (*AuthFailureWarningConfiguration, error) {
type GetAuthFailureWarningConfiguration struct {
type getAuthFailureWarningConfigurationRequest struct {
XMLName xml.Name `xml:"tds:GetAuthFailureWarningConfiguration"`
Xmlns string `xml:"xmlns:tds,attr"`
}
type GetAuthFailureWarningConfigurationResponse struct {
type getAuthFailureWarningConfigurationResponse struct {
XMLName xml.Name `xml:"GetAuthFailureWarningConfigurationResponse"`
Enabled bool `xml:"Enabled"`
MonitorPeriod int `xml:"MonitorPeriod"`
MaxAuthFailures int `xml:"MaxAuthFailures"`
}
req := GetAuthFailureWarningConfiguration{
req := getAuthFailureWarningConfigurationRequest{
Xmlns: deviceNamespace,
}
var resp GetAuthFailureWarningConfigurationResponse
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, &resp); err != nil {
var resp getAuthFailureWarningConfigurationResponse
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, &resp); err != nil {
return nil, fmt.Errorf("GetAuthFailureWarningConfiguration failed: %w", err)
}
@@ -595,7 +516,7 @@ func (c *Client) SetAuthFailureWarningConfiguration(
ctx context.Context,
config *AuthFailureWarningConfiguration,
) error {
type SetAuthFailureWarningConfiguration struct {
type setAuthFailureWarningConfigurationRequest struct {
XMLName xml.Name `xml:"tds:SetAuthFailureWarningConfiguration"`
Xmlns string `xml:"xmlns:tds,attr"`
Enabled bool `xml:"tds:Enabled"`
@@ -603,17 +524,14 @@ func (c *Client) SetAuthFailureWarningConfiguration(
MaxAuthFailures int `xml:"tds:MaxAuthFailures"`
}
req := SetAuthFailureWarningConfiguration{
req := setAuthFailureWarningConfigurationRequest{
Xmlns: deviceNamespace,
Enabled: config.Enabled,
MonitorPeriod: config.MonitorPeriod,
MaxAuthFailures: config.MaxAuthFailures,
}
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, c.endpoint, "", req, nil); err != nil {
if err := c.newSOAPClient().Call(ctx, c.endpoint, "", req, nil); err != nil {
return fmt.Errorf("SetAuthFailureWarningConfiguration failed: %w", err)
}
+263
View File
@@ -521,3 +521,266 @@ func TestIPAddressFilterTypeConstants(t *testing.T) {
t.Errorf("IPAddressFilterDeny should be 'Deny', got %s", IPAddressFilterDeny)
}
}
// Benchmarks for device security operations.
func BenchmarkGetRemoteUser(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = client.GetRemoteUser(ctx)
}
}
func BenchmarkSetRemoteUser(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
remoteUser := &RemoteUser{
Username: "test_user",
Password: "password123",
UseDerivedPassword: true,
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = client.SetRemoteUser(ctx, remoteUser)
}
}
func BenchmarkGetIPAddressFilter(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = client.GetIPAddressFilter(ctx)
}
}
func BenchmarkSetIPAddressFilter(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
filter := &IPAddressFilter{
Type: IPAddressFilterAllow,
IPv4Address: []PrefixedIPv4Address{
{Address: "192.168.1.0", PrefixLength: 24},
{Address: "10.0.0.0", PrefixLength: 8},
},
IPv6Address: []PrefixedIPv6Address{
{Address: "fe80::", PrefixLength: 64},
},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = client.SetIPAddressFilter(ctx, filter)
}
}
func BenchmarkAddIPAddressFilter(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
filter := &IPAddressFilter{
Type: IPAddressFilterAllow,
IPv4Address: []PrefixedIPv4Address{
{Address: "172.16.0.0", PrefixLength: 12},
},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = client.AddIPAddressFilter(ctx, filter)
}
}
func BenchmarkRemoveIPAddressFilter(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
filter := &IPAddressFilter{
Type: IPAddressFilterAllow,
IPv4Address: []PrefixedIPv4Address{
{Address: "172.16.0.0", PrefixLength: 12},
},
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = client.RemoveIPAddressFilter(ctx, filter)
}
}
func BenchmarkGetZeroConfiguration(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = client.GetZeroConfiguration(ctx)
}
}
func BenchmarkSetZeroConfiguration(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = client.SetZeroConfiguration(ctx, "eth0", true)
}
}
func BenchmarkGetPasswordComplexityConfiguration(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = client.GetPasswordComplexityConfiguration(ctx)
}
}
func BenchmarkSetPasswordComplexityConfiguration(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
config := &PasswordComplexityConfiguration{
MinLen: 10,
Uppercase: 2,
Number: 2,
SpecialChars: 1,
BlockUsernameOccurrence: true,
PolicyConfigurationLocked: false,
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = client.SetPasswordComplexityConfiguration(ctx, config)
}
}
func BenchmarkGetPasswordHistoryConfiguration(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = client.GetPasswordHistoryConfiguration(ctx)
}
}
func BenchmarkSetPasswordHistoryConfiguration(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
config := &PasswordHistoryConfiguration{
Enabled: true,
Length: 10,
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = client.SetPasswordHistoryConfiguration(ctx, config)
}
}
func BenchmarkGetAuthFailureWarningConfiguration(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
b.ResetTimer()
for i := 0; i < b.N; i++ {
_, _ = client.GetAuthFailureWarningConfiguration(ctx)
}
}
func BenchmarkSetAuthFailureWarningConfiguration(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
config := &AuthFailureWarningConfiguration{
Enabled: true,
MonitorPeriod: 120,
MaxAuthFailures: 3,
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = client.SetAuthFailureWarningConfiguration(ctx, config)
}
}
// BenchmarkIPAddressFilterWithManyAddresses tests performance with larger address lists.
func BenchmarkIPAddressFilterWithManyAddresses(b *testing.B) {
server := newMockDeviceSecurityServer()
defer server.Close()
client, _ := NewClient(server.URL)
ctx := context.Background()
// Create filter with many addresses to test pre-allocation efficiency
filter := &IPAddressFilter{
Type: IPAddressFilterAllow,
IPv4Address: make([]PrefixedIPv4Address, 100),
IPv6Address: make([]PrefixedIPv6Address, 50),
}
for i := 0; i < 100; i++ {
filter.IPv4Address[i] = PrefixedIPv4Address{
Address: "192.168.1.0",
PrefixLength: 24,
}
}
for i := 0; i < 50; i++ {
filter.IPv6Address[i] = PrefixedIPv6Address{
Address: "fe80::",
PrefixLength: 64,
}
}
b.ResetTimer()
for i := 0; i < b.N; i++ {
_ = client.SetIPAddressFilter(ctx, filter)
}
}
+9 -5
View File
@@ -227,12 +227,16 @@ func deviceMapToSlice(m map[string]*Device) []*Device {
// generateUUID generates a simple UUID (not cryptographically secure).
func generateUUID() string {
now := time.Now()
nanos := now.UnixNano()
secs := now.Unix()
return fmt.Sprintf("%d-%d-%d-%d-%d",
time.Now().UnixNano(),
time.Now().Unix(),
time.Now().UnixNano()%uuidMod1000,
time.Now().Unix()%uuidMod1000,
time.Now().UnixNano()%uuidMod10000)
nanos,
secs,
nanos%uuidMod1000,
secs%uuidMod1000,
nanos%uuidMod10000)
}
// resolveNetworkInterface resolves a network interface by name or IP address.
+2 -24
View File
@@ -5,6 +5,7 @@ import (
"encoding/xml"
"errors"
"fmt"
"strings"
"time"
"github.com/0x524a/onvif-go/internal/soap"
@@ -751,28 +752,5 @@ func splitSpaceSeparated(s string) []string {
return nil
}
var result []string
start := 0
inWord := false
for i, r := range s {
if r == ' ' || r == '\t' {
if inWord {
result = append(result, s[start:i])
inWord = false
}
} else {
if !inWord {
start = i
inWord = true
}
}
}
if inWord {
result = append(result, s[start:])
}
return result
return strings.Fields(s)
}
+86 -329
View File
@@ -20,21 +20,11 @@ func (c *Client) getMediaEndpoint() string {
return c.endpoint
}
// getMediaSoapClient creates a new SOAP client for media operations.
func (c *Client) getMediaSoapClient() *soap.Client {
username, password := c.GetCredentials()
return soap.NewClient(c.httpClient, username, password)
}
// GetProfiles retrieves all media profiles.
//
//nolint:funlen // GetProfiles has many statements due to parsing complex profile structures
func (c *Client) GetProfiles(ctx context.Context) ([]*Profile, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetProfiles struct {
XMLName xml.Name `xml:"trt:GetProfiles"`
@@ -160,10 +150,7 @@ func (c *Client) GetProfiles(ctx context.Context) ([]*Profile, error) {
// GetStreamURI retrieves the stream URI for a profile.
func (c *Client) GetStreamURI(ctx context.Context, profileToken string) (*MediaURI, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetStreamURI struct {
XMLName xml.Name `xml:"trt:GetStreamUri"`
@@ -214,10 +201,7 @@ func (c *Client) GetStreamURI(ctx context.Context, profileToken string) (*MediaU
// GetSnapshotURI retrieves the snapshot URI for a profile.
func (c *Client) GetSnapshotURI(ctx context.Context, profileToken string) (*MediaURI, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetSnapshotURI struct {
XMLName xml.Name `xml:"trt:GetSnapshotUri"`
@@ -261,10 +245,7 @@ func (c *Client) GetVideoEncoderConfiguration(
ctx context.Context,
configurationToken string,
) (*VideoEncoderConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetVideoEncoderConfiguration struct {
XMLName xml.Name `xml:"trt:GetVideoEncoderConfiguration"`
@@ -334,10 +315,7 @@ func (c *Client) GetVideoEncoderConfiguration(
// GetVideoSources retrieves all video sources.
func (c *Client) GetVideoSources(ctx context.Context) ([]*VideoSource, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetVideoSources struct {
XMLName xml.Name `xml:"trt:GetVideoSources"`
@@ -386,10 +364,7 @@ func (c *Client) GetVideoSources(ctx context.Context) ([]*VideoSource, error) {
// GetAudioSources retrieves all audio sources.
func (c *Client) GetAudioSources(ctx context.Context) ([]*AudioSource, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetAudioSources struct {
XMLName xml.Name `xml:"trt:GetAudioSources"`
@@ -430,10 +405,7 @@ func (c *Client) GetAudioSources(ctx context.Context) ([]*AudioSource, error) {
// GetAudioOutputs retrieves all audio outputs.
func (c *Client) GetAudioOutputs(ctx context.Context) ([]*AudioOutput, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetAudioOutputs struct {
XMLName xml.Name `xml:"trt:GetAudioOutputs"`
@@ -472,10 +444,7 @@ func (c *Client) GetAudioOutputs(ctx context.Context) ([]*AudioOutput, error) {
// CreateProfile creates a new media profile.
func (c *Client) CreateProfile(ctx context.Context, name, token string) (*Profile, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type CreateProfile struct {
XMLName xml.Name `xml:"trt:CreateProfile"`
@@ -517,10 +486,7 @@ func (c *Client) CreateProfile(ctx context.Context, name, token string) (*Profil
// DeleteProfile deletes a media profile.
func (c *Client) DeleteProfile(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type DeleteProfile struct {
XMLName xml.Name `xml:"trt:DeleteProfile"`
@@ -549,10 +515,7 @@ func (c *Client) SetVideoEncoderConfiguration(
config *VideoEncoderConfiguration,
forcePersistence bool,
) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type SetVideoEncoderConfiguration struct {
XMLName xml.Name `xml:"trt:SetVideoEncoderConfiguration"`
@@ -626,10 +589,7 @@ func (c *Client) SetVideoEncoderConfiguration(
// GetMediaServiceCapabilities retrieves media service capabilities.
func (c *Client) GetMediaServiceCapabilities(ctx context.Context) (*MediaServiceCapabilities, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetServiceCapabilities struct {
XMLName xml.Name `xml:"trt:GetServiceCapabilities"`
@@ -697,10 +657,7 @@ func (c *Client) GetMediaServiceCapabilities(ctx context.Context) (*MediaService
func (c *Client) GetVideoEncoderConfigurationOptions(
ctx context.Context, configurationToken string,
) (*VideoEncoderConfigurationOptions, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetVideoEncoderConfigurationOptions struct {
XMLName xml.Name `xml:"trt:GetVideoEncoderConfigurationOptions"`
@@ -839,10 +796,7 @@ func (c *Client) GetAudioEncoderConfiguration(
ctx context.Context,
configurationToken string,
) (*AudioEncoderConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetAudioEncoderConfiguration struct {
XMLName xml.Name `xml:"trt:GetAudioEncoderConfiguration"`
@@ -920,10 +874,7 @@ func (c *Client) SetAudioEncoderConfiguration(
config *AudioEncoderConfiguration,
forcePersistence bool,
) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type SetAudioEncoderConfiguration struct {
XMLName xml.Name `xml:"trt:SetAudioEncoderConfiguration"`
@@ -1011,10 +962,7 @@ func (c *Client) GetMetadataConfiguration(
ctx context.Context,
configurationToken string,
) (*MetadataConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetMetadataConfiguration struct {
XMLName xml.Name `xml:"trt:GetMetadataConfiguration"`
@@ -1104,10 +1052,7 @@ func (c *Client) SetMetadataConfiguration(
config *MetadataConfiguration,
forcePersistence bool,
) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type SetMetadataConfiguration struct {
XMLName xml.Name `xml:"trt:SetMetadataConfiguration"`
@@ -1203,10 +1148,7 @@ func (c *Client) SetMetadataConfiguration(
// GetVideoSourceModes retrieves available video source modes.
func (c *Client) GetVideoSourceModes(ctx context.Context, videoSourceToken string) ([]*VideoSourceMode, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetVideoSourceModes struct {
XMLName xml.Name `xml:"trt:GetVideoSourceModes"`
@@ -1257,10 +1199,7 @@ func (c *Client) GetVideoSourceModes(ctx context.Context, videoSourceToken strin
// SetVideoSourceMode sets the video source mode.
func (c *Client) SetVideoSourceMode(ctx context.Context, videoSourceToken, modeToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type SetVideoSourceMode struct {
XMLName xml.Name `xml:"trt:SetVideoSourceMode"`
@@ -1287,10 +1226,7 @@ func (c *Client) SetVideoSourceMode(ctx context.Context, videoSourceToken, modeT
// SetSynchronizationPoint sets a synchronization point for the stream.
func (c *Client) SetSynchronizationPoint(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type SetSynchronizationPoint struct {
XMLName xml.Name `xml:"trt:SetSynchronizationPoint"`
@@ -1315,10 +1251,7 @@ func (c *Client) SetSynchronizationPoint(ctx context.Context, profileToken strin
// GetOSDs retrieves all OSD configurations.
func (c *Client) GetOSDs(ctx context.Context, configurationToken string) ([]*OSDConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetOSDs struct {
XMLName xml.Name `xml:"trt:GetOSDs"`
@@ -1361,10 +1294,7 @@ func (c *Client) GetOSDs(ctx context.Context, configurationToken string) ([]*OSD
// GetOSD retrieves a specific OSD configuration.
func (c *Client) GetOSD(ctx context.Context, osdToken string) (*OSDConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetOSD struct {
XMLName xml.Name `xml:"trt:GetOSD"`
@@ -1400,10 +1330,7 @@ func (c *Client) GetOSD(ctx context.Context, osdToken string) (*OSDConfiguration
// SetOSD sets OSD configuration.
func (c *Client) SetOSD(ctx context.Context, osd *OSDConfiguration) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type SetOSD struct {
XMLName xml.Name `xml:"trt:SetOSD"`
@@ -1436,10 +1363,7 @@ func (c *Client) CreateOSD(
videoSourceConfigurationToken string,
osd *OSDConfiguration,
) (*OSDConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type CreateOSD struct {
XMLName xml.Name `xml:"trt:CreateOSD"`
@@ -1483,10 +1407,7 @@ func (c *Client) CreateOSD(
// DeleteOSD deletes an OSD configuration.
func (c *Client) DeleteOSD(ctx context.Context, osdToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type DeleteOSD struct {
XMLName xml.Name `xml:"trt:DeleteOSD"`
@@ -1511,10 +1432,7 @@ func (c *Client) DeleteOSD(ctx context.Context, osdToken string) error {
// StartMulticastStreaming starts multicast streaming.
func (c *Client) StartMulticastStreaming(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type StartMulticastStreaming struct {
XMLName xml.Name `xml:"trt:StartMulticastStreaming"`
@@ -1539,10 +1457,7 @@ func (c *Client) StartMulticastStreaming(ctx context.Context, profileToken strin
// StopMulticastStreaming stops multicast streaming.
func (c *Client) StopMulticastStreaming(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type StopMulticastStreaming struct {
XMLName xml.Name `xml:"trt:StopMulticastStreaming"`
@@ -1567,10 +1482,7 @@ func (c *Client) StopMulticastStreaming(ctx context.Context, profileToken string
// GetProfile retrieves a specific media profile.
func (c *Client) GetProfile(ctx context.Context, profileToken string) (*Profile, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetProfile struct {
XMLName xml.Name `xml:"trt:GetProfile"`
@@ -1608,10 +1520,7 @@ func (c *Client) GetProfile(ctx context.Context, profileToken string) (*Profile,
// SetProfile sets profile configuration.
func (c *Client) SetProfile(ctx context.Context, profile *Profile) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type SetProfile struct {
XMLName xml.Name `xml:"trt:SetProfile"`
@@ -1642,10 +1551,7 @@ func (c *Client) SetProfile(ctx context.Context, profile *Profile) error {
// AddVideoEncoderConfiguration adds video encoder configuration to a profile.
func (c *Client) AddVideoEncoderConfiguration(ctx context.Context, profileToken, configurationToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type AddVideoEncoderConfiguration struct {
XMLName xml.Name `xml:"trt:AddVideoEncoderConfiguration"`
@@ -1672,10 +1578,7 @@ func (c *Client) AddVideoEncoderConfiguration(ctx context.Context, profileToken,
// RemoveVideoEncoderConfiguration removes video encoder configuration from a profile.
func (c *Client) RemoveVideoEncoderConfiguration(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type RemoveVideoEncoderConfiguration struct {
XMLName xml.Name `xml:"trt:RemoveVideoEncoderConfiguration"`
@@ -1700,10 +1603,7 @@ func (c *Client) RemoveVideoEncoderConfiguration(ctx context.Context, profileTok
// AddAudioEncoderConfiguration adds audio encoder configuration to a profile.
func (c *Client) AddAudioEncoderConfiguration(ctx context.Context, profileToken, configurationToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type AddAudioEncoderConfiguration struct {
XMLName xml.Name `xml:"trt:AddAudioEncoderConfiguration"`
@@ -1730,10 +1630,7 @@ func (c *Client) AddAudioEncoderConfiguration(ctx context.Context, profileToken,
// RemoveAudioEncoderConfiguration removes audio encoder configuration from a profile.
func (c *Client) RemoveAudioEncoderConfiguration(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type RemoveAudioEncoderConfiguration struct {
XMLName xml.Name `xml:"trt:RemoveAudioEncoderConfiguration"`
@@ -1758,10 +1655,7 @@ func (c *Client) RemoveAudioEncoderConfiguration(ctx context.Context, profileTok
// AddAudioSourceConfiguration adds audio source configuration to a profile.
func (c *Client) AddAudioSourceConfiguration(ctx context.Context, profileToken, configurationToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type AddAudioSourceConfiguration struct {
XMLName xml.Name `xml:"trt:AddAudioSourceConfiguration"`
@@ -1788,10 +1682,7 @@ func (c *Client) AddAudioSourceConfiguration(ctx context.Context, profileToken,
// RemoveAudioSourceConfiguration removes audio source configuration from a profile.
func (c *Client) RemoveAudioSourceConfiguration(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type RemoveAudioSourceConfiguration struct {
XMLName xml.Name `xml:"trt:RemoveAudioSourceConfiguration"`
@@ -1816,10 +1707,7 @@ func (c *Client) RemoveAudioSourceConfiguration(ctx context.Context, profileToke
// AddVideoSourceConfiguration adds video source configuration to a profile.
func (c *Client) AddVideoSourceConfiguration(ctx context.Context, profileToken, configurationToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type AddVideoSourceConfiguration struct {
XMLName xml.Name `xml:"trt:AddVideoSourceConfiguration"`
@@ -1846,10 +1734,7 @@ func (c *Client) AddVideoSourceConfiguration(ctx context.Context, profileToken,
// RemoveVideoSourceConfiguration removes video source configuration from a profile.
func (c *Client) RemoveVideoSourceConfiguration(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type RemoveVideoSourceConfiguration struct {
XMLName xml.Name `xml:"trt:RemoveVideoSourceConfiguration"`
@@ -1874,10 +1759,7 @@ func (c *Client) RemoveVideoSourceConfiguration(ctx context.Context, profileToke
// AddPTZConfiguration adds PTZ configuration to a profile.
func (c *Client) AddPTZConfiguration(ctx context.Context, profileToken, configurationToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type AddPTZConfiguration struct {
XMLName xml.Name `xml:"trt:AddPTZConfiguration"`
@@ -1904,10 +1786,7 @@ func (c *Client) AddPTZConfiguration(ctx context.Context, profileToken, configur
// RemovePTZConfiguration removes PTZ configuration from a profile.
func (c *Client) RemovePTZConfiguration(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type RemovePTZConfiguration struct {
XMLName xml.Name `xml:"trt:RemovePTZConfiguration"`
@@ -1932,10 +1811,7 @@ func (c *Client) RemovePTZConfiguration(ctx context.Context, profileToken string
// AddMetadataConfiguration adds metadata configuration to a profile.
func (c *Client) AddMetadataConfiguration(ctx context.Context, profileToken, configurationToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type AddMetadataConfiguration struct {
XMLName xml.Name `xml:"trt:AddMetadataConfiguration"`
@@ -1962,10 +1838,7 @@ func (c *Client) AddMetadataConfiguration(ctx context.Context, profileToken, con
// RemoveMetadataConfiguration removes metadata configuration from a profile.
func (c *Client) RemoveMetadataConfiguration(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type RemoveMetadataConfiguration struct {
XMLName xml.Name `xml:"trt:RemoveMetadataConfiguration"`
@@ -1993,10 +1866,7 @@ func (c *Client) GetAudioEncoderConfigurationOptions(
ctx context.Context,
configurationToken, profileToken string,
) (*AudioEncoderConfigurationOptions, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetAudioEncoderConfigurationOptions struct {
XMLName xml.Name `xml:"trt:GetAudioEncoderConfigurationOptions"`
@@ -2045,10 +1915,7 @@ func (c *Client) GetMetadataConfigurationOptions(
ctx context.Context,
configurationToken, profileToken string,
) (*MetadataConfigurationOptions, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetMetadataConfigurationOptions struct {
XMLName xml.Name `xml:"trt:GetMetadataConfigurationOptions"`
@@ -2124,7 +1991,9 @@ func (c *Client) GetAudioOutputConfiguration(ctx context.Context, configurationT
}
var resp GetAudioOutputConfigurationResponse
soapClient := c.getMediaSoapClient()
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil {
return nil, fmt.Errorf("GetAudioOutputConfiguration failed: %w", err)
@@ -2140,10 +2009,7 @@ func (c *Client) GetAudioOutputConfiguration(ctx context.Context, configurationT
// SetAudioOutputConfiguration sets audio output configuration.
func (c *Client) SetAudioOutputConfiguration(ctx context.Context, config *AudioOutputConfiguration, forcePersistence bool) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type SetAudioOutputConfiguration struct {
XMLName xml.Name `xml:"trt:SetAudioOutputConfiguration"`
@@ -2184,10 +2050,7 @@ func (c *Client) GetAudioOutputConfigurationOptions(
ctx context.Context,
configurationToken string,
) (*AudioOutputConfigurationOptions, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetAudioOutputConfigurationOptions struct {
XMLName xml.Name `xml:"trt:GetAudioOutputConfigurationOptions"`
@@ -2228,10 +2091,7 @@ func (c *Client) GetAudioDecoderConfigurationOptions(
ctx context.Context,
configurationToken string,
) (*AudioDecoderConfigurationOptions, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetAudioDecoderConfigurationOptions struct {
XMLName xml.Name `xml:"trt:GetAudioDecoderConfigurationOptions"`
@@ -2297,10 +2157,7 @@ func (c *Client) GetGuaranteedNumberOfVideoEncoderInstances(
ctx context.Context,
configurationToken string,
) (*GuaranteedNumberOfVideoEncoderInstances, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetGuaranteedNumberOfVideoEncoderInstances struct {
XMLName xml.Name `xml:"trt:GetGuaranteedNumberOfVideoEncoderInstances"`
@@ -2340,10 +2197,7 @@ func (c *Client) GetGuaranteedNumberOfVideoEncoderInstances(
// GetOSDOptions retrieves available options for OSD configuration.
func (c *Client) GetOSDOptions(ctx context.Context, configurationToken string) (*OSDConfigurationOptions, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetOSDOptions struct {
XMLName xml.Name `xml:"trt:GetOSDOptions"`
@@ -2381,10 +2235,7 @@ func (c *Client) GetOSDOptions(ctx context.Context, configurationToken string) (
// GetVideoSourceConfigurations retrieves all video source configurations.
func (c *Client) GetVideoSourceConfigurations(ctx context.Context) ([]*VideoSourceConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetVideoSourceConfigurations struct {
XMLName xml.Name `xml:"trt:GetVideoSourceConfigurations"`
@@ -2444,10 +2295,7 @@ func (c *Client) GetVideoSourceConfigurations(ctx context.Context) ([]*VideoSour
// GetAudioSourceConfigurations retrieves all audio source configurations.
func (c *Client) GetAudioSourceConfigurations(ctx context.Context) ([]*AudioSourceConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetAudioSourceConfigurations struct {
XMLName xml.Name `xml:"trt:GetAudioSourceConfigurations"`
@@ -2492,10 +2340,7 @@ func (c *Client) GetAudioSourceConfigurations(ctx context.Context) ([]*AudioSour
// GetVideoEncoderConfigurations retrieves all video encoder configurations.
func (c *Client) GetVideoEncoderConfigurations(ctx context.Context) ([]*VideoEncoderConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetVideoEncoderConfigurations struct {
XMLName xml.Name `xml:"trt:GetVideoEncoderConfigurations"`
@@ -2616,10 +2461,7 @@ func (c *Client) GetVideoEncoderConfigurations(ctx context.Context) ([]*VideoEnc
// GetAudioEncoderConfigurations retrieves all audio encoder configurations.
func (c *Client) GetAudioEncoderConfigurations(ctx context.Context) ([]*AudioEncoderConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetAudioEncoderConfigurations struct {
XMLName xml.Name `xml:"trt:GetAudioEncoderConfigurations"`
@@ -2699,10 +2541,7 @@ func (c *Client) GetVideoSourceConfiguration(
ctx context.Context,
configurationToken string,
) (*VideoSourceConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetVideoSourceConfiguration struct {
XMLName xml.Name `xml:"trt:GetVideoSourceConfiguration"`
@@ -2785,7 +2624,9 @@ func (c *Client) GetAudioSourceConfiguration(ctx context.Context, configurationT
}
var resp GetAudioSourceConfigurationResponse
soapClient := c.getMediaSoapClient()
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
if err := soapClient.Call(ctx, endpoint, "", req, &resp); err != nil {
return nil, fmt.Errorf("GetAudioSourceConfiguration failed: %w", err)
@@ -2804,10 +2645,7 @@ func (c *Client) GetVideoSourceConfigurationOptions(
ctx context.Context,
configurationToken, profileToken string,
) (*VideoSourceConfigurationOptions, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetVideoSourceConfigurationOptions struct {
XMLName xml.Name `xml:"trt:GetVideoSourceConfigurationOptions"`
@@ -2867,10 +2705,7 @@ func (c *Client) GetAudioSourceConfigurationOptions(
ctx context.Context,
configurationToken, profileToken string,
) (*AudioSourceConfigurationOptions, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetAudioSourceConfigurationOptions struct {
XMLName xml.Name `xml:"trt:GetAudioSourceConfigurationOptions"`
@@ -2916,10 +2751,7 @@ func (c *Client) SetVideoSourceConfiguration(
config *VideoSourceConfiguration,
forcePersistence bool,
) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type SetVideoSourceConfiguration struct {
XMLName xml.Name `xml:"trt:SetVideoSourceConfiguration"`
@@ -2977,10 +2809,7 @@ func (c *Client) SetVideoSourceConfiguration(
// SetAudioSourceConfiguration sets audio source configuration.
func (c *Client) SetAudioSourceConfiguration(ctx context.Context, config *AudioSourceConfiguration, forcePersistence bool) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type SetAudioSourceConfiguration struct {
XMLName xml.Name `xml:"trt:SetAudioSourceConfiguration"`
@@ -3021,10 +2850,7 @@ func (c *Client) GetCompatibleVideoEncoderConfigurations(
ctx context.Context,
profileToken string,
) ([]*VideoEncoderConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetCompatibleVideoEncoderConfigurations struct {
XMLName xml.Name `xml:"trt:GetCompatibleVideoEncoderConfigurations"`
@@ -3102,10 +2928,7 @@ func (c *Client) GetCompatibleVideoSourceConfigurations(
ctx context.Context,
profileToken string,
) ([]*VideoSourceConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetCompatibleVideoSourceConfigurations struct {
XMLName xml.Name `xml:"trt:GetCompatibleVideoSourceConfigurations"`
@@ -3170,10 +2993,7 @@ func (c *Client) GetCompatibleAudioEncoderConfigurations(
ctx context.Context,
profileToken string,
) ([]*AudioEncoderConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetCompatibleAudioEncoderConfigurations struct {
XMLName xml.Name `xml:"trt:GetCompatibleAudioEncoderConfigurations"`
@@ -3224,10 +3044,7 @@ func (c *Client) GetCompatibleAudioEncoderConfigurations(
// GetCompatibleAudioSourceConfigurations retrieves compatible audio source configurations for a profile.
func (c *Client) GetCompatibleAudioSourceConfigurations(ctx context.Context, profileToken string) ([]*AudioSourceConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetCompatibleAudioSourceConfigurations struct {
XMLName xml.Name `xml:"trt:GetCompatibleAudioSourceConfigurations"`
@@ -3274,10 +3091,7 @@ func (c *Client) GetCompatibleAudioSourceConfigurations(ctx context.Context, pro
// GetCompatiblePTZConfigurations retrieves compatible PTZ configurations for a profile.
func (c *Client) GetCompatiblePTZConfigurations(ctx context.Context, profileToken string) ([]*PTZConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetCompatiblePTZConfigurations struct {
XMLName xml.Name `xml:"trt:GetCompatiblePTZConfigurations"`
@@ -3324,10 +3138,7 @@ func (c *Client) GetCompatiblePTZConfigurations(ctx context.Context, profileToke
// GetCompatibleMetadataConfigurations retrieves compatible metadata configurations for a profile.
func (c *Client) GetCompatibleMetadataConfigurations(ctx context.Context, profileToken string) ([]*MetadataConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetCompatibleMetadataConfigurations struct {
XMLName xml.Name `xml:"trt:GetCompatibleMetadataConfigurations"`
@@ -3374,10 +3185,7 @@ func (c *Client) GetCompatibleMetadataConfigurations(ctx context.Context, profil
// GetCompatibleAudioOutputConfigurations retrieves compatible audio output configurations for a profile.
func (c *Client) GetCompatibleAudioOutputConfigurations(ctx context.Context, profileToken string) ([]*AudioOutputConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetCompatibleAudioOutputConfigurations struct {
XMLName xml.Name `xml:"trt:GetCompatibleAudioOutputConfigurations"`
@@ -3424,10 +3232,7 @@ func (c *Client) GetCompatibleAudioOutputConfigurations(ctx context.Context, pro
// GetCompatibleAudioDecoderConfigurations retrieves compatible audio decoder configurations for a profile.
func (c *Client) GetCompatibleAudioDecoderConfigurations(ctx context.Context, profileToken string) ([]*AudioDecoderConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetCompatibleAudioDecoderConfigurations struct {
XMLName xml.Name `xml:"trt:GetCompatibleAudioDecoderConfigurations"`
@@ -3472,10 +3277,7 @@ func (c *Client) GetCompatibleAudioDecoderConfigurations(ctx context.Context, pr
// GetMetadataConfigurations retrieves all metadata configurations.
func (c *Client) GetMetadataConfigurations(ctx context.Context) ([]*MetadataConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetMetadataConfigurations struct {
XMLName xml.Name `xml:"trt:GetMetadataConfigurations"`
@@ -3520,10 +3322,7 @@ func (c *Client) GetMetadataConfigurations(ctx context.Context) ([]*MetadataConf
// GetAudioOutputConfigurations retrieves all audio output configurations.
func (c *Client) GetAudioOutputConfigurations(ctx context.Context) ([]*AudioOutputConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetAudioOutputConfigurations struct {
XMLName xml.Name `xml:"trt:GetAudioOutputConfigurations"`
@@ -3568,10 +3367,7 @@ func (c *Client) GetAudioOutputConfigurations(ctx context.Context) ([]*AudioOutp
// GetAudioDecoderConfigurations retrieves all audio decoder configurations.
func (c *Client) GetAudioDecoderConfigurations(ctx context.Context) ([]*AudioDecoderConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetAudioDecoderConfigurations struct {
XMLName xml.Name `xml:"trt:GetAudioDecoderConfigurations"`
@@ -3617,10 +3413,7 @@ func (c *Client) GetAudioDecoderConfiguration(
ctx context.Context,
configurationToken string,
) (*AudioDecoderConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetAudioDecoderConfiguration struct {
XMLName xml.Name `xml:"trt:GetAudioDecoderConfiguration"`
@@ -3660,10 +3453,7 @@ func (c *Client) GetAudioDecoderConfiguration(
// SetAudioDecoderConfiguration sets audio decoder configuration.
func (c *Client) SetAudioDecoderConfiguration(ctx context.Context, config *AudioDecoderConfiguration, forcePersistence bool) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type SetAudioDecoderConfiguration struct {
XMLName xml.Name `xml:"trt:SetAudioDecoderConfiguration"`
@@ -3699,10 +3489,7 @@ func (c *Client) SetAudioDecoderConfiguration(ctx context.Context, config *Audio
// GetVideoAnalyticsConfigurations retrieves all video analytics configurations.
func (c *Client) GetVideoAnalyticsConfigurations(ctx context.Context) ([]*VideoAnalyticsConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetVideoAnalyticsConfigurations struct {
XMLName xml.Name `xml:"trt:GetVideoAnalyticsConfigurations"`
@@ -3748,10 +3535,7 @@ func (c *Client) GetVideoAnalyticsConfiguration(
ctx context.Context,
configurationToken string,
) (*VideoAnalyticsConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetVideoAnalyticsConfiguration struct {
XMLName xml.Name `xml:"trt:GetVideoAnalyticsConfiguration"`
@@ -3791,10 +3575,7 @@ func (c *Client) GetVideoAnalyticsConfiguration(
// GetCompatibleVideoAnalyticsConfigurations retrieves compatible video analytics configurations for a profile.
func (c *Client) GetCompatibleVideoAnalyticsConfigurations(ctx context.Context, profileToken string) ([]*VideoAnalyticsConfiguration, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetCompatibleVideoAnalyticsConfigurations struct {
XMLName xml.Name `xml:"trt:GetCompatibleVideoAnalyticsConfigurations"`
@@ -3839,10 +3620,7 @@ func (c *Client) GetCompatibleVideoAnalyticsConfigurations(ctx context.Context,
// SetVideoAnalyticsConfiguration sets video analytics configuration.
func (c *Client) SetVideoAnalyticsConfiguration(ctx context.Context, config *VideoAnalyticsConfiguration, forcePersistence bool) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type SetVideoAnalyticsConfiguration struct {
XMLName xml.Name `xml:"trt:SetVideoAnalyticsConfiguration"`
@@ -3881,10 +3659,7 @@ func (c *Client) GetVideoAnalyticsConfigurationOptions(
ctx context.Context,
configurationToken, profileToken string,
) (*VideoAnalyticsConfigurationOptions, error) {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type GetVideoAnalyticsConfigurationOptions struct {
XMLName xml.Name `xml:"trt:GetVideoAnalyticsConfigurationOptions"`
@@ -3922,10 +3697,7 @@ func (c *Client) GetVideoAnalyticsConfigurationOptions(
// AddVideoAnalyticsConfiguration adds a video analytics configuration to a profile.
func (c *Client) AddVideoAnalyticsConfiguration(ctx context.Context, profileToken, configurationToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type AddVideoAnalyticsConfiguration struct {
XMLName xml.Name `xml:"trt:AddVideoAnalyticsConfiguration"`
@@ -3952,10 +3724,7 @@ func (c *Client) AddVideoAnalyticsConfiguration(ctx context.Context, profileToke
// RemoveVideoAnalyticsConfiguration removes a video analytics configuration from a profile.
func (c *Client) RemoveVideoAnalyticsConfiguration(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type RemoveVideoAnalyticsConfiguration struct {
XMLName xml.Name `xml:"trt:RemoveVideoAnalyticsConfiguration"`
@@ -3980,10 +3749,7 @@ func (c *Client) RemoveVideoAnalyticsConfiguration(ctx context.Context, profileT
// AddAudioOutputConfiguration adds an audio output configuration to a profile.
func (c *Client) AddAudioOutputConfiguration(ctx context.Context, profileToken, configurationToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type AddAudioOutputConfiguration struct {
XMLName xml.Name `xml:"trt:AddAudioOutputConfiguration"`
@@ -4010,10 +3776,7 @@ func (c *Client) AddAudioOutputConfiguration(ctx context.Context, profileToken,
// RemoveAudioOutputConfiguration removes an audio output configuration from a profile.
func (c *Client) RemoveAudioOutputConfiguration(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type RemoveAudioOutputConfiguration struct {
XMLName xml.Name `xml:"trt:RemoveAudioOutputConfiguration"`
@@ -4038,10 +3801,7 @@ func (c *Client) RemoveAudioOutputConfiguration(ctx context.Context, profileToke
// AddAudioDecoderConfiguration adds an audio decoder configuration to a profile.
func (c *Client) AddAudioDecoderConfiguration(ctx context.Context, profileToken, configurationToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type AddAudioDecoderConfiguration struct {
XMLName xml.Name `xml:"trt:AddAudioDecoderConfiguration"`
@@ -4068,10 +3828,7 @@ func (c *Client) AddAudioDecoderConfiguration(ctx context.Context, profileToken,
// RemoveAudioDecoderConfiguration removes an audio decoder configuration from a profile.
func (c *Client) RemoveAudioDecoderConfiguration(ctx context.Context, profileToken string) error {
endpoint := c.mediaEndpoint
if endpoint == "" {
endpoint = c.endpoint
}
endpoint := c.getMediaEndpoint()
type RemoveAudioDecoderConfiguration struct {
XMLName xml.Name `xml:"trt:RemoveAudioDecoderConfiguration"`
+86 -346
View File
@@ -11,6 +11,61 @@ import (
// PTZ service namespace.
const ptzNamespace = "http://www.onvif.org/ver20/ptz/wsdl"
// ptzPanTiltXML is a shared type for PTZ pan/tilt XML serialization.
type ptzPanTiltXML struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
}
// ptzZoomXML is a shared type for PTZ zoom XML serialization.
type ptzZoomXML struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
}
// ptzVectorXML is a shared type for PTZ position/velocity XML serialization.
type ptzVectorXML struct {
PanTilt *ptzPanTiltXML `xml:"PanTilt,omitempty"`
Zoom *ptzZoomXML `xml:"Zoom,omitempty"`
}
// ptzSpeedXML is a shared type for PTZ speed XML serialization.
type ptzSpeedXML struct {
PanTilt *ptzPanTiltXML `xml:"PanTilt,omitempty"`
Zoom *ptzZoomXML `xml:"Zoom,omitempty"`
}
// convertToPTZVectorXML converts PTZVector to XML struct.
func convertToPTZVectorXML(v *PTZVector) *ptzVectorXML {
if v == nil {
return nil
}
result := &ptzVectorXML{}
if v.PanTilt != nil {
result.PanTilt = &ptzPanTiltXML{X: v.PanTilt.X, Y: v.PanTilt.Y, Space: v.PanTilt.Space}
}
if v.Zoom != nil {
result.Zoom = &ptzZoomXML{X: v.Zoom.X, Space: v.Zoom.Space}
}
return result
}
// convertToPTZSpeedXML converts PTZSpeed to XML struct.
func convertToPTZSpeedXML(s *PTZSpeed) *ptzSpeedXML {
if s == nil {
return nil
}
result := &ptzSpeedXML{}
if s.PanTilt != nil {
result.PanTilt = &ptzPanTiltXML{X: s.PanTilt.X, Y: s.PanTilt.Y, Space: s.PanTilt.Space}
}
if s.Zoom != nil {
result.Zoom = &ptzZoomXML{X: s.Zoom.X, Space: s.Zoom.Space}
}
return result
}
// ContinuousMove starts continuous PTZ movement.
func (c *Client) ContinuousMove(ctx context.Context, profileToken string, velocity *PTZSpeed, timeout *string) error {
endpoint := c.ptzEndpoint
@@ -19,65 +74,20 @@ func (c *Client) ContinuousMove(ctx context.Context, profileToken string, veloci
}
type ContinuousMove struct {
XMLName xml.Name `xml:"tptz:ContinuousMove"`
Xmlns string `xml:"xmlns:tptz,attr"`
ProfileToken string `xml:"tptz:ProfileToken"`
Velocity *struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
} `xml:"tptz:Velocity"`
Timeout *string `xml:"tptz:Timeout,omitempty"`
XMLName xml.Name `xml:"tptz:ContinuousMove"`
Xmlns string `xml:"xmlns:tptz,attr"`
ProfileToken string `xml:"tptz:ProfileToken"`
Velocity *ptzSpeedXML `xml:"tptz:Velocity"`
Timeout *string `xml:"tptz:Timeout,omitempty"`
}
req := ContinuousMove{
Xmlns: ptzNamespace,
ProfileToken: profileToken,
Velocity: convertToPTZSpeedXML(velocity),
Timeout: timeout,
}
if velocity != nil {
req.Velocity = &struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
}{}
if velocity.PanTilt != nil {
req.Velocity.PanTilt = &struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: velocity.PanTilt.X,
Y: velocity.PanTilt.Y,
Space: velocity.PanTilt.Space,
}
}
if velocity.Zoom != nil {
req.Velocity.Zoom = &struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: velocity.Zoom.X,
Space: velocity.Zoom.Space,
}
}
}
username, password := c.GetCredentials()
soapClient := soap.NewClient(c.httpClient, username, password)
@@ -96,108 +106,18 @@ func (c *Client) AbsoluteMove(ctx context.Context, profileToken string, position
}
type AbsoluteMove struct {
XMLName xml.Name `xml:"tptz:AbsoluteMove"`
Xmlns string `xml:"xmlns:tptz,attr"`
ProfileToken string `xml:"tptz:ProfileToken"`
Position *struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
} `xml:"tptz:Position"`
Speed *struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
} `xml:"tptz:Speed,omitempty"`
XMLName xml.Name `xml:"tptz:AbsoluteMove"`
Xmlns string `xml:"xmlns:tptz,attr"`
ProfileToken string `xml:"tptz:ProfileToken"`
Position *ptzVectorXML `xml:"tptz:Position"`
Speed *ptzSpeedXML `xml:"tptz:Speed,omitempty"`
}
req := AbsoluteMove{
Xmlns: ptzNamespace,
ProfileToken: profileToken,
}
if position != nil {
req.Position = &struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
}{}
if position.PanTilt != nil {
req.Position.PanTilt = &struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: position.PanTilt.X,
Y: position.PanTilt.Y,
Space: position.PanTilt.Space,
}
}
if position.Zoom != nil {
req.Position.Zoom = &struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: position.Zoom.X,
Space: position.Zoom.Space,
}
}
}
if speed != nil {
req.Speed = &struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
}{}
if speed.PanTilt != nil {
req.Speed.PanTilt = &struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: speed.PanTilt.X,
Y: speed.PanTilt.Y,
Space: speed.PanTilt.Space,
}
}
if speed.Zoom != nil {
req.Speed.Zoom = &struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: speed.Zoom.X,
Space: speed.Zoom.Space,
}
}
Position: convertToPTZVectorXML(position),
Speed: convertToPTZSpeedXML(speed),
}
username, password := c.GetCredentials()
@@ -218,108 +138,18 @@ func (c *Client) RelativeMove(ctx context.Context, profileToken string, translat
}
type RelativeMove struct {
XMLName xml.Name `xml:"tptz:RelativeMove"`
Xmlns string `xml:"xmlns:tptz,attr"`
ProfileToken string `xml:"tptz:ProfileToken"`
Translation *struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
} `xml:"tptz:Translation"`
Speed *struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
} `xml:"tptz:Speed,omitempty"`
XMLName xml.Name `xml:"tptz:RelativeMove"`
Xmlns string `xml:"xmlns:tptz,attr"`
ProfileToken string `xml:"tptz:ProfileToken"`
Translation *ptzVectorXML `xml:"tptz:Translation"`
Speed *ptzSpeedXML `xml:"tptz:Speed,omitempty"`
}
req := RelativeMove{
Xmlns: ptzNamespace,
ProfileToken: profileToken,
}
if translation != nil {
req.Translation = &struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
}{}
if translation.PanTilt != nil {
req.Translation.PanTilt = &struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: translation.PanTilt.X,
Y: translation.PanTilt.Y,
Space: translation.PanTilt.Space,
}
}
if translation.Zoom != nil {
req.Translation.Zoom = &struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: translation.Zoom.X,
Space: translation.Zoom.Space,
}
}
}
if speed != nil {
req.Speed = &struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
}{}
if speed.PanTilt != nil {
req.Speed.PanTilt = &struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: speed.PanTilt.X,
Y: speed.PanTilt.Y,
Space: speed.PanTilt.Space,
}
}
if speed.Zoom != nil {
req.Speed.Zoom = &struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: speed.Zoom.X,
Space: speed.Zoom.Space,
}
}
Translation: convertToPTZVectorXML(translation),
Speed: convertToPTZSpeedXML(speed),
}
username, password := c.GetCredentials()
@@ -534,63 +364,18 @@ func (c *Client) GotoPreset(ctx context.Context, profileToken, presetToken strin
}
type GotoPreset struct {
XMLName xml.Name `xml:"tptz:GotoPreset"`
Xmlns string `xml:"xmlns:tptz,attr"`
ProfileToken string `xml:"tptz:ProfileToken"`
PresetToken string `xml:"tptz:PresetToken"`
Speed *struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
} `xml:"tptz:Speed,omitempty"`
XMLName xml.Name `xml:"tptz:GotoPreset"`
Xmlns string `xml:"xmlns:tptz,attr"`
ProfileToken string `xml:"tptz:ProfileToken"`
PresetToken string `xml:"tptz:PresetToken"`
Speed *ptzSpeedXML `xml:"tptz:Speed,omitempty"`
}
req := GotoPreset{
Xmlns: ptzNamespace,
ProfileToken: profileToken,
PresetToken: presetToken,
}
if speed != nil {
req.Speed = &struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
}{}
if speed.PanTilt != nil {
req.Speed.PanTilt = &struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: speed.PanTilt.X,
Y: speed.PanTilt.Y,
Space: speed.PanTilt.Space,
}
}
if speed.Zoom != nil {
req.Speed.Zoom = &struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: speed.Zoom.X,
Space: speed.Zoom.Space,
}
}
Speed: convertToPTZSpeedXML(speed),
}
username, password := c.GetCredentials()
@@ -685,61 +470,16 @@ func (c *Client) GotoHomePosition(ctx context.Context, profileToken string, spee
}
type GotoHomePosition struct {
XMLName xml.Name `xml:"tptz:GotoHomePosition"`
Xmlns string `xml:"xmlns:tptz,attr"`
ProfileToken string `xml:"tptz:ProfileToken"`
Speed *struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
} `xml:"tptz:Speed,omitempty"`
XMLName xml.Name `xml:"tptz:GotoHomePosition"`
Xmlns string `xml:"xmlns:tptz,attr"`
ProfileToken string `xml:"tptz:ProfileToken"`
Speed *ptzSpeedXML `xml:"tptz:Speed,omitempty"`
}
req := GotoHomePosition{
Xmlns: ptzNamespace,
ProfileToken: profileToken,
}
if speed != nil {
req.Speed = &struct {
PanTilt *struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"PanTilt,omitempty"`
Zoom *struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
} `xml:"Zoom,omitempty"`
}{}
if speed.PanTilt != nil {
req.Speed.PanTilt = &struct {
X float64 `xml:"x,attr"`
Y float64 `xml:"y,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: speed.PanTilt.X,
Y: speed.PanTilt.Y,
Space: speed.PanTilt.Space,
}
}
if speed.Zoom != nil {
req.Speed.Zoom = &struct {
X float64 `xml:"x,attr"`
Space string `xml:"space,attr,omitempty"`
}{
X: speed.Zoom.X,
Space: speed.Zoom.Space,
}
}
Speed: convertToPTZSpeedXML(speed),
}
username, password := c.GetCredentials()