Files
onvif-go/docs/XML_DEBUGGING_SOLUTION.md
T

381 lines
9.5 KiB
Markdown

# ONVIF Debugging Solution
## Problem
The diagnostic utility (`onvif-diagnostics`) logs only parsed JSON results. When XML parsing fails or responses are unexpected, you can't see the raw SOAP XML to debug the issue.
## Solution
The `onvif-diagnostics` utility now includes built-in XML capture functionality via the `-capture-xml` flag. This captures raw SOAP request/response XML and creates a compressed tar.gz archive.
## What Changed
### 1. Enhanced SOAP Client (`soap/soap.go`)
Added debug logging capability:
```go
type Client struct {
httpClient *http.Client
username string
password string
debug bool // NEW
logger func(format string, args ...interface{}) // NEW
}
// New methods:
func (c *Client) SetDebug(enabled bool, logger func(format string, args ...interface{}))
func (c *Client) logDebug(format string, args ...interface{})
```
The SOAP client now logs requests/responses when debug mode is enabled.
### 2. Integrated XML Capture in `onvif-diagnostics`
Location: `cmd/onvif-diagnostics/main.go`
Features:
- Single command for both diagnostic report and XML capture
- `-capture-xml` flag enables raw SOAP traffic capture
- Creates compressed tar.gz archive with camera identification
- Archive naming: `Manufacturer_Model_Firmware_xmlcapture_timestamp.tar.gz`
- Saves to `camera-logs/` directory (same as diagnostic report)
- Automatic cleanup of temporary files
## Usage
### Quick Start
```bash
# Build the utility
go build -o onvif-diagnostics ./cmd/onvif-diagnostics/
# Run with XML capture enabled
./onvif-diagnostics \
-endpoint "http://192.168.1.164/onvif/device_service" \
-username "admin" \
-password "password" \
-capture-xml \
-verbose
```
This creates two files:
- `Manufacturer_Model_Firmware_timestamp.json` - Diagnostic report
- `Manufacturer_Model_Firmware_xmlcapture_timestamp.tar.gz` - Raw SOAP XML archive
### Without XML Capture (Faster)
```bash
# Just diagnostic report
./onvif-diagnostics \
-endpoint "http://192.168.1.164/onvif/device_service" \
-username "admin" \
-password "password" \
-verbose
```
### Extract and Analyze XML
```bash
# Extract the archive
tar -xzf camera-logs/Camera_Model_xmlcapture_timestamp.tar.gz -C /tmp/xml-debug
# View files (now with operation names)
ls /tmp/xml-debug/
# capture_001_GetDeviceInformation.json
# capture_001_GetDeviceInformation_request.xml
# capture_001_GetDeviceInformation_response.xml
# capture_002_GetSystemDateAndTime.json
# ...
```
## Workflow
### 1. Run Diagnostic with XML Capture
```bash
./onvif-diagnostics \
-endpoint "http://camera-ip/onvif/device_service" \
-username "user" \
-password "pass" \
-capture-xml \
-verbose
```
This generates both:
- JSON diagnostic report
- tar.gz XML capture archive
### 2. Review Diagnostic Report
Check the JSON file for errors:
```bash
cat camera-logs/Camera_Model_Firmware_timestamp.json | jq '.errors'
```
### 3. Analyze Raw XML (if needed)
Extract and inspect the XML archive:
```bash
tar -xzf camera-logs/Camera_Model_xmlcapture_timestamp.tar.gz -C /tmp/xml-debug
```
### 3. Analyze Raw XML
```bash
# Extract the archive
tar -xzf camera-logs/Camera_Model_xmlcapture_timestamp.tar.gz -C /tmp/xml-debug
# View specific operation (now easier to find)
cat /tmp/xml-debug/capture_*_GetCapabilities_response.xml
# Search for errors
grep "Fault" /tmp/xml-debug/capture_*_response.xml
# Pretty-print (XML is already formatted with indentation)
cat /tmp/xml-debug/capture_001_GetDeviceInformation_response.xml
```
## Example: Debugging AXIS Q3626-VE Localhost Issue
### Problem (from diagnostic report)
```json
{
"operation": "GetProfiles",
"error": "Post \"http://127.0.0.1/onvif/services\": EOF"
}
```
### Capture XML
```bash
### Capture XML
```bash
./onvif-diagnostics \
-endpoint "http://192.168.1.164/onvif/device_service" \
-username "admin" \
-password "password" \
-capture-xml \
-verbose
```
Result:
- `camera-logs/AXIS_Q3626-VE_12.6.104_20251110-120000.json`
- `camera-logs/AXIS_Q3626-VE_12.6.104_xmlcapture_20251110-120000.tar.gz`
```
Result: `camera-logs/AXIS_Q3626-VE_12.6.104_xmlcapture_20251110-120000.tar.gz`
### Analyze Response
```bash
tar -xzf camera-logs/AXIS_Q3626-VE_12.6.104_xmlcapture_20251110-120000.tar.gz
cat capture_*_GetCapabilities_response.xml | grep XAddr
```
Shows:
```xml
<Media>
<XAddr>http://127.0.0.1/onvif/services</XAddr>
</Media>
```
### Root Cause
Camera returns `127.0.0.1` instead of actual IP `192.168.1.164`, causing client to connect to localhost.
### Solution Required
Client needs to rewrite localhost addresses:
```go
if strings.Contains(xAddr, "127.0.0.1") || strings.Contains(xAddr, "localhost") {
// Replace with actual camera IP from original endpoint
}
```
## Example: Debugging Bosch Panoramic "Incomplete Configuration"
### Problem (from diagnostic report)
```json
{
"operation": "GetStreamURI[9]",
"error": "ter:IncompleteConfiguration - Configuration not complete"
}
```
### Capture XML
```bash
### Capture XML
```bash
./onvif-diagnostics \
-endpoint "http://192.168.2.24/onvif/device_service" \
-username "service" \
-password "Service.1234" \
-capture-xml \
-verbose
```
Result:
- `camera-logs/Bosch_FLEXIDOME_panoramic_5100i_9.00.0210_20251110.json`
- `camera-logs/Bosch_FLEXIDOME_panoramic_5100i_9.00.0210_xmlcapture_20251110.tar.gz`
```
### Analyze Response
```bash
tar -xzf camera-logs/Bosch_FLEXIDOME_panoramic_5100i_*_xmlcapture_*.tar.gz
# Look for GetStreamUri operation (easy to find by name)
cat capture_*_GetStreamUri_response.xml
```
Result:
```xml
<SOAP-ENV:Fault>
<SOAP-ENV:Code>
<SOAP-ENV:Subcode>
<SOAP-ENV:Value>ter:IncompleteConfiguration</SOAP-ENV:Value>
</SOAP-ENV:Subcode>
</SOAP-ENV:Code>
<SOAP-ENV:Reason>
<SOAP-ENV:Text>Configuration not complete</SOAP-ENV:Text>
</SOAP-ENV:Reason>
</SOAP-ENV:Fault>
```
### Root Cause
Profile 9 has `VideoEncoderConfiguration: null` in the profiles response. Can't get stream URI for profile without video encoder.
### Solution
Skip GetStreamURI for profiles without VideoEncoderConfiguration:
```go
if profile.VideoEncoderConfiguration == nil {
// Skip - this is audio-only or metadata-only profile
continue
}
```
## Files Created
### SOAP Client Enhancement
- `soap/soap.go` - Added debug logging capability
### Diagnostic Utility Enhancement
- `cmd/onvif-diagnostics/main.go` - Added XML capture functionality with `-capture-xml` flag
## Output Organization
All debugging files are saved to the same `camera-logs/` directory:
```
camera-logs/
├── Bosch_FLEXIDOME_indoor_5100i_IR_8.71.0066_20251107-193656.json # Diagnostic report
├── Bosch_FLEXIDOME_indoor_5100i_IR_8.71.0066_xmlcapture_20251110.tar.gz # XML capture archive
├── AXIS_Q3626-VE_12.6.104_20251108-212157.json
├── AXIS_Q3626-VE_12.6.104_xmlcapture_20251108-213000.tar.gz
└── Bosch_FLEXIDOME_panoramic_5100i_9.00.0210_20251107-195636.json
```
### Archive Contents
Each tar.gz archive contains the captured XML files with descriptive operation names:
```bash
$ tar -tzf camera-logs/Bosch_FLEXIDOME_indoor_5100i_IR_*_xmlcapture_*.tar.gz
capture_001_GetDeviceInformation.json
capture_001_GetDeviceInformation_request.xml
capture_001_GetDeviceInformation_response.xml
capture_002_GetSystemDateAndTime.json
capture_002_GetSystemDateAndTime_request.xml
capture_002_GetSystemDateAndTime_response.xml
capture_003_GetCapabilities.json
capture_003_GetCapabilities_request.xml
capture_003_GetCapabilities_response.xml
...
```
Each file is named with both a sequence number and the SOAP operation name for easy identification.
## Benefits
1. **Complete Visibility**: See exact SOAP XML sent/received
2. **Namespace Debugging**: Identify namespace mismatches
3. **Fault Analysis**: See detailed SOAP fault information
4. **Comparison**: Compare working vs failing cameras
5. **Easy Sharing**: Compressed archives (< 10KB) easy to share via email
6. **Organized**: All camera logs in one directory with consistent naming
7. **Privacy**: Review and sanitize XML before sharing archives
## Next Steps
When you encounter errors in the diagnostic report:
1. ✅ Run `onvif-diagnostics` to identify which operations fail
2. ✅ Re-run with `-capture-xml` flag to capture raw XML
3. ✅ Extract and analyze the tar.gz archive
4. ✅ Share both files (JSON report + tar.gz archive) for debugging assistance
## Command-Line Flags
```
-endpoint string
ONVIF device endpoint (required)
-username string
Username for authentication (required)
-password string
Password for authentication (required)
-output string
Output directory (default: "./camera-logs")
-timeout int
Request timeout in seconds (default: 30)
-verbose
Enable verbose output
-capture-xml
Capture raw SOAP XML traffic and create tar.gz archive
```
## Output Structure
### Before (separate files):
```
xml-captures/
└── 20251110-095000/
├── capture_001.json
├── capture_001_request.xml
├── capture_001_response.xml
└── ...
```
### Now (compressed archives):
```
camera-logs/
├── Bosch_FLEXIDOME_indoor_5100i_IR_8.71.0066_20251107-193656.json
├── Bosch_FLEXIDOME_indoor_5100i_IR_8.71.0066_xmlcapture_20251110-115830.tar.gz (5KB)
├── AXIS_Q3626-VE_12.6.104_20251108-212157.json
└── AXIS_Q3626-VE_12.6.104_xmlcapture_20251110-120000.tar.gz (3KB)
```
## Tips
- Use `-operation` to test specific failing operations
- Check response XML for `<Fault>` elements
- Compare namespace prefixes (tds, trt, tt, etc.)
- Look for XAddr values in capabilities response
- Verify authentication headers in request XML