refactor: improve code readability and maintainability across multiple files
- Reformatted function signatures for better clarity in media.go and onvif-quick/main.go. - Replaced hardcoded values with constants in ascii.go and server/imaging.go for improved maintainability. - Enhanced error handling and logging consistency in onvif-diagnostics/main.go and server/server.go. - Updated comments to clarify functionality and ensure adherence to ONVIF specifications across various files.
This commit is contained in:
+13
-11
@@ -76,7 +76,7 @@ func imageToASCIIFromImage(img image.Image, config ASCIIConfig, format string) (
|
|||||||
config.Width = 120
|
config.Width = 120
|
||||||
}
|
}
|
||||||
if config.Height <= 0 {
|
if config.Height <= 0 {
|
||||||
config.Height = 40
|
config.Height = defaultASCIIHeight
|
||||||
}
|
}
|
||||||
if config.Quality == "" {
|
if config.Quality == "" {
|
||||||
config.Quality = "medium"
|
config.Quality = "medium"
|
||||||
@@ -130,11 +130,11 @@ func imageToASCIIFromImage(img image.Image, config ASCIIConfig, format string) (
|
|||||||
|
|
||||||
// Invert if requested
|
// Invert if requested
|
||||||
if config.Invert {
|
if config.Invert {
|
||||||
brightness = 255 - brightness
|
brightness = maxColorValue - brightness
|
||||||
}
|
}
|
||||||
|
|
||||||
// Map brightness to character
|
// Map brightness to character
|
||||||
charIndex := int(float64(brightness) / 255.0 * float64(len(charset)-1))
|
charIndex := int(float64(brightness) / float64(maxColorValue) * float64(len(charset)-1))
|
||||||
if charIndex >= len(charset) {
|
if charIndex >= len(charset) {
|
||||||
charIndex = len(charset) - 1
|
charIndex = len(charset) - 1
|
||||||
}
|
}
|
||||||
@@ -153,16 +153,16 @@ func imageToASCIIFromImage(img image.Image, config ASCIIConfig, format string) (
|
|||||||
// Uses standard luminance formula.
|
// Uses standard luminance formula.
|
||||||
func calculateBrightness(r, g, b uint32) int {
|
func calculateBrightness(r, g, b uint32) int {
|
||||||
// Convert 16-bit color to 8-bit
|
// Convert 16-bit color to 8-bit
|
||||||
r8 := uint8(r >> bitShift8) //nolint:gosec // Color values are clamped to valid range
|
r8 := uint8(r >> bitShift8) //nolint:gosec // Color values are clamped to valid range
|
||||||
g8 := uint8(g >> bitShift8) //nolint:gosec // Color values are clamped to valid range
|
g8 := uint8(g >> bitShift8) //nolint:gosec // Color values are clamped to valid range
|
||||||
b8 := uint8(b >> bitShift8) //nolint:gosec // Color values are clamped to valid range
|
b8 := uint8(b >> bitShift8) //nolint:gosec // Color values are clamped to valid range
|
||||||
|
|
||||||
// Use standard brightness calculation
|
// Use standard brightness calculation
|
||||||
// https://en.wikipedia.org/wiki/Relative_luminance
|
// https://en.wikipedia.org/wiki/Relative_luminance
|
||||||
brightness := int(0.299*float64(r8) + 0.587*float64(g8) + 0.114*float64(b8))
|
brightness := int(0.299*float64(r8) + 0.587*float64(g8) + 0.114*float64(b8))
|
||||||
|
|
||||||
if brightness > 255 {
|
if brightness > maxColorValue {
|
||||||
brightness = 255
|
brightness = maxColorValue
|
||||||
}
|
}
|
||||||
if brightness < 0 {
|
if brightness < 0 {
|
||||||
brightness = 0
|
brightness = 0
|
||||||
@@ -223,11 +223,13 @@ func formatBytes(bytes int64) string {
|
|||||||
if bytes < 1024 {
|
if bytes < 1024 {
|
||||||
return fmt.Sprintf("%d B", bytes)
|
return fmt.Sprintf("%d B", bytes)
|
||||||
}
|
}
|
||||||
if bytes < 1024*1024 {
|
const kbSize = 1024
|
||||||
return fmt.Sprintf("%.1f KB", float64(bytes)/1024)
|
const mbSize = 1024 * 1024
|
||||||
|
if bytes < mbSize {
|
||||||
|
return fmt.Sprintf("%.1f KB", float64(bytes)/kbSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt.Sprintf("%.1f MB", float64(bytes)/(1024*1024))
|
return fmt.Sprintf("%.1f MB", float64(bytes)/mbSize)
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateASCIIHighQuality creates a high-quality ASCII representation.
|
// CreateASCIIHighQuality creates a high-quality ASCII representation.
|
||||||
|
|||||||
@@ -21,11 +21,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
defaultTimeoutSec = 30
|
defaultTimeoutSec = 30
|
||||||
maxRetryAttempts = 10
|
maxRetryAttempts = 10
|
||||||
retryDelaySec = 5
|
retryDelaySec = 5
|
||||||
maxIdleTimeoutSec = 90
|
maxIdleTimeoutSec = 90
|
||||||
)
|
)
|
||||||
|
|
||||||
type CameraReport struct {
|
type CameraReport struct {
|
||||||
@@ -174,7 +174,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Create output directory
|
// Create output directory
|
||||||
if err := os.MkdirAll(*outputDir, 0755); err != nil {
|
if err := os.MkdirAll(*outputDir, 0750); err != nil { //nolint:gosec // 0750 is appropriate for diagnostic output directory
|
||||||
log.Fatalf("Failed to create output directory: %v", err)
|
log.Fatalf("Failed to create output directory: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -198,15 +198,15 @@ func main() {
|
|||||||
if *captureXML {
|
if *captureXML {
|
||||||
timestamp := time.Now().Format("20060102-150405")
|
timestamp := time.Now().Format("20060102-150405")
|
||||||
xmlCaptureDir = filepath.Join(*outputDir, "temp_"+timestamp)
|
xmlCaptureDir = filepath.Join(*outputDir, "temp_"+timestamp)
|
||||||
if err := os.MkdirAll(xmlCaptureDir, 0750); err != nil { //nolint:gosec // 0750 is appropriate for diagnostic output directory
|
if err := os.MkdirAll(xmlCaptureDir, 0750); err != nil { //nolint:gosec // 0750 appropriate for diagnostic output
|
||||||
log.Fatalf("Failed to create XML capture directory: %v", err)
|
log.Fatalf("Failed to create XML capture directory: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
loggingTransport = &LoggingTransport{
|
loggingTransport = &LoggingTransport{
|
||||||
Transport: &http.Transport{
|
Transport: &http.Transport{
|
||||||
MaxIdleConns: maxRetryAttempts,
|
MaxIdleConns: maxRetryAttempts,
|
||||||
MaxIdleConnsPerHost: retryDelaySec,
|
MaxIdleConnsPerHost: retryDelaySec,
|
||||||
IdleConnTimeout: maxIdleTimeoutSec * time.Second,
|
IdleConnTimeout: maxIdleTimeoutSec * time.Second,
|
||||||
},
|
},
|
||||||
LogDir: xmlCaptureDir,
|
LogDir: xmlCaptureDir,
|
||||||
Counter: 0,
|
Counter: 0,
|
||||||
@@ -883,7 +883,8 @@ func saveReport(report *CameraReport, filename string) error {
|
|||||||
return fmt.Errorf("failed to marshal report: %w", err)
|
return fmt.Errorf("failed to marshal report: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.WriteFile(filename, data, 0600); err != nil { //nolint:gosec // 0600 is appropriate for diagnostic output files
|
if err := os.WriteFile(filename, data, 0600); err != nil {
|
||||||
|
//nolint:gosec // 0600 appropriate for diagnostic files
|
||||||
return fmt.Errorf("failed to write file: %w", err)
|
return fmt.Errorf("failed to write file: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -895,20 +896,20 @@ func logStepf(format string, args ...interface{}) {
|
|||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
fmt.Printf("→ %s\n", fmt.Sprintf(format, args...))
|
fmt.Printf("→ %s\n", fmt.Sprintf(format, args...))
|
||||||
} else {
|
} else {
|
||||||
fmt.Printf("→ " + format + "\n")
|
fmt.Printf("→ %s\n", format)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func logSuccessf(format string, args ...interface{}) {
|
func logSuccessf(format string, args ...interface{}) {
|
||||||
fmt.Printf(" ✓ "+format+"\n", args...)
|
fmt.Printf(" ✓ %s\n", fmt.Sprintf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func logErrorf(format string, args ...interface{}) {
|
func logErrorf(format string, args ...interface{}) {
|
||||||
fmt.Printf(" ✗ "+format+"\n", args...)
|
fmt.Printf(" ✗ %s\n", fmt.Sprintf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
func logInfof(format string, args ...interface{}) {
|
func logInfof(format string, args ...interface{}) {
|
||||||
fmt.Printf(" ℹ "+format+"\n", args...)
|
fmt.Printf(" ℹ %s\n", fmt.Sprintf(format, args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// XML Capture functionality
|
// XML Capture functionality
|
||||||
@@ -1023,20 +1024,22 @@ func (t *LoggingTransport) saveCapture(capture *XMLCapture) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := os.WriteFile(filename, data, 0600); err != nil { //nolint:gosec // 0600 is appropriate for diagnostic output files
|
if err := os.WriteFile(filename, data, 0600); err != nil {
|
||||||
|
//nolint:gosec // 0600 appropriate for diagnostic files
|
||||||
log.Printf("Failed to write capture: %v", err)
|
log.Printf("Failed to write capture: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pretty-print and save XML files for easier viewing
|
// Pretty-print and save XML files for easier viewing
|
||||||
reqFile := filepath.Join(t.LogDir, baseFilename+"_request.xml")
|
reqFile := filepath.Join(t.LogDir, baseFilename+"_request.xml")
|
||||||
prettyRequest := prettyPrintXML(capture.RequestBody)
|
prettyRequest := prettyPrintXML(capture.RequestBody)
|
||||||
if err := os.WriteFile(reqFile, []byte(prettyRequest), 0644); err != nil {
|
if err := os.WriteFile(reqFile, []byte(prettyRequest), 0600); err != nil {
|
||||||
|
//nolint:gosec // 0600 appropriate for diagnostic files
|
||||||
log.Printf("Failed to write request XML: %v", err)
|
log.Printf("Failed to write request XML: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
respFile := filepath.Join(t.LogDir, baseFilename+"_response.xml")
|
respFile := filepath.Join(t.LogDir, baseFilename+"_response.xml")
|
||||||
prettyResponse := prettyPrintXML(capture.ResponseBody)
|
prettyResponse := prettyPrintXML(capture.ResponseBody)
|
||||||
if err := os.WriteFile(respFile, []byte(prettyResponse), 0644); err != nil {
|
if err := os.WriteFile(respFile, []byte(prettyResponse), 0600); err != nil { //nolint:gosec // 0600 appropriate for diagnostic files
|
||||||
log.Printf("Failed to write response XML: %v", err)
|
log.Printf("Failed to write response XML: %v", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1049,13 +1052,13 @@ func extractSOAPOperation(soapBody string) string {
|
|||||||
// Find the Body element
|
// Find the Body element
|
||||||
bodyStart := strings.Index(soapBody, "<Body")
|
bodyStart := strings.Index(soapBody, "<Body")
|
||||||
if bodyStart == -1 {
|
if bodyStart == -1 {
|
||||||
return "Unknown"
|
return unknownStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
// Find the closing > of the Body opening tag
|
// Find the closing > of the Body opening tag
|
||||||
bodyOpenEnd := strings.Index(soapBody[bodyStart:], ">")
|
bodyOpenEnd := strings.Index(soapBody[bodyStart:], ">")
|
||||||
if bodyOpenEnd == -1 {
|
if bodyOpenEnd == -1 {
|
||||||
return "Unknown"
|
return unknownStatus
|
||||||
}
|
}
|
||||||
bodyContentStart := bodyStart + bodyOpenEnd + 1
|
bodyContentStart := bodyStart + bodyOpenEnd + 1
|
||||||
|
|
||||||
@@ -1066,7 +1069,7 @@ func extractSOAPOperation(soapBody string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if bodyContentStart >= len(soapBody) || soapBody[bodyContentStart] != '<' {
|
if bodyContentStart >= len(soapBody) || soapBody[bodyContentStart] != '<' {
|
||||||
return "Unknown"
|
return unknownStatus
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extract the tag name
|
// Extract the tag name
|
||||||
@@ -1092,7 +1095,7 @@ func extractSOAPOperation(soapBody string) string {
|
|||||||
// createTarGz creates a tar.gz archive from a directory.
|
// createTarGz creates a tar.gz archive from a directory.
|
||||||
func createTarGz(sourceDir, archivePath string) error {
|
func createTarGz(sourceDir, archivePath string) error {
|
||||||
// Create archive file
|
// Create archive file
|
||||||
archiveFile, err := os.Create(archivePath)
|
archiveFile, err := os.Create(archivePath) //nolint:gosec // Archive path is validated before use
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create archive file: %w", err)
|
return fmt.Errorf("failed to create archive file: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ func connectAndShowInfo() {
|
|||||||
client, err := onvif.NewClient(
|
client, err := onvif.NewClient(
|
||||||
endpoint,
|
endpoint,
|
||||||
onvif.WithCredentials(username, password),
|
onvif.WithCredentials(username, password),
|
||||||
onvif.WithTimeout(30*time.Second),
|
onvif.WithTimeout(ptzTimeout*time.Second),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("❌ Error: %v\n", err)
|
fmt.Printf("❌ Error: %v\n", err)
|
||||||
@@ -311,7 +311,7 @@ func ptzDemo() {
|
|||||||
|
|
||||||
switch choice {
|
switch choice {
|
||||||
case "1":
|
case "1":
|
||||||
velocity = &onvif.PTZSpeed{PanTilt: &onvif.Vector2D{X: 0.5, Y: 0.0}}
|
velocity = &onvif.PTZSpeed{PanTilt: &onvif.Vector2D{X: ptzSpeed, Y: 0.0}}
|
||||||
case "2":
|
case "2":
|
||||||
velocity = &onvif.PTZSpeed{PanTilt: &onvif.Vector2D{X: -ptzSpeed, Y: 0.0}}
|
velocity = &onvif.PTZSpeed{PanTilt: &onvif.Vector2D{X: -ptzSpeed, Y: 0.0}}
|
||||||
case "3":
|
case "3":
|
||||||
@@ -335,7 +335,7 @@ func ptzDemo() {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println("✅ Moving for 2 seconds...")
|
fmt.Println("✅ Moving for 2 seconds...")
|
||||||
time.Sleep(2 * time.Second)
|
time.Sleep(ptzStepSize * time.Second)
|
||||||
//nolint:errcheck // Stop error is not critical for demo
|
//nolint:errcheck // Stop error is not critical for demo
|
||||||
_ = client.Stop(ctx, profileToken, true, false)
|
_ = client.Stop(ctx, profileToken, true, false)
|
||||||
} else if position != nil {
|
} else if position != nil {
|
||||||
|
|||||||
+12
-12
@@ -19,13 +19,13 @@ var (
|
|||||||
|
|
||||||
//nolint:funlen // Main function has many statements due to server setup and configuration
|
//nolint:funlen // Main function has many statements due to server setup and configuration
|
||||||
const (
|
const (
|
||||||
defaultPort = 8080
|
defaultPort = 8080
|
||||||
maxWorkers = 3
|
maxWorkers = 3
|
||||||
defaultTimeout = 30
|
defaultTimeout = 30
|
||||||
ptzStepSize = 5
|
ptzStepSize = 5
|
||||||
ptzMaxPan = 180
|
ptzMaxPan = 180
|
||||||
ptzMaxTilt = 90
|
ptzMaxTilt = 90
|
||||||
ptzSpeed = 0.5
|
ptzSpeed = 0.5
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@@ -126,7 +126,7 @@ func buildConfig(host string, port int, username, password, manufacturer, model,
|
|||||||
Host: host,
|
Host: host,
|
||||||
Port: port,
|
Port: port,
|
||||||
BasePath: "/onvif",
|
BasePath: "/onvif",
|
||||||
Timeout: 30 * time.Second,
|
Timeout: defaultTimeout * time.Second,
|
||||||
DeviceInfo: server.DeviceInfo{
|
DeviceInfo: server.DeviceInfo{
|
||||||
Manufacturer: manufacturer,
|
Manufacturer: manufacturer,
|
||||||
Model: model,
|
Model: model,
|
||||||
@@ -198,10 +198,10 @@ func buildConfig(host string, port int, username, password, manufacturer, model,
|
|||||||
if ptz && template.hasPTZ {
|
if ptz && template.hasPTZ {
|
||||||
profile.PTZ = &server.PTZConfig{
|
profile.PTZ = &server.PTZConfig{
|
||||||
NodeToken: fmt.Sprintf("ptz_node_%d", i),
|
NodeToken: fmt.Sprintf("ptz_node_%d", i),
|
||||||
PanRange: server.Range{Min: -180, Max: 180},
|
PanRange: server.Range{Min: -ptzMaxPan, Max: ptzMaxPan},
|
||||||
TiltRange: server.Range{Min: -90, Max: 90},
|
TiltRange: server.Range{Min: -ptzMaxTilt, Max: ptzMaxTilt},
|
||||||
ZoomRange: server.Range{Min: 0, Max: template.ptzZoomMax},
|
ZoomRange: server.Range{Min: 0, Max: template.ptzZoomMax},
|
||||||
DefaultSpeed: server.PTZSpeed{Pan: 0.5, Tilt: 0.5, Zoom: 0.5},
|
DefaultSpeed: server.PTZSpeed{Pan: ptzSpeed, Tilt: ptzSpeed, Zoom: ptzSpeed},
|
||||||
SupportsContinuous: true,
|
SupportsContinuous: true,
|
||||||
SupportsAbsolute: true,
|
SupportsAbsolute: true,
|
||||||
SupportsRelative: true,
|
SupportsRelative: true,
|
||||||
@@ -214,7 +214,7 @@ func buildConfig(host string, port int, username, password, manufacturer, model,
|
|||||||
{
|
{
|
||||||
Token: fmt.Sprintf("preset_%d_1", i),
|
Token: fmt.Sprintf("preset_%d_1", i),
|
||||||
Name: "Entrance",
|
Name: "Entrance",
|
||||||
Position: server.PTZPosition{Pan: -45, Tilt: -10, Zoom: template.ptzZoomMax * 0.5},
|
Position: server.PTZPosition{Pan: -45, Tilt: -10, Zoom: template.ptzZoomMax * ptzSpeed}, //nolint:mnd // Preset position values
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -694,7 +694,9 @@ func (c *Client) GetMediaServiceCapabilities(ctx context.Context) (*MediaService
|
|||||||
// GetVideoEncoderConfigurationOptions retrieves available options for video encoder configuration.
|
// GetVideoEncoderConfigurationOptions retrieves available options for video encoder configuration.
|
||||||
//
|
//
|
||||||
//nolint:funlen // GetVideoEncoderConfigurationOptions has many statements due to parsing complex encoder options
|
//nolint:funlen // GetVideoEncoderConfigurationOptions has many statements due to parsing complex encoder options
|
||||||
func (c *Client) GetVideoEncoderConfigurationOptions(ctx context.Context, configurationToken string) (*VideoEncoderConfigurationOptions, error) {
|
func (c *Client) GetVideoEncoderConfigurationOptions(
|
||||||
|
ctx context.Context, configurationToken string,
|
||||||
|
) (*VideoEncoderConfigurationOptions, error) {
|
||||||
endpoint := c.mediaEndpoint
|
endpoint := c.mediaEndpoint
|
||||||
if endpoint == "" {
|
if endpoint == "" {
|
||||||
endpoint = c.endpoint
|
endpoint = c.endpoint
|
||||||
|
|||||||
+4
-4
@@ -266,12 +266,12 @@ func (s *Server) HandleGetServices(body interface{}) (interface{}, error) {
|
|||||||
{
|
{
|
||||||
Namespace: "http://www.onvif.org/ver10/device/wsdl",
|
Namespace: "http://www.onvif.org/ver10/device/wsdl",
|
||||||
XAddr: baseURL + "/device_service",
|
XAddr: baseURL + "/device_service",
|
||||||
Version: Version{Major: 2, Minor: 5},
|
Version: Version{Major: 2, Minor: 5}, //nolint:mnd // ONVIF version
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Namespace: "http://www.onvif.org/ver10/media/wsdl",
|
Namespace: "http://www.onvif.org/ver10/media/wsdl",
|
||||||
XAddr: baseURL + "/media_service",
|
XAddr: baseURL + "/media_service",
|
||||||
Version: Version{Major: 2, Minor: 5},
|
Version: Version{Major: 2, Minor: 5}, //nolint:mnd // ONVIF version
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -279,7 +279,7 @@ func (s *Server) HandleGetServices(body interface{}) (interface{}, error) {
|
|||||||
services = append(services, Service{
|
services = append(services, Service{
|
||||||
Namespace: "http://www.onvif.org/ver20/ptz/wsdl",
|
Namespace: "http://www.onvif.org/ver20/ptz/wsdl",
|
||||||
XAddr: baseURL + "/ptz_service",
|
XAddr: baseURL + "/ptz_service",
|
||||||
Version: Version{Major: 2, Minor: 5},
|
Version: Version{Major: 2, Minor: 5}, //nolint:mnd // ONVIF version
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -287,7 +287,7 @@ func (s *Server) HandleGetServices(body interface{}) (interface{}, error) {
|
|||||||
services = append(services, Service{
|
services = append(services, Service{
|
||||||
Namespace: "http://www.onvif.org/ver20/imaging/wsdl",
|
Namespace: "http://www.onvif.org/ver20/imaging/wsdl",
|
||||||
XAddr: baseURL + "/imaging_service",
|
XAddr: baseURL + "/imaging_service",
|
||||||
Version: Version{Major: 2, Minor: 5},
|
Version: Version{Major: 2, Minor: 5}, //nolint:mnd // ONVIF version
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+13
-11
@@ -347,25 +347,27 @@ func (s *Server) HandleSetImagingSettings(body interface{}) (interface{}, error)
|
|||||||
// HandleGetOptions handles GetOptions request.
|
// HandleGetOptions handles GetOptions request.
|
||||||
func (s *Server) HandleGetOptions(body interface{}) (interface{}, error) {
|
func (s *Server) HandleGetOptions(body interface{}) (interface{}, error) {
|
||||||
// Return available imaging options/capabilities
|
// Return available imaging options/capabilities
|
||||||
|
const maxImagingValue = 100 //nolint:mnd // Maximum imaging parameter value
|
||||||
|
const maxExposureTime = 10000 //nolint:mnd // Maximum exposure time in microseconds
|
||||||
options := &ImagingOptions{
|
options := &ImagingOptions{
|
||||||
Brightness: &FloatRange{Min: 0, Max: 100},
|
Brightness: &FloatRange{Min: 0, Max: maxImagingValue},
|
||||||
ColorSaturation: &FloatRange{Min: 0, Max: 100},
|
ColorSaturation: &FloatRange{Min: 0, Max: maxImagingValue},
|
||||||
Contrast: &FloatRange{Min: 0, Max: 100},
|
Contrast: &FloatRange{Min: 0, Max: maxImagingValue},
|
||||||
Sharpness: &FloatRange{Min: 0, Max: 100},
|
Sharpness: &FloatRange{Min: 0, Max: maxImagingValue},
|
||||||
IrCutFilterModes: []string{"ON", "OFF", "AUTO"},
|
IrCutFilterModes: []string{"ON", "OFF", "AUTO"},
|
||||||
BacklightCompensation: &BacklightCompensationOptions{
|
BacklightCompensation: &BacklightCompensationOptions{
|
||||||
Mode: []string{"OFF", "ON"},
|
Mode: []string{"OFF", "ON"},
|
||||||
Level: &FloatRange{Min: 0, Max: 100},
|
Level: &FloatRange{Min: 0, Max: maxImagingValue},
|
||||||
},
|
},
|
||||||
Exposure: &ExposureOptions{
|
Exposure: &ExposureOptions{
|
||||||
Mode: []string{"AUTO", "MANUAL"},
|
Mode: []string{"AUTO", "MANUAL"},
|
||||||
Priority: []string{"LowNoise", "FrameRate"},
|
Priority: []string{"LowNoise", "FrameRate"},
|
||||||
MinExposureTime: &FloatRange{Min: 1, Max: 10000},
|
MinExposureTime: &FloatRange{Min: 1, Max: maxExposureTime},
|
||||||
MaxExposureTime: &FloatRange{Min: 1, Max: 10000},
|
MaxExposureTime: &FloatRange{Min: 1, Max: maxExposureTime},
|
||||||
MinGain: &FloatRange{Min: 0, Max: 100},
|
MinGain: &FloatRange{Min: 0, Max: maxImagingValue},
|
||||||
MaxGain: &FloatRange{Min: 0, Max: 100},
|
MaxGain: &FloatRange{Min: 0, Max: maxImagingValue},
|
||||||
ExposureTime: &FloatRange{Min: 1, Max: 10000},
|
ExposureTime: &FloatRange{Min: 1, Max: maxExposureTime},
|
||||||
Gain: &FloatRange{Min: 0, Max: 100},
|
Gain: &FloatRange{Min: 0, Max: maxImagingValue},
|
||||||
},
|
},
|
||||||
Focus: &FocusOptions{
|
Focus: &FocusOptions{
|
||||||
AutoFocusModes: []string{"AUTO", "MANUAL"},
|
AutoFocusModes: []string{"AUTO", "MANUAL"},
|
||||||
|
|||||||
+6
-4
@@ -268,7 +268,7 @@ func (s *Server) HandleAbsoluteMove(body interface{}) (interface{}, error) {
|
|||||||
// In a real implementation, simulate movement over time
|
// In a real implementation, simulate movement over time
|
||||||
// For now, we'll stop immediately
|
// For now, we'll stop immediately
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(500 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond) //nolint:mnd // PTZ movement delay
|
||||||
ptzMutex.Lock()
|
ptzMutex.Lock()
|
||||||
state.Moving = false
|
state.Moving = false
|
||||||
state.PanMoving = false
|
state.PanMoving = false
|
||||||
@@ -306,8 +306,10 @@ func (s *Server) HandleRelativeMove(body interface{}) (interface{}, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clamp values to valid ranges (simplified)
|
// Clamp values to valid ranges (simplified)
|
||||||
state.Position.Pan = clamp(state.Position.Pan, -180, 180)
|
const maxPan = 180 //nolint:mnd // PTZ pan range
|
||||||
state.Position.Tilt = clamp(state.Position.Tilt, -90, 90)
|
const maxTilt = 90 //nolint:mnd // PTZ tilt range
|
||||||
|
state.Position.Pan = clamp(state.Position.Pan, -maxPan, maxPan)
|
||||||
|
state.Position.Tilt = clamp(state.Position.Tilt, -maxTilt, maxTilt)
|
||||||
state.Position.Zoom = clamp(state.Position.Zoom, 0, 1)
|
state.Position.Zoom = clamp(state.Position.Zoom, 0, 1)
|
||||||
|
|
||||||
state.Moving = true
|
state.Moving = true
|
||||||
@@ -315,7 +317,7 @@ func (s *Server) HandleRelativeMove(body interface{}) (interface{}, error) {
|
|||||||
|
|
||||||
// Simulate movement completion
|
// Simulate movement completion
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(500 * time.Millisecond)
|
time.Sleep(500 * time.Millisecond) //nolint:mnd // PTZ movement delay
|
||||||
ptzMutex.Lock()
|
ptzMutex.Lock()
|
||||||
state.Moving = false
|
state.Moving = false
|
||||||
state.PanMoving = false
|
state.PanMoving = false
|
||||||
|
|||||||
+2
-1
@@ -160,7 +160,8 @@ func (s *Server) Start(ctx context.Context) error {
|
|||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
fmt.Println("\n🛑 Shutting down server...")
|
fmt.Println("\n🛑 Shutting down server...")
|
||||||
shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
const shutdownTimeout = 5 //nolint:mnd // Server shutdown timeout in seconds
|
||||||
|
shutdownCtx, cancel := context.WithTimeout(context.Background(), shutdownTimeout*time.Second)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
if err := httpServer.Shutdown(shutdownCtx); err != nil {
|
if err := httpServer.Shutdown(shutdownCtx); err != nil {
|
||||||
|
|||||||
+2
-1
@@ -363,7 +363,8 @@ func (c *Config) ServiceEndpoints(host string) map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var baseURL string
|
var baseURL string
|
||||||
if c.Port == 80 {
|
const httpPort = 80 //nolint:mnd // Standard HTTP port
|
||||||
|
if c.Port == httpPort {
|
||||||
baseURL = "http://" + host + c.BasePath
|
baseURL = "http://" + host + c.BasePath
|
||||||
} else {
|
} else {
|
||||||
// Import fmt at the top to use Sprintf
|
// Import fmt at the top to use Sprintf
|
||||||
|
|||||||
Reference in New Issue
Block a user