Initial Commit
This commit is contained in:
+353
@@ -0,0 +1,353 @@
|
||||
package onvif
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
|
||||
"github.com/0x524A/go-onvif/soap"
|
||||
)
|
||||
|
||||
// Imaging service namespace
|
||||
const imagingNamespace = "http://www.onvif.org/ver20/imaging/wsdl"
|
||||
|
||||
// GetImagingSettings retrieves imaging settings for a video source
|
||||
func (c *Client) GetImagingSettings(ctx context.Context, videoSourceToken string) (*ImagingSettings, error) {
|
||||
endpoint := c.imagingEndpoint
|
||||
if endpoint == "" {
|
||||
endpoint = c.endpoint
|
||||
}
|
||||
|
||||
type GetImagingSettings struct {
|
||||
XMLName xml.Name `xml:"timg:GetImagingSettings"`
|
||||
Xmlns string `xml:"xmlns:timg,attr"`
|
||||
VideoSourceToken string `xml:"timg:VideoSourceToken"`
|
||||
}
|
||||
|
||||
type GetImagingSettingsResponse struct {
|
||||
XMLName xml.Name `xml:"GetImagingSettingsResponse"`
|
||||
ImagingSettings struct {
|
||||
BacklightCompensation *struct {
|
||||
Mode string `xml:"Mode"`
|
||||
Level float64 `xml:"Level"`
|
||||
} `xml:"BacklightCompensation"`
|
||||
Brightness *float64 `xml:"Brightness"`
|
||||
ColorSaturation *float64 `xml:"ColorSaturation"`
|
||||
Contrast *float64 `xml:"Contrast"`
|
||||
Exposure *struct {
|
||||
Mode string `xml:"Mode"`
|
||||
Priority string `xml:"Priority"`
|
||||
MinExposureTime float64 `xml:"MinExposureTime"`
|
||||
MaxExposureTime float64 `xml:"MaxExposureTime"`
|
||||
MinGain float64 `xml:"MinGain"`
|
||||
MaxGain float64 `xml:"MaxGain"`
|
||||
MinIris float64 `xml:"MinIris"`
|
||||
MaxIris float64 `xml:"MaxIris"`
|
||||
ExposureTime float64 `xml:"ExposureTime"`
|
||||
Gain float64 `xml:"Gain"`
|
||||
Iris float64 `xml:"Iris"`
|
||||
} `xml:"Exposure"`
|
||||
Focus *struct {
|
||||
AutoFocusMode string `xml:"AutoFocusMode"`
|
||||
DefaultSpeed float64 `xml:"DefaultSpeed"`
|
||||
NearLimit float64 `xml:"NearLimit"`
|
||||
FarLimit float64 `xml:"FarLimit"`
|
||||
} `xml:"Focus"`
|
||||
IrCutFilter *string `xml:"IrCutFilter"`
|
||||
Sharpness *float64 `xml:"Sharpness"`
|
||||
WideDynamicRange *struct {
|
||||
Mode string `xml:"Mode"`
|
||||
Level float64 `xml:"Level"`
|
||||
} `xml:"WideDynamicRange"`
|
||||
WhiteBalance *struct {
|
||||
Mode string `xml:"Mode"`
|
||||
CrGain float64 `xml:"CrGain"`
|
||||
CbGain float64 `xml:"CbGain"`
|
||||
} `xml:"WhiteBalance"`
|
||||
} `xml:"ImagingSettings"`
|
||||
}
|
||||
|
||||
req := GetImagingSettings{
|
||||
Xmlns: imagingNamespace,
|
||||
VideoSourceToken: videoSourceToken,
|
||||
}
|
||||
|
||||
var resp GetImagingSettingsResponse
|
||||
|
||||
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("GetImagingSettings failed: %w", err)
|
||||
}
|
||||
|
||||
settings := &ImagingSettings{
|
||||
Brightness: resp.ImagingSettings.Brightness,
|
||||
ColorSaturation: resp.ImagingSettings.ColorSaturation,
|
||||
Contrast: resp.ImagingSettings.Contrast,
|
||||
IrCutFilter: resp.ImagingSettings.IrCutFilter,
|
||||
Sharpness: resp.ImagingSettings.Sharpness,
|
||||
}
|
||||
|
||||
if resp.ImagingSettings.BacklightCompensation != nil {
|
||||
settings.BacklightCompensation = &BacklightCompensation{
|
||||
Mode: resp.ImagingSettings.BacklightCompensation.Mode,
|
||||
Level: resp.ImagingSettings.BacklightCompensation.Level,
|
||||
}
|
||||
}
|
||||
|
||||
if resp.ImagingSettings.Exposure != nil {
|
||||
settings.Exposure = &Exposure{
|
||||
Mode: resp.ImagingSettings.Exposure.Mode,
|
||||
Priority: resp.ImagingSettings.Exposure.Priority,
|
||||
MinExposureTime: resp.ImagingSettings.Exposure.MinExposureTime,
|
||||
MaxExposureTime: resp.ImagingSettings.Exposure.MaxExposureTime,
|
||||
MinGain: resp.ImagingSettings.Exposure.MinGain,
|
||||
MaxGain: resp.ImagingSettings.Exposure.MaxGain,
|
||||
MinIris: resp.ImagingSettings.Exposure.MinIris,
|
||||
MaxIris: resp.ImagingSettings.Exposure.MaxIris,
|
||||
ExposureTime: resp.ImagingSettings.Exposure.ExposureTime,
|
||||
Gain: resp.ImagingSettings.Exposure.Gain,
|
||||
Iris: resp.ImagingSettings.Exposure.Iris,
|
||||
}
|
||||
}
|
||||
|
||||
if resp.ImagingSettings.Focus != nil {
|
||||
settings.Focus = &FocusConfiguration{
|
||||
AutoFocusMode: resp.ImagingSettings.Focus.AutoFocusMode,
|
||||
DefaultSpeed: resp.ImagingSettings.Focus.DefaultSpeed,
|
||||
NearLimit: resp.ImagingSettings.Focus.NearLimit,
|
||||
FarLimit: resp.ImagingSettings.Focus.FarLimit,
|
||||
}
|
||||
}
|
||||
|
||||
if resp.ImagingSettings.WideDynamicRange != nil {
|
||||
settings.WideDynamicRange = &WideDynamicRange{
|
||||
Mode: resp.ImagingSettings.WideDynamicRange.Mode,
|
||||
Level: resp.ImagingSettings.WideDynamicRange.Level,
|
||||
}
|
||||
}
|
||||
|
||||
if resp.ImagingSettings.WhiteBalance != nil {
|
||||
settings.WhiteBalance = &WhiteBalance{
|
||||
Mode: resp.ImagingSettings.WhiteBalance.Mode,
|
||||
CrGain: resp.ImagingSettings.WhiteBalance.CrGain,
|
||||
CbGain: resp.ImagingSettings.WhiteBalance.CbGain,
|
||||
}
|
||||
}
|
||||
|
||||
return settings, nil
|
||||
}
|
||||
|
||||
// SetImagingSettings sets imaging settings for a video source
|
||||
func (c *Client) SetImagingSettings(ctx context.Context, videoSourceToken string, settings *ImagingSettings, forcePersistence bool) error {
|
||||
endpoint := c.imagingEndpoint
|
||||
if endpoint == "" {
|
||||
endpoint = c.endpoint
|
||||
}
|
||||
|
||||
type SetImagingSettings struct {
|
||||
XMLName xml.Name `xml:"timg:SetImagingSettings"`
|
||||
Xmlns string `xml:"xmlns:timg,attr"`
|
||||
VideoSourceToken string `xml:"timg:VideoSourceToken"`
|
||||
ImagingSettings struct {
|
||||
BacklightCompensation *struct {
|
||||
Mode string `xml:"Mode"`
|
||||
Level float64 `xml:"Level"`
|
||||
} `xml:"BacklightCompensation,omitempty"`
|
||||
Brightness *float64 `xml:"Brightness,omitempty"`
|
||||
ColorSaturation *float64 `xml:"ColorSaturation,omitempty"`
|
||||
Contrast *float64 `xml:"Contrast,omitempty"`
|
||||
Exposure *struct {
|
||||
Mode string `xml:"Mode"`
|
||||
Priority string `xml:"Priority,omitempty"`
|
||||
MinExposureTime float64 `xml:"MinExposureTime,omitempty"`
|
||||
MaxExposureTime float64 `xml:"MaxExposureTime,omitempty"`
|
||||
MinGain float64 `xml:"MinGain,omitempty"`
|
||||
MaxGain float64 `xml:"MaxGain,omitempty"`
|
||||
MinIris float64 `xml:"MinIris,omitempty"`
|
||||
MaxIris float64 `xml:"MaxIris,omitempty"`
|
||||
ExposureTime float64 `xml:"ExposureTime,omitempty"`
|
||||
Gain float64 `xml:"Gain,omitempty"`
|
||||
Iris float64 `xml:"Iris,omitempty"`
|
||||
} `xml:"Exposure,omitempty"`
|
||||
Focus *struct {
|
||||
AutoFocusMode string `xml:"AutoFocusMode"`
|
||||
DefaultSpeed float64 `xml:"DefaultSpeed,omitempty"`
|
||||
NearLimit float64 `xml:"NearLimit,omitempty"`
|
||||
FarLimit float64 `xml:"FarLimit,omitempty"`
|
||||
} `xml:"Focus,omitempty"`
|
||||
IrCutFilter *string `xml:"IrCutFilter,omitempty"`
|
||||
Sharpness *float64 `xml:"Sharpness,omitempty"`
|
||||
WideDynamicRange *struct {
|
||||
Mode string `xml:"Mode"`
|
||||
Level float64 `xml:"Level,omitempty"`
|
||||
} `xml:"WideDynamicRange,omitempty"`
|
||||
WhiteBalance *struct {
|
||||
Mode string `xml:"Mode"`
|
||||
CrGain float64 `xml:"CrGain,omitempty"`
|
||||
CbGain float64 `xml:"CbGain,omitempty"`
|
||||
} `xml:"WhiteBalance,omitempty"`
|
||||
} `xml:"timg:ImagingSettings"`
|
||||
ForcePersistence bool `xml:"timg:ForcePersistence"`
|
||||
}
|
||||
|
||||
req := SetImagingSettings{
|
||||
Xmlns: imagingNamespace,
|
||||
VideoSourceToken: videoSourceToken,
|
||||
ForcePersistence: forcePersistence,
|
||||
}
|
||||
|
||||
// Map settings
|
||||
if settings.BacklightCompensation != nil {
|
||||
req.ImagingSettings.BacklightCompensation = &struct {
|
||||
Mode string `xml:"Mode"`
|
||||
Level float64 `xml:"Level"`
|
||||
}{
|
||||
Mode: settings.BacklightCompensation.Mode,
|
||||
Level: settings.BacklightCompensation.Level,
|
||||
}
|
||||
}
|
||||
|
||||
req.ImagingSettings.Brightness = settings.Brightness
|
||||
req.ImagingSettings.ColorSaturation = settings.ColorSaturation
|
||||
req.ImagingSettings.Contrast = settings.Contrast
|
||||
req.ImagingSettings.IrCutFilter = settings.IrCutFilter
|
||||
req.ImagingSettings.Sharpness = settings.Sharpness
|
||||
|
||||
if settings.Exposure != nil {
|
||||
req.ImagingSettings.Exposure = &struct {
|
||||
Mode string `xml:"Mode"`
|
||||
Priority string `xml:"Priority,omitempty"`
|
||||
MinExposureTime float64 `xml:"MinExposureTime,omitempty"`
|
||||
MaxExposureTime float64 `xml:"MaxExposureTime,omitempty"`
|
||||
MinGain float64 `xml:"MinGain,omitempty"`
|
||||
MaxGain float64 `xml:"MaxGain,omitempty"`
|
||||
MinIris float64 `xml:"MinIris,omitempty"`
|
||||
MaxIris float64 `xml:"MaxIris,omitempty"`
|
||||
ExposureTime float64 `xml:"ExposureTime,omitempty"`
|
||||
Gain float64 `xml:"Gain,omitempty"`
|
||||
Iris float64 `xml:"Iris,omitempty"`
|
||||
}{
|
||||
Mode: settings.Exposure.Mode,
|
||||
Priority: settings.Exposure.Priority,
|
||||
MinExposureTime: settings.Exposure.MinExposureTime,
|
||||
MaxExposureTime: settings.Exposure.MaxExposureTime,
|
||||
MinGain: settings.Exposure.MinGain,
|
||||
MaxGain: settings.Exposure.MaxGain,
|
||||
MinIris: settings.Exposure.MinIris,
|
||||
MaxIris: settings.Exposure.MaxIris,
|
||||
ExposureTime: settings.Exposure.ExposureTime,
|
||||
Gain: settings.Exposure.Gain,
|
||||
Iris: settings.Exposure.Iris,
|
||||
}
|
||||
}
|
||||
|
||||
if settings.Focus != nil {
|
||||
req.ImagingSettings.Focus = &struct {
|
||||
AutoFocusMode string `xml:"AutoFocusMode"`
|
||||
DefaultSpeed float64 `xml:"DefaultSpeed,omitempty"`
|
||||
NearLimit float64 `xml:"NearLimit,omitempty"`
|
||||
FarLimit float64 `xml:"FarLimit,omitempty"`
|
||||
}{
|
||||
AutoFocusMode: settings.Focus.AutoFocusMode,
|
||||
DefaultSpeed: settings.Focus.DefaultSpeed,
|
||||
NearLimit: settings.Focus.NearLimit,
|
||||
FarLimit: settings.Focus.FarLimit,
|
||||
}
|
||||
}
|
||||
|
||||
if settings.WideDynamicRange != nil {
|
||||
req.ImagingSettings.WideDynamicRange = &struct {
|
||||
Mode string `xml:"Mode"`
|
||||
Level float64 `xml:"Level,omitempty"`
|
||||
}{
|
||||
Mode: settings.WideDynamicRange.Mode,
|
||||
Level: settings.WideDynamicRange.Level,
|
||||
}
|
||||
}
|
||||
|
||||
if settings.WhiteBalance != nil {
|
||||
req.ImagingSettings.WhiteBalance = &struct {
|
||||
Mode string `xml:"Mode"`
|
||||
CrGain float64 `xml:"CrGain,omitempty"`
|
||||
CbGain float64 `xml:"CbGain,omitempty"`
|
||||
}{
|
||||
Mode: settings.WhiteBalance.Mode,
|
||||
CrGain: settings.WhiteBalance.CrGain,
|
||||
CbGain: settings.WhiteBalance.CbGain,
|
||||
}
|
||||
}
|
||||
|
||||
username, password := c.GetCredentials()
|
||||
soapClient := soap.NewClient(c.httpClient, username, password)
|
||||
|
||||
if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil {
|
||||
return fmt.Errorf("SetImagingSettings failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Move performs a focus move operation
|
||||
func (c *Client) Move(ctx context.Context, videoSourceToken string, focus *FocusMove) error {
|
||||
endpoint := c.imagingEndpoint
|
||||
if endpoint == "" {
|
||||
endpoint = c.endpoint
|
||||
}
|
||||
|
||||
type Move struct {
|
||||
XMLName xml.Name `xml:"timg:Move"`
|
||||
Xmlns string `xml:"xmlns:timg,attr"`
|
||||
VideoSourceToken string `xml:"timg:VideoSourceToken"`
|
||||
Focus *struct {
|
||||
Absolute *struct {
|
||||
Position float64 `xml:"Position"`
|
||||
Speed float64 `xml:"Speed,omitempty"`
|
||||
} `xml:"Absolute,omitempty"`
|
||||
Relative *struct {
|
||||
Distance float64 `xml:"Distance"`
|
||||
Speed float64 `xml:"Speed,omitempty"`
|
||||
} `xml:"Relative,omitempty"`
|
||||
Continuous *struct {
|
||||
Speed float64 `xml:"Speed"`
|
||||
} `xml:"Continuous,omitempty"`
|
||||
} `xml:"timg:Focus"`
|
||||
}
|
||||
|
||||
req := Move{
|
||||
Xmlns: imagingNamespace,
|
||||
VideoSourceToken: videoSourceToken,
|
||||
}
|
||||
|
||||
if focus != nil {
|
||||
req.Focus = &struct {
|
||||
Absolute *struct {
|
||||
Position float64 `xml:"Position"`
|
||||
Speed float64 `xml:"Speed,omitempty"`
|
||||
} `xml:"Absolute,omitempty"`
|
||||
Relative *struct {
|
||||
Distance float64 `xml:"Distance"`
|
||||
Speed float64 `xml:"Speed,omitempty"`
|
||||
} `xml:"Relative,omitempty"`
|
||||
Continuous *struct {
|
||||
Speed float64 `xml:"Speed"`
|
||||
} `xml:"Continuous,omitempty"`
|
||||
}{}
|
||||
// Implementation would add specific focus move types here
|
||||
}
|
||||
|
||||
username, password := c.GetCredentials()
|
||||
soapClient := soap.NewClient(c.httpClient, username, password)
|
||||
|
||||
if err := soapClient.Call(ctx, endpoint, "", req, nil); err != nil {
|
||||
return fmt.Errorf("Move failed: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// FocusMove represents a focus move operation (placeholder for focus move types)
|
||||
type FocusMove struct {
|
||||
// Can be extended with Absolute, Relative, Continuous move types
|
||||
}
|
||||
Reference in New Issue
Block a user