Files
onvif-go/server copy/types.go
T
2026-01-16 04:11:59 +00:00

466 lines
13 KiB
Go

package server
import (
"fmt"
"time"
"github.com/0x524a/onvif-go"
)
const (
defaultPort = 8080
defaultTimeoutSec = 30
defaultWidth = 1920
defaultHeight = 1080
defaultFramerate = 30
defaultQuality = 80
defaultBitrate = 4096
maxPan = 180
maxTilt = 90
defaultPTZSpeed = 0.5
mediumWidth = 1280
mediumHeight = 720
mediumQuality = 75
highQuality = 85
mediumBitrate = 2048
lowFramerate = 25
highBitrate = 6144
maxZoom = 3
lowPTZSpeed = 0.3
presetZoom = 2
)
// Config represents the ONVIF server configuration.
type Config struct {
// Server settings
Host string // Bind address (e.g., "0.0.0.0")
Port int // Server port (default: 8080)
BasePath string // Base path for services (default: "/onvif")
Timeout time.Duration // Request timeout
// Device information
DeviceInfo DeviceInfo
// Authentication
Username string
Password string
// Camera profiles (supports multi-lens cameras)
Profiles []ProfileConfig
// Capabilities
SupportPTZ bool
SupportImaging bool
SupportEvents bool
}
// DeviceInfo contains device identification information.
type DeviceInfo struct {
Manufacturer string
Model string
FirmwareVersion string
SerialNumber string
HardwareID string
}
// ProfileConfig represents a camera profile configuration.
type ProfileConfig struct {
Token string // Profile token (unique identifier)
Name string // Profile name
VideoSource VideoSourceConfig // Video source configuration
AudioSource *AudioSourceConfig // Audio source configuration (optional)
VideoEncoder VideoEncoderConfig // Video encoder configuration
AudioEncoder *AudioEncoderConfig // Audio encoder configuration (optional)
PTZ *PTZConfig // PTZ configuration (optional)
Snapshot SnapshotConfig // Snapshot configuration
}
// VideoSourceConfig represents video source configuration.
type VideoSourceConfig struct {
Token string // Video source token
Name string // Video source name
Resolution Resolution
Framerate int
Bounds Bounds
}
// AudioSourceConfig represents audio source configuration.
type AudioSourceConfig struct {
Token string // Audio source token
Name string // Audio source name
SampleRate int // Sample rate in Hz (e.g., 8000, 16000, 48000)
Bitrate int // Bitrate in kbps
}
// VideoEncoderConfig represents video encoder configuration.
type VideoEncoderConfig struct {
Encoding string // JPEG, H264, H265, MPEG4
Resolution Resolution // Video resolution
Quality float64 // Quality (0-100)
Framerate int // Frames per second
Bitrate int // Bitrate in kbps
GovLength int // GOP length
}
// AudioEncoderConfig represents audio encoder configuration.
type AudioEncoderConfig struct {
Encoding string // G711, G726, AAC
Bitrate int // Bitrate in kbps
SampleRate int // Sample rate in Hz
}
// PTZConfig represents PTZ configuration.
type PTZConfig struct {
NodeToken string // PTZ node token
PanRange Range // Pan range in degrees
TiltRange Range // Tilt range in degrees
ZoomRange Range // Zoom range
DefaultSpeed PTZSpeed // Default speed
SupportsContinuous bool // Supports continuous move
SupportsAbsolute bool // Supports absolute move
SupportsRelative bool // Supports relative move
Presets []Preset // Predefined presets
}
// SnapshotConfig represents snapshot configuration.
type SnapshotConfig struct {
Enabled bool // Whether snapshots are supported
Resolution Resolution // Snapshot resolution
Quality float64 // JPEG quality (0-100)
}
// Resolution represents video resolution.
type Resolution struct {
Width int
Height int
}
// Bounds represents video bounds.
type Bounds struct {
X int
Y int
Width int
Height int
}
// Range represents a numeric range.
type Range struct {
Min float64
Max float64
}
// PTZSpeed represents PTZ movement speed.
type PTZSpeed struct {
Pan float64 // Pan speed (-1.0 to 1.0)
Tilt float64 // Tilt speed (-1.0 to 1.0)
Zoom float64 // Zoom speed (-1.0 to 1.0)
}
// Preset represents a PTZ preset position.
type Preset struct {
Token string // Preset token
Name string // Preset name
Position PTZPosition // Position
}
// PTZPosition represents PTZ position.
type PTZPosition struct {
Pan float64 // Pan position
Tilt float64 // Tilt position
Zoom float64 // Zoom position
}
// StreamConfig represents an RTSP stream configuration.
type StreamConfig struct {
ProfileToken string // Associated profile token
RTSPPath string // RTSP path (e.g., "/stream1")
StreamURI string // Full RTSP URI
}
// Server represents the ONVIF server.
type Server struct {
config *Config
streams map[string]*StreamConfig // Profile token -> stream config
ptzState map[string]*PTZState // Profile token -> PTZ state
imagingState map[string]*ImagingState // Video source token -> imaging state
systemTime time.Time
}
// PTZState represents the current PTZ state.
type PTZState struct {
Position PTZPosition
Moving bool
PanMoving bool
TiltMoving bool
ZoomMoving bool
LastUpdate time.Time
}
// ImagingState represents the current imaging settings state.
type ImagingState struct {
Brightness float64
Contrast float64
Saturation float64
Sharpness float64
BacklightComp BacklightCompensation
Exposure ExposureSettings
Focus FocusSettings
WhiteBalance WhiteBalanceSettings
WideDynamicRange WDRSettings
IrCutFilter string // ON, OFF, AUTO
}
// BacklightCompensation represents backlight compensation settings.
type BacklightCompensation struct {
Mode string // OFF, ON
Level float64 // 0-100
}
// ExposureSettings represents exposure settings.
type ExposureSettings struct {
Mode string // AUTO, MANUAL
Priority string // LowNoise, FrameRate
MinExposure float64
MaxExposure float64
MinGain float64
MaxGain float64
ExposureTime float64
Gain float64
}
// FocusSettings represents focus settings.
type FocusSettings struct {
AutoFocusMode string // AUTO, MANUAL
DefaultSpeed float64
NearLimit float64
FarLimit float64
CurrentPos float64
}
// WhiteBalanceSettings represents white balance settings.
type WhiteBalanceSettings struct {
Mode string // AUTO, MANUAL
CrGain float64
CbGain float64
}
// WDRSettings represents wide dynamic range settings.
type WDRSettings struct {
Mode string // OFF, ON
Level float64 // 0-100
}
// DefaultConfig returns a default server configuration with a multi-lens camera setup.
//
//nolint:funlen // DefaultConfig has many statements due to comprehensive default configuration
func DefaultConfig() *Config {
return &Config{
Host: "0.0.0.0",
Port: defaultPort,
BasePath: "/onvif",
Timeout: defaultTimeoutSec * time.Second,
DeviceInfo: DeviceInfo{
Manufacturer: "onvif-go",
Model: "Virtual Multi-Lens Camera",
FirmwareVersion: "1.0.0",
SerialNumber: "SN-12345678",
HardwareID: "HW-87654321",
},
Username: "admin",
Password: "admin",
SupportPTZ: true,
SupportImaging: true,
SupportEvents: false,
Profiles: []ProfileConfig{
{
Token: "profile_0",
Name: "Main Camera - High Quality",
VideoSource: VideoSourceConfig{
Token: "video_source_0",
Name: "Main Camera",
Resolution: Resolution{Width: defaultWidth, Height: defaultHeight},
Framerate: defaultFramerate,
Bounds: Bounds{X: 0, Y: 0, Width: defaultWidth, Height: defaultHeight},
},
VideoEncoder: VideoEncoderConfig{
Encoding: "H264",
Resolution: Resolution{Width: defaultWidth, Height: defaultHeight},
Quality: defaultQuality,
Framerate: defaultFramerate,
Bitrate: defaultBitrate,
GovLength: defaultFramerate,
},
PTZ: &PTZConfig{
NodeToken: "ptz_node_0",
PanRange: Range{Min: -maxPan, Max: maxPan},
TiltRange: Range{Min: -maxTilt, Max: maxTilt},
ZoomRange: Range{Min: 0, Max: 1},
DefaultSpeed: PTZSpeed{
Pan: defaultPTZSpeed, Tilt: defaultPTZSpeed, Zoom: defaultPTZSpeed,
},
SupportsContinuous: true,
SupportsAbsolute: true,
SupportsRelative: true,
Presets: []Preset{
{Token: "preset_0", Name: "Home", Position: PTZPosition{Pan: 0, Tilt: 0, Zoom: 0}},
{
Token: "preset_1", Name: "Entrance",
Position: PTZPosition{Pan: -45, Tilt: -10, Zoom: defaultPTZSpeed},
},
},
},
Snapshot: SnapshotConfig{
Enabled: true,
Resolution: Resolution{Width: defaultWidth, Height: defaultHeight},
Quality: highQuality,
},
},
{
Token: "profile_1",
Name: "Wide Angle Camera",
VideoSource: VideoSourceConfig{
Token: "video_source_1",
Name: "Wide Angle Camera",
Resolution: Resolution{Width: mediumWidth, Height: mediumHeight},
Framerate: defaultFramerate,
Bounds: Bounds{X: 0, Y: 0, Width: mediumWidth, Height: mediumHeight},
},
VideoEncoder: VideoEncoderConfig{
Encoding: "H264",
Resolution: Resolution{Width: mediumWidth, Height: mediumHeight},
Quality: mediumQuality,
Framerate: defaultFramerate,
Bitrate: mediumBitrate,
GovLength: defaultFramerate,
},
Snapshot: SnapshotConfig{
Enabled: true,
Resolution: Resolution{Width: mediumWidth, Height: mediumHeight},
Quality: defaultQuality,
},
},
{
Token: "profile_2",
Name: "Telephoto Camera",
VideoSource: VideoSourceConfig{
Token: "video_source_2",
Name: "Telephoto Camera",
Resolution: Resolution{Width: defaultWidth, Height: defaultHeight},
Framerate: lowFramerate,
Bounds: Bounds{X: 0, Y: 0, Width: defaultWidth, Height: defaultHeight},
},
VideoEncoder: VideoEncoderConfig{
Encoding: "H264",
Resolution: Resolution{Width: defaultWidth, Height: defaultHeight},
Quality: highQuality,
Framerate: lowFramerate,
Bitrate: highBitrate,
GovLength: lowFramerate,
},
PTZ: &PTZConfig{
NodeToken: "ptz_node_2",
PanRange: Range{Min: -maxPan, Max: maxPan},
TiltRange: Range{Min: -maxTilt, Max: maxTilt},
ZoomRange: Range{Min: 0, Max: maxZoom},
DefaultSpeed: PTZSpeed{
Pan: lowPTZSpeed, Tilt: lowPTZSpeed, Zoom: lowPTZSpeed,
},
SupportsContinuous: true,
SupportsAbsolute: true,
SupportsRelative: true,
Presets: []Preset{
{Token: "preset_2_0", Name: "Home", Position: PTZPosition{Pan: 0, Tilt: 0, Zoom: 0}},
{
Token: "preset_2_1", Name: "Zoom In",
Position: PTZPosition{Pan: 0, Tilt: 0, Zoom: presetZoom},
},
},
},
Snapshot: SnapshotConfig{
Enabled: true,
Resolution: Resolution{Width: defaultWidth, Height: defaultHeight},
Quality: highQuality,
},
},
},
}
}
// ServiceEndpoints returns the service endpoint URLs.
func (c *Config) ServiceEndpoints(host string) map[string]string {
if host == "" {
host = c.Host
if host == "0.0.0.0" || host == "" {
host = "localhost"
}
}
var baseURL string
const httpPort = 80
if c.Port == httpPort {
baseURL = "http://" + host + c.BasePath
} else {
// Import fmt at the top to use Sprintf
baseURL = fmt.Sprintf("http://%s:%d%s", host, c.Port, c.BasePath)
}
endpoints := map[string]string{
"device": baseURL + "/device_service",
"media": baseURL + "/media_service",
"imaging": baseURL + "/imaging_service",
}
if c.SupportPTZ {
endpoints["ptz"] = baseURL + "/ptz_service"
}
if c.SupportEvents {
endpoints["events"] = baseURL + "/events_service"
}
return endpoints
}
// ToONVIFProfile converts a ProfileConfig to an ONVIF Profile.
func (p *ProfileConfig) ToONVIFProfile() *onvif.Profile {
profile := &onvif.Profile{
Token: p.Token,
Name: p.Name,
VideoSourceConfiguration: &onvif.VideoSourceConfiguration{
Token: p.VideoSource.Token,
Name: p.VideoSource.Name,
SourceToken: p.VideoSource.Token,
Bounds: &onvif.IntRectangle{
X: p.VideoSource.Bounds.X,
Y: p.VideoSource.Bounds.Y,
Width: p.VideoSource.Bounds.Width,
Height: p.VideoSource.Bounds.Height,
},
},
VideoEncoderConfiguration: &onvif.VideoEncoderConfiguration{
Token: p.Token + "_encoder",
Name: p.Name + " Encoder",
Encoding: p.VideoEncoder.Encoding,
Resolution: &onvif.VideoResolution{
Width: p.VideoEncoder.Resolution.Width,
Height: p.VideoEncoder.Resolution.Height,
},
Quality: p.VideoEncoder.Quality,
RateControl: &onvif.VideoRateControl{
FrameRateLimit: p.VideoEncoder.Framerate,
BitrateLimit: p.VideoEncoder.Bitrate,
},
},
}
if p.PTZ != nil {
profile.PTZConfiguration = &onvif.PTZConfiguration{
Token: p.PTZ.NodeToken,
Name: p.Name + " PTZ",
NodeToken: p.PTZ.NodeToken,
}
}
return profile
}