Skip to content

Conversation

bdraco
Copy link
Member

@bdraco bdraco commented Aug 20, 2025

Summary

This PR adds resilience against ONVIF cameras that improperly close HTTP connections without notification. Some cameras close the TCP connection after each response without sending a Connection: close header, causing ServerDisconnectedError when the client attempts to reuse the connection. This particularly affects Thingino firmware cameras and similar devices with non-compliant HTTP implementations.

Problem

  • Some ONVIF cameras close the TCP connection after each response without sending Connection: close header
  • This violates HTTP/1.1 best practices - servers should indicate connection closure with proper headers
  • When the client tries to reuse the connection for the next request, aiohttp raises ServerDisconnectedError
  • The existing @retry_connection_error decorator wasn't being applied to the post_xml() method that zeep uses for SOAP calls
  • This caused Home Assistant's ONVIF integration to fail with "Server disconnected" errors

Solution

  1. Added retry decorator to post_xml() method: The AsyncTransportProtocolErrorHandler class now wraps post_xml() with the retry decorator, matching the existing post() and get() methods

  2. Made backoff configurable: Added an optional backoff parameter to the retry_connection_error decorator to allow immediate retries for connection errors

  3. Set zero backoff for ServerDisconnectedError: Since this is just a closed connection (not a server issue), we can immediately retry without any delay

Changes

  • onvif/client.py: Added @retry_connection_error decorator to post_xml() method with 0 backoff
  • onvif/wrappers.py: Made backoff time configurable in the retry decorator

Testing

  • Verified the retry mechanism is triggered when ServerDisconnectedError occurs
  • Confirmed successful retry on second attempt with cameras that close connections
  • No impact on cameras that keep connections alive

Related Issues

Backward Compatibility

This change is fully backward compatible. It only adds retry logic for a specific error condition and doesn't change any existing behavior for working cameras.

Copy link

codecov bot commented Aug 20, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.

Files with missing lines Coverage Δ
onvif/client.py 67.28% <100.00%> (+0.79%) ⬆️
onvif/wrappers.py 100.00% <100.00%> (+34.78%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@bdraco bdraco marked this pull request as ready for review August 20, 2025 22:53
@bdraco bdraco merged commit 64c9311 into async Aug 20, 2025
6 checks passed
@bdraco bdraco deleted the server_disconnected branch August 20, 2025 22:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ONVIF don’t work after 2025.8.2 update with Xiaomi 2K camera using custom Thingino firmware
1 participant