python-aidot-cameras 1.0.0rc1__tar.gz → 1.0.0rc2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (277) hide show
  1. {python_aidot_cameras-1.0.0rc1/python_aidot_cameras.egg-info → python_aidot_cameras-1.0.0rc2}/PKG-INFO +1 -1
  2. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/sdes_open.py +39 -1
  3. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/pyproject.toml +1 -1
  4. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2/python_aidot_cameras.egg-info}/PKG-INFO +1 -1
  5. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/python_aidot_cameras.egg-info/SOURCES.txt +1 -0
  6. python_aidot_cameras-1.0.0rc2/tests/test_liveplay_echo_timeout.py +67 -0
  7. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/LICENSE +0 -0
  8. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/MANIFEST.in +0 -0
  9. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/README.md +0 -0
  10. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/__init__.py +0 -0
  11. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/__main__.py +0 -0
  12. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_upstream.py +0 -0
  13. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/__init__.py +0 -0
  14. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/LICENSE +0 -0
  15. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/__init__.py +0 -0
  16. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/clock.py +0 -0
  17. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/codecs/__init__.py +0 -0
  18. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/codecs/base.py +0 -0
  19. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/codecs/g711.py +0 -0
  20. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/codecs/g722.py +0 -0
  21. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/codecs/h264.py +0 -0
  22. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/codecs/opus.py +0 -0
  23. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/codecs/vpx.py +0 -0
  24. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/contrib/__init__.py +0 -0
  25. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/contrib/media.py +0 -0
  26. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/contrib/signaling.py +0 -0
  27. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/events.py +0 -0
  28. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/exceptions.py +0 -0
  29. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/jitterbuffer.py +0 -0
  30. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/mediastreams.py +0 -0
  31. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rate.py +0 -0
  32. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rtcconfiguration.py +0 -0
  33. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rtcdatachannel.py +0 -0
  34. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rtcdtlstransport.py +0 -0
  35. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rtcicetransport.py +0 -0
  36. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rtcpeerconnection.py +0 -0
  37. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rtcrtpparameters.py +0 -0
  38. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rtcrtpreceiver.py +0 -0
  39. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rtcrtpsender.py +0 -0
  40. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rtcrtptransceiver.py +0 -0
  41. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rtcsctptransport.py +0 -0
  42. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rtcsessiondescription.py +0 -0
  43. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/rtp.py +0 -0
  44. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/sdp.py +0 -0
  45. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/stats.py +0 -0
  46. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/_vendor/aiortc/utils.py +0 -0
  47. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/ble_gateway.py +0 -0
  48. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/__init__.py +0 -0
  49. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/client.py +0 -0
  50. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/constants.py +0 -0
  51. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/controls.py +0 -0
  52. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/go2rtc.py +0 -0
  53. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/hwaccel.py +0 -0
  54. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/lan_control.py +0 -0
  55. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/models.py +0 -0
  56. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/playback.py +0 -0
  57. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/protocol.py +0 -0
  58. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/sd_events.py +0 -0
  59. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/sd_listing.py +0 -0
  60. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/sd_playback.py +0 -0
  61. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/sdes.py +0 -0
  62. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/tutk.py +0 -0
  63. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/webrtc.py +0 -0
  64. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/camera/webrtc_open.py +0 -0
  65. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/client.py +0 -0
  66. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/cloud_auth.py +0 -0
  67. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/const.py +0 -0
  68. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/credentials.py +0 -0
  69. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/crypto.py +0 -0
  70. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/device_client.py +0 -0
  71. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/discover.py +0 -0
  72. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/exceptions.py +0 -0
  73. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/g711.py +0 -0
  74. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/lan_retry.py +0 -0
  75. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/aidot_cameras/py.typed +0 -0
  76. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/python_aidot_cameras.egg-info/dependency_links.txt +0 -0
  77. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/python_aidot_cameras.egg-info/entry_points.txt +0 -0
  78. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/python_aidot_cameras.egg-info/requires.txt +0 -0
  79. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/python_aidot_cameras.egg-info/top_level.txt +0 -0
  80. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/setup.cfg +0 -0
  81. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_aioice_compat.py +0 -0
  82. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_alarm_event.py +0 -0
  83. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_answer_pt_kinds.py +0 -0
  84. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_answer_sdp_video_pt.py +0 -0
  85. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_answer_section_selection.py +0 -0
  86. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_audio_mux_offline.py +0 -0
  87. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_avio_ctrl_uses_the_session_dseq.py +0 -0
  88. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_avio_request.py +0 -0
  89. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_avio_response_parse.py +0 -0
  90. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_avio_response_router.py +0 -0
  91. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_backoff.py +0 -0
  92. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_battery_detection.py +0 -0
  93. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_battery_evidence_corroboration.py +0 -0
  94. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_battery_skip_turn.py +0 -0
  95. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_bitrate_campaign_arms.py +0 -0
  96. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_ble_gateway.py +0 -0
  97. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_bridge_state_sentinels.py +0 -0
  98. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_busy_backoff.py +0 -0
  99. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_canary_log_names_the_camera.py +0 -0
  100. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_cloud_count.py +0 -0
  101. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_cloud_plan.py +0 -0
  102. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_constants_imports_resolve.py +0 -0
  103. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_control_verdicts.py +0 -0
  104. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_deferred_hardening.py +0 -0
  105. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_device_cmd_seq_match.py +0 -0
  106. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_device_login_guard.py +0 -0
  107. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_device_user_info_cache.py +0 -0
  108. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_direct_ts_serve.py +0 -0
  109. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_dormant_camera_cleanup.py +0 -0
  110. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_drain_is_cancellable.py +0 -0
  111. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_dtls_mux_terminal_write.py +0 -0
  112. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_dtls_not_ready_burst.py +0 -0
  113. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_dtls_pinning.py +0 -0
  114. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_dtls_resolution_ack.py +0 -0
  115. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_dtls_serve_decode_skip.py +0 -0
  116. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_dtls_serve_ice_wait.py +0 -0
  117. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_dtls_serve_open_timeout.py +0 -0
  118. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_dtls_skip_signaling_wait.py +0 -0
  119. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_dtls_slow_probe.py +0 -0
  120. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_dtls_stdout_producer.py +0 -0
  121. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_dtls_video_presence.py +0 -0
  122. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_egress_guard.py +0 -0
  123. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_env_seams.py +0 -0
  124. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_feature_probe_needs_a_live_session.py +0 -0
  125. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_ffmpeg_signal_exit_is_not_a_crash.py +0 -0
  126. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_futile_keepalive.py +0 -0
  127. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_gate_requires_a_decoded_frame.py +0 -0
  128. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_go2rtc.py +0 -0
  129. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_go2rtc_cli.py +0 -0
  130. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_h264_decode_rate_limit.py +0 -0
  131. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_highport_nomination.py +0 -0
  132. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_hwaccel_probe.py +0 -0
  133. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_ice_config_cache.py +0 -0
  134. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_ice_peer_reflexive.py +0 -0
  135. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_idle_release_both_loops.py +0 -0
  136. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_keepalive_renew.py +0 -0
  137. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_key_restart_sdp.py +0 -0
  138. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_keyframe_prompter.py +0 -0
  139. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_lan_control.py +0 -0
  140. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_lan_retry_reaches_the_storming_devices.py +0 -0
  141. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_late_repeats_are_dropped.py +0 -0
  142. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_light_active_color_mode.py +0 -0
  143. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_live_session_carries_talk.py +0 -0
  144. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_live_stream_param.py +0 -0
  145. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_live_validate_policy.py +0 -0
  146. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_live_video_canary.py +0 -0
  147. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_local_only_controls.py +0 -0
  148. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_logging_caps.py +0 -0
  149. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_login_connect_deadline.py +0 -0
  150. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_login_reconnect_backoff.py +0 -0
  151. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_media_counted_only_when_plaintext.py +0 -0
  152. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_media_path_is_reported.py +0 -0
  153. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_media_socket_rcvbuf.py +0 -0
  154. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_media_wait_floor.py +0 -0
  155. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_motion_poll.py +0 -0
  156. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_mqtt_client_id_is_exact.py +0 -0
  157. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_mqtt_credential_refetch.py +0 -0
  158. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_mqtt_credential_self_heal.py +0 -0
  159. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_mqtt_password_not_persisted.py +0 -0
  160. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_mqtt_session_reconnect.py +0 -0
  161. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_mqtt_thread_not_orphaned.py +0 -0
  162. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_nack.py +0 -0
  163. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_nack_cannot_add_load_in_a_burst.py +0 -0
  164. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_narrow_pc_ice.py +0 -0
  165. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_no_key_material_in_logs.py +0 -0
  166. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_no_self_referential_go2rtc.py +0 -0
  167. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_no_undefined_names.py +0 -0
  168. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_offer_bandwidth_line.py +0 -0
  169. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_offer_keeps_rtcp_feedback.py +0 -0
  170. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_offline_keepalive_pause.py +0 -0
  171. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_on_frame_is_an_av_frame.py +0 -0
  172. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_open_fail_logger.py +0 -0
  173. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_open_gate_delay.py +0 -0
  174. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_peer_id_client_type.py +0 -0
  175. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_peerid_reuse.py +0 -0
  176. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_persistent_mqtt.py +0 -0
  177. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_persistent_mqtt_robustness.py +0 -0
  178. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_playback_tls.py +0 -0
  179. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_post_merge_hardening.py +0 -0
  180. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_ptz_probe_reads_what_it_is_told.py +0 -0
  181. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_public_signature_matches_impl.py +0 -0
  182. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_quality_campaign_in_session.py +0 -0
  183. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_recent_recordings.py +0 -0
  184. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_remb.py +0 -0
  185. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_remb_goes_out_the_relay_aware_sender.py +0 -0
  186. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_resent_frames_are_dropped.py +0 -0
  187. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_resolution_persists.py +0 -0
  188. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_restart_cycle.py +0 -0
  189. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_retry_policy.py +0 -0
  190. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_scripts_importable.py +0 -0
  191. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sctp_init_ack_tsn.py +0 -0
  192. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sctp_reassembly.py +0 -0
  193. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sctp_sack.py +0 -0
  194. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sd_card_presence.py +0 -0
  195. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sd_event_decode.py +0 -0
  196. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sd_event_probe_payloads.py +0 -0
  197. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sd_listing.py +0 -0
  198. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sd_playback.py +0 -0
  199. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_adaptive.py +0 -0
  200. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_avio_dispatch.py +0 -0
  201. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_bridge_break_gate.py +0 -0
  202. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_connection_mode.py +0 -0
  203. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_echo_wait_timeout.py +0 -0
  204. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_fast_liveplay.py +0 -0
  205. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_ffmpeg_stderr_log.py +0 -0
  206. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_first_media_stall_report.py +0 -0
  207. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_ice_teardown.py +0 -0
  208. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_idle_release.py +0 -0
  209. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_nack_bridge.py +0 -0
  210. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_offer_video_order.py +0 -0
  211. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_offer_video_pin.py +0 -0
  212. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_open_cleanup.py +0 -0
  213. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_sctp_abort.py +0 -0
  214. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_serve_audio.py +0 -0
  215. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_serve_cmd.py +0 -0
  216. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_serve_stderr_drain.py +0 -0
  217. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_session_cap.py +0 -0
  218. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_sprop.py +0 -0
  219. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_talk.py +0 -0
  220. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_teardown_exit_log.py +0 -0
  221. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_terminal_ack.py +0 -0
  222. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_terminal_ack_latency.py +0 -0
  223. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_tmmbr_bridge.py +0 -0
  224. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdes_watchdog.py +0 -0
  225. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdp_narrowing_properties.py +0 -0
  226. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sdp_payload_type_narrowing.py +0 -0
  227. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_security_hardening.py +0 -0
  228. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_self_peer_is_an_address_not_an_ip.py +0 -0
  229. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_serializable_login_info.py +0 -0
  230. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_serve_input_timeout.py +0 -0
  231. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_serve_loss_tolerance.py +0 -0
  232. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_serve_pt_respects_the_pin.py +0 -0
  233. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_serve_relay.py +0 -0
  234. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_serve_stderr_keeps_the_reason.py +0 -0
  235. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_session_stats.py +0 -0
  236. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_shared_house_seam.py +0 -0
  237. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_snapshot_cancellation.py +0 -0
  238. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_speak.py +0 -0
  239. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sprop_capture_gate.py +0 -0
  240. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sprop_staleness.py +0 -0
  241. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sprop_unstable_public.py +0 -0
  242. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_sprop_write_is_reported_truthfully.py +0 -0
  243. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_srtp_rx_rekey.py +0 -0
  244. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_srtp_tx_key_note.py +0 -0
  245. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_stable_terminal_id.py +0 -0
  246. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_stall_nudge_policy.py +0 -0
  247. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_stall_report_says_what_the_answer_carried.py +0 -0
  248. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_stall_report_says_whether_the_trigger_was_answered.py +0 -0
  249. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_stall_report_separates_silence_from_undecryptable.py +0 -0
  250. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_stall_report_survives_a_caller_giving_up.py +0 -0
  251. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_stall_reports_reach_the_artifact.py +0 -0
  252. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_stream_cap.py +0 -0
  253. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_stream_drain_ownership.py +0 -0
  254. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_stream_idle.py +0 -0
  255. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_stream_slot_cap.py +0 -0
  256. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_stream_teardown.py +0 -0
  257. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_talk.py +0 -0
  258. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_talk_reports_a_speaker_that_never_opened.py +0 -0
  259. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_tap_to_mux_end_to_end.py +0 -0
  260. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_terminal_ack.py +0 -0
  261. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_tmmbr.py +0 -0
  262. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_token_file_robustness.py +0 -0
  263. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_token_refresh.py +0 -0
  264. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_turn_create_permission.py +0 -0
  265. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_tutk_path_is_out_of_reach.py +0 -0
  266. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_upstream_compat.py +0 -0
  267. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_validator_shares_one_token.py +0 -0
  268. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_video_profile_log.py +0 -0
  269. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_video_pts_dts.py +0 -0
  270. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_video_ts_unwrap.py +0 -0
  271. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_viewer_check_throttle.py +0 -0
  272. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_viewer_presence.py +0 -0
  273. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_viewer_present_push_mode.py +0 -0
  274. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_wait_or_event.py +0 -0
  275. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_wake_gate_camera_evidence.py +0 -0
  276. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_wake_readiness_retry.py +0 -0
  277. {python_aidot_cameras-1.0.0rc1 → python_aidot_cameras-1.0.0rc2}/tests/test_webrtc_answer_race.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-aidot-cameras
3
- Version: 1.0.0rc1
3
+ Version: 1.0.0rc2
4
4
  Summary: Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)
5
5
  Author-email: cbrightly <chris.brightly@gmail.com>
6
6
  License-Expression: MIT
@@ -615,6 +615,44 @@ def _sdes_tmmbr_after_s() -> float:
615
615
  EXPT_CAP_FILE = _os.environ.get("AIDOT_EXPT_CAP_FILE")
616
616
 
617
617
 
618
+ #: How long to wait for the broker to echo our own livePlayReq back before
619
+ #: proceeding. Was 5.0 s (1.5 s with fast-liveplay), and it is pure latency:
620
+ #: across 22 h of one deployment the wait ran 169 times and timed out 169 times,
621
+ #: never once ending early, and not a single inbound `livePlayReq` was seen among
622
+ #: 5000+ messages the cameras and broker did send. The success branch has never
623
+ #: executed. On timeout the code proceeds anyway, so the wait has never changed
624
+ #: behaviour - only delayed it, by 44% of a measured 11.4 s time-to-first-frame
625
+ #: on an A001064.
626
+ #:
627
+ #: Kept rather than deleted, and still honoured, because a broker or firmware
628
+ #: that does echo should still short-circuit the wait; only the price of its
629
+ #: absence changes. Override with AIDOT_SDES_LIVEPLAY_ECHO_S (seconds, 0
630
+ #: disables the wait entirely) to measure it against the old value.
631
+ _LIVEPLAY_ECHO_S = 0.25
632
+ #: Fast-liveplay models keep the 1.5 s they were given: that value came out
633
+ #: of its own 3 h live soak, and nothing here measured it. The 169/169
634
+ #: evidence below is for the 5.0 s non-fast wait only, so only that one
635
+ #: moves.
636
+ _LIVEPLAY_ECHO_S_FAST = 1.5
637
+
638
+
639
+ def _sdes_liveplay_echo_timeout(fast_liveplay: bool) -> float:
640
+ """Seconds to wait for the livePlayReq echo. Never negative.
641
+
642
+ A malformed env value is ignored rather than raising: this runs on every
643
+ open, and an unparseable knob must not be able to stop a camera streaming.
644
+ """
645
+ raw = _os.environ.get("AIDOT_SDES_LIVEPLAY_ECHO_S")
646
+ if raw is not None:
647
+ try:
648
+ val = float(raw)
649
+ except (TypeError, ValueError):
650
+ val = None
651
+ if val is not None and val >= 0.0:
652
+ return val
653
+ return _LIVEPLAY_ECHO_S_FAST if fast_liveplay else _LIVEPLAY_ECHO_S
654
+
655
+
618
656
  def _sdes_max_session_s(device_id: str, path: "Optional[str]" = None) -> float:
619
657
  """Seconds of media after which to end THIS device's session. 0 = off.
620
658
 
@@ -2559,7 +2597,7 @@ class _SdesOpenMixin:
2559
2597
  # (_NO_FAST_LIVEPLAY_MODELS, e.g. A001064) are always excluded; disable
2560
2598
  # elsewhere via AIDOT_SDES_FAST_LIVEPLAY={0,false,no,off}.
2561
2599
  _skip_lp = self._resolve_sdes_fast_liveplay()
2562
- _echo_timeout = 1.5 if _skip_lp else 5.0
2600
+ _echo_timeout = _sdes_liveplay_echo_timeout(_skip_lp)
2563
2601
  _echo_t0 = time.monotonic()
2564
2602
  try:
2565
2603
  await _asyncio.wait_for(liveplay_echo_ev.wait(), timeout=_echo_timeout)
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "python-aidot-cameras"
7
- version = "1.0.0rc1"
7
+ version = "1.0.0rc2"
8
8
  description = "Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: python-aidot-cameras
3
- Version: 1.0.0rc1
3
+ Version: 1.0.0rc2
4
4
  Summary: Control AiDot/Leedarson WiFi lights and cameras (WebRTC streaming, two-way audio, PTZ, controls)
5
5
  Author-email: cbrightly <chris.brightly@gmail.com>
6
6
  License-Expression: MIT
@@ -141,6 +141,7 @@ tests/test_live_session_carries_talk.py
141
141
  tests/test_live_stream_param.py
142
142
  tests/test_live_validate_policy.py
143
143
  tests/test_live_video_canary.py
144
+ tests/test_liveplay_echo_timeout.py
144
145
  tests/test_local_only_controls.py
145
146
  tests/test_logging_caps.py
146
147
  tests/test_login_connect_deadline.py
@@ -0,0 +1,67 @@
1
+ """The livePlayReq-echo wait is latency, and this pins its price.
2
+
3
+ The broker echoing our own livePlayReq back is what this wait is for. Across
4
+ 22 h of one deployment it ran 169 times and timed out 169 times - never once
5
+ ending early - and not one inbound `livePlayReq` appeared among the 5000+
6
+ messages the cameras and broker did send. The success branch has never
7
+ executed, and on timeout the open proceeds anyway, so the wait has never
8
+ changed behaviour: only delayed it, by 44% of a measured 11.4 s
9
+ time-to-first-frame on an A001064.
10
+
11
+ The wait is kept so a broker that does echo still short-circuits it. Only the
12
+ price of its absence changed, from 5.0 s to 0.25 s, on the non-fast
13
+ path only.
14
+ """
15
+ import pytest
16
+
17
+ from aidot_cameras.camera.sdes_open import (
18
+ _LIVEPLAY_ECHO_S,
19
+ _LIVEPLAY_ECHO_S_FAST,
20
+ _sdes_liveplay_echo_timeout,
21
+ )
22
+
23
+
24
+ class TestTheDefault:
25
+ def test_only_the_non_fast_path_moves(self, monkeypatch):
26
+ monkeypatch.delenv("AIDOT_SDES_LIVEPLAY_ECHO_S", raising=False)
27
+ assert _sdes_liveplay_echo_timeout(False) == _LIVEPLAY_ECHO_S == 0.25
28
+ # The fast-liveplay models are deliberately NOT changed: their 1.5 s
29
+ # came out of its own live soak and no measurement here touched it.
30
+ assert _sdes_liveplay_echo_timeout(True) == _LIVEPLAY_ECHO_S_FAST == 1.5
31
+
32
+ def test_it_is_far_below_the_old_five_seconds(self, monkeypatch):
33
+ """The regression this guards: quietly restoring a multi-second wait for
34
+ a message this fleet has never once received."""
35
+ monkeypatch.delenv("AIDOT_SDES_LIVEPLAY_ECHO_S", raising=False)
36
+ assert _sdes_liveplay_echo_timeout(False) <= 0.5
37
+
38
+
39
+ class TestTheOverride:
40
+ @pytest.mark.parametrize("raw,expected", [("5.0", 5.0), ("0", 0.0),
41
+ ("1.5", 1.5), ("0.1", 0.1)])
42
+ def test_a_valid_value_is_honoured(self, monkeypatch, raw, expected):
43
+ """The old behaviour has to remain reachable, or the change cannot be
44
+ measured against it."""
45
+ monkeypatch.setenv("AIDOT_SDES_LIVEPLAY_ECHO_S", raw)
46
+ assert _sdes_liveplay_echo_timeout(False) == expected
47
+
48
+ @pytest.mark.parametrize("raw", ["", " ", "abc", "-1", "-0.5", "1,5", "None"])
49
+ def test_a_bad_value_falls_back_instead_of_raising(self, monkeypatch, raw):
50
+ """This runs on every open. An unparseable knob must not be able to stop
51
+ a camera streaming."""
52
+ monkeypatch.setenv("AIDOT_SDES_LIVEPLAY_ECHO_S", raw)
53
+ assert _sdes_liveplay_echo_timeout(False) == _LIVEPLAY_ECHO_S
54
+
55
+ def test_zero_disables_the_wait_entirely(self, monkeypatch):
56
+ monkeypatch.setenv("AIDOT_SDES_LIVEPLAY_ECHO_S", "0")
57
+ assert _sdes_liveplay_echo_timeout(True) == 0.0
58
+
59
+
60
+ class TestItIsWiredIn:
61
+ def test_the_open_path_uses_the_resolver_not_a_literal(self):
62
+ import inspect
63
+ from aidot_cameras.camera import sdes_open
64
+ src = inspect.getsource(sdes_open)
65
+ assert "_echo_timeout = _sdes_liveplay_echo_timeout(" in src, (
66
+ "the echo wait is back to a hardcoded timeout")
67
+ assert "_echo_timeout = 1.5 if" not in src