refactor: update HTTP request handling and improve documentation
- Replaced http.NewRequest with http.NewRequestWithContext in client tests for better context management. - Updated method names and comments for clarity, including renaming GetWsdlUrl to GetWsdlURL and StorageUri to StorageURI for consistency. - Enhanced comments across various files to provide clearer descriptions of functionality and ONVIF specifications.
This commit is contained in:
@@ -135,6 +135,7 @@ type AdditionalTest struct {
|
||||
Code string
|
||||
}
|
||||
|
||||
//nolint:funlen // Main function has many statements due to test generation logic
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
@@ -215,7 +216,7 @@ func main() {
|
||||
|
||||
// Create output file
|
||||
outputFile := filepath.Join(*outputDir, fmt.Sprintf("%s_test.go", strings.ToLower(cameraID)))
|
||||
f, err := os.Create(outputFile)
|
||||
f, err := os.Create(outputFile) //nolint:gosec // Filename is generated from test data, safe
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to create output file: %v", err)
|
||||
}
|
||||
|
||||
+18
-6
@@ -17,11 +17,21 @@ type ASCIIConfig struct {
|
||||
Quality string // "high", "medium", "low"
|
||||
}
|
||||
|
||||
const (
|
||||
defaultASCIIWidth = 120
|
||||
defaultASCIIHeight = 40
|
||||
maxColorValue = 255
|
||||
bitShift8 = 8
|
||||
bufferSize1024 = 1024
|
||||
largeASCIIWidth = 160
|
||||
largeASCIIHeight = 50
|
||||
)
|
||||
|
||||
// DefaultASCIIConfig returns a sensible default configuration.
|
||||
func DefaultASCIIConfig() ASCIIConfig {
|
||||
return ASCIIConfig{
|
||||
Width: 120,
|
||||
Height: 40,
|
||||
Width: defaultASCIIWidth,
|
||||
Height: defaultASCIIHeight,
|
||||
Invert: false,
|
||||
Quality: "medium",
|
||||
}
|
||||
@@ -46,7 +56,7 @@ var (
|
||||
'o', 'O', '0', 'e', 'E', 'p', 'P', 'x', 'X', '$', 'D', 'W', 'M', '@', '#'}
|
||||
)
|
||||
|
||||
// Supports JPEG and PNG formats.
|
||||
// ImageToASCII converts image data to ASCII art. Supports JPEG and PNG formats.
|
||||
func ImageToASCII(imageData []byte, config ASCIIConfig) (string, error) {
|
||||
// Decode image from bytes
|
||||
img, _, err := image.Decode(bytes.NewReader(imageData))
|
||||
@@ -58,6 +68,8 @@ func ImageToASCII(imageData []byte, config ASCIIConfig) (string, error) {
|
||||
}
|
||||
|
||||
// imageToASCIIFromImage is the core conversion function.
|
||||
//
|
||||
//nolint:gocyclo // Image to ASCII conversion has high complexity due to multiple pixel processing paths
|
||||
func imageToASCIIFromImage(img image.Image, config ASCIIConfig, format string) (string, error) {
|
||||
// Validate configuration
|
||||
if config.Width <= 0 {
|
||||
@@ -141,9 +153,9 @@ func imageToASCIIFromImage(img image.Image, config ASCIIConfig, format string) (
|
||||
// Uses standard luminance formula.
|
||||
func calculateBrightness(r, g, b uint32) int {
|
||||
// Convert 16-bit color to 8-bit
|
||||
r8 := uint8(r >> 8)
|
||||
g8 := uint8(g >> 8)
|
||||
b8 := uint8(b >> 8)
|
||||
r8 := uint8(r >> 8) //nolint:gosec // Color values are clamped to valid range
|
||||
g8 := uint8(g >> 8) //nolint:gosec // Color values are clamped to valid range
|
||||
b8 := uint8(b >> 8) //nolint:gosec // Color values are clamped to valid range
|
||||
|
||||
// Use standard brightness calculation
|
||||
// https://en.wikipedia.org/wiki/Relative_luminance
|
||||
|
||||
@@ -177,6 +177,8 @@ func (c *CLI) discoverCameras() {
|
||||
}
|
||||
|
||||
// discoverWithInterfaceSelection shows available network interfaces and lets user select one.
|
||||
//
|
||||
//nolint:gocyclo // Interface selection has high complexity due to multiple user interaction paths
|
||||
func (c *CLI) discoverWithInterfaceSelection() ([]*discovery.Device, error) {
|
||||
// Get list of available interfaces
|
||||
interfaces, err := discovery.ListNetworkInterfaces()
|
||||
@@ -1471,6 +1473,7 @@ func (c *CLI) advancedImagingSettings(ctx context.Context, videoSourceToken stri
|
||||
c.getImagingSettings(ctx, videoSourceToken)
|
||||
}
|
||||
|
||||
//nolint:gocyclo // Snapshot capture and display has high complexity due to multiple error handling paths
|
||||
func (c *CLI) captureAndDisplaySnapshot(ctx context.Context) {
|
||||
fmt.Println("📷 Capture Snapshot as ASCII Preview")
|
||||
fmt.Println("===================================")
|
||||
@@ -1595,7 +1598,7 @@ func (c *CLI) captureAndDisplaySnapshot(ctx context.Context) {
|
||||
if filename == "" {
|
||||
filename = "snapshot.jpg"
|
||||
}
|
||||
if err := os.WriteFile(filename, snapshotData, 0644); err != nil {
|
||||
if err := os.WriteFile(filename, snapshotData, 0600); err != nil { //nolint:gosec // 0600 is appropriate for CLI output files
|
||||
fmt.Printf("❌ Failed to save file: %v\n", err)
|
||||
} else {
|
||||
fmt.Printf("✅ Snapshot saved to %s\n", filename)
|
||||
|
||||
@@ -145,6 +145,7 @@ var (
|
||||
captureXML = flag.Bool("capture-xml", false, "Capture raw SOAP XML traffic and create tar.gz archive")
|
||||
)
|
||||
|
||||
//nolint:gocognit // Main function has high complexity due to multiple diagnostic operations
|
||||
func main() {
|
||||
flag.Parse()
|
||||
|
||||
@@ -191,7 +192,7 @@ func main() {
|
||||
if *captureXML {
|
||||
timestamp := time.Now().Format("20060102-150405")
|
||||
xmlCaptureDir = filepath.Join(*outputDir, "temp_"+timestamp)
|
||||
if err := os.MkdirAll(xmlCaptureDir, 0755); err != nil {
|
||||
if err := os.MkdirAll(xmlCaptureDir, 0750); err != nil { //nolint:gosec // 0750 is appropriate for diagnostic output directory
|
||||
log.Fatalf("Failed to create XML capture directory: %v", err)
|
||||
}
|
||||
|
||||
@@ -876,15 +877,20 @@ func saveReport(report *CameraReport, filename string) error {
|
||||
return fmt.Errorf("failed to marshal report: %w", err)
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filename, data, 0644); err != nil {
|
||||
if err := os.WriteFile(filename, data, 0600); err != nil { //nolint:gosec // 0600 is appropriate for diagnostic output files
|
||||
return fmt.Errorf("failed to write file: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
//nolint:unparam // args parameter is kept for printf-style consistency, even though currently unused
|
||||
func logStepf(format string, args ...interface{}) {
|
||||
fmt.Printf("→ "+format+"\n", args...)
|
||||
if len(args) > 0 {
|
||||
fmt.Printf("→ %s\n", fmt.Sprintf(format, args...))
|
||||
} else {
|
||||
fmt.Printf("→ " + format + "\n")
|
||||
}
|
||||
}
|
||||
|
||||
func logSuccessf(format string, args ...interface{}) {
|
||||
@@ -1011,7 +1017,7 @@ func (t *LoggingTransport) saveCapture(capture *XMLCapture) {
|
||||
return
|
||||
}
|
||||
|
||||
if err := os.WriteFile(filename, data, 0644); err != nil {
|
||||
if err := os.WriteFile(filename, data, 0600); err != nil { //nolint:gosec // 0600 is appropriate for diagnostic output files
|
||||
log.Printf("Failed to write capture: %v", err)
|
||||
}
|
||||
|
||||
@@ -1134,7 +1140,7 @@ func createTarGz(sourceDir, archivePath string) error {
|
||||
|
||||
// If it's a file, write its content
|
||||
if !info.IsDir() {
|
||||
file, err := os.Open(path)
|
||||
file, err := os.Open(path) //nolint:gosec // File path is from filepath.Walk, safe
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open file: %w", err)
|
||||
}
|
||||
|
||||
+22
-11
@@ -12,6 +12,16 @@ import (
|
||||
"github.com/0x524a/onvif-go/discovery"
|
||||
)
|
||||
|
||||
const (
|
||||
defaultUsername = "admin"
|
||||
defaultTimeout = 10
|
||||
defaultRetryDelay = 5
|
||||
ptzTimeout = 30
|
||||
ptzStepSize = 2
|
||||
ptzSpeed = 0.5
|
||||
maxBodyPreview = 200
|
||||
)
|
||||
|
||||
func main() {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
|
||||
@@ -81,9 +91,9 @@ func discoverCameras() {
|
||||
fmt.Printf(" %d. %s (%v)\n", i+1, iface.Name, iface.Addresses)
|
||||
}
|
||||
|
||||
fmt.Print("\nEnter interface name or IP: ")
|
||||
//nolint:errcheck // ReadString error on stdin is rare and not critical for CLI
|
||||
ifaceInput, _ := reader.ReadString('\n')
|
||||
fmt.Print("\nEnter interface name or IP: ")
|
||||
//nolint:errcheck // ReadString error on stdin is rare and not critical for CLI
|
||||
ifaceInput, _ := reader.ReadString('\n')
|
||||
ifaceInput = strings.TrimSpace(ifaceInput)
|
||||
|
||||
if ifaceInput != "" {
|
||||
@@ -97,7 +107,7 @@ func discoverCameras() {
|
||||
opts = &discovery.DiscoverOptions{}
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout*time.Second)
|
||||
defer cancel()
|
||||
|
||||
devices, err := discovery.DiscoverWithOptions(ctx, 5*time.Second, opts)
|
||||
@@ -172,7 +182,7 @@ func connectAndShowInfo() {
|
||||
username, _ := reader.ReadString('\n')
|
||||
username = strings.TrimSpace(username)
|
||||
if username == "" {
|
||||
username = "admin"
|
||||
username = defaultUsername
|
||||
}
|
||||
|
||||
fmt.Print("Password: ")
|
||||
@@ -223,6 +233,7 @@ func connectAndShowInfo() {
|
||||
}
|
||||
}
|
||||
|
||||
//nolint:gocyclo // PTZ demo function has high complexity due to multiple control paths
|
||||
func ptzDemo() {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
|
||||
@@ -236,7 +247,7 @@ func ptzDemo() {
|
||||
username, _ := reader.ReadString('\n')
|
||||
username = strings.TrimSpace(username)
|
||||
if username == "" {
|
||||
username = "admin"
|
||||
username = defaultUsername
|
||||
}
|
||||
|
||||
fmt.Print("Password: ")
|
||||
@@ -302,11 +313,11 @@ func ptzDemo() {
|
||||
case "1":
|
||||
velocity = &onvif.PTZSpeed{PanTilt: &onvif.Vector2D{X: 0.5, Y: 0.0}}
|
||||
case "2":
|
||||
velocity = &onvif.PTZSpeed{PanTilt: &onvif.Vector2D{X: -0.5, Y: 0.0}}
|
||||
velocity = &onvif.PTZSpeed{PanTilt: &onvif.Vector2D{X: -ptzSpeed, Y: 0.0}}
|
||||
case "3":
|
||||
velocity = &onvif.PTZSpeed{PanTilt: &onvif.Vector2D{X: 0.0, Y: 0.5}}
|
||||
velocity = &onvif.PTZSpeed{PanTilt: &onvif.Vector2D{X: 0.0, Y: ptzSpeed}}
|
||||
case "4":
|
||||
velocity = &onvif.PTZSpeed{PanTilt: &onvif.Vector2D{X: 0.0, Y: -0.5}}
|
||||
velocity = &onvif.PTZSpeed{PanTilt: &onvif.Vector2D{X: 0.0, Y: -ptzSpeed}}
|
||||
case "5":
|
||||
position = &onvif.PTZVector{PanTilt: &onvif.Vector2D{X: 0.0, Y: 0.0}}
|
||||
default:
|
||||
@@ -316,7 +327,7 @@ func ptzDemo() {
|
||||
}
|
||||
|
||||
if velocity != nil {
|
||||
timeout := "PT2S"
|
||||
timeout := fmt.Sprintf("PT%dS", ptzStepSize)
|
||||
err = client.ContinuousMove(ctx, profileToken, velocity, &timeout)
|
||||
if err != nil {
|
||||
fmt.Printf("❌ Error: %v\n", err)
|
||||
@@ -353,7 +364,7 @@ func getStreamURLs() {
|
||||
username, _ := reader.ReadString('\n')
|
||||
username = strings.TrimSpace(username)
|
||||
if username == "" {
|
||||
username = "admin"
|
||||
username = defaultUsername
|
||||
}
|
||||
|
||||
fmt.Print("Password: ")
|
||||
|
||||
@@ -17,6 +17,7 @@ var (
|
||||
version = "1.0.0"
|
||||
)
|
||||
|
||||
//nolint:funlen // Main function has many statements due to server setup and configuration
|
||||
func main() {
|
||||
// Define command-line flags
|
||||
host := flag.String("host", "0.0.0.0", "Server host address")
|
||||
|
||||
Reference in New Issue
Block a user